web/preferences: add option to change window title

Fixes #564
This commit is contained in:
Tulir Asokan 2024-12-23 13:25:35 +02:00
parent 266116f237
commit 4c8497e5d9
6 changed files with 29 additions and 7 deletions

View file

@ -76,7 +76,7 @@ export class StateStore {
readonly accountData: Map<string, UnknownEventContent> = new Map() readonly accountData: Map<string, UnknownEventContent> = new Map()
readonly accountDataSubs = new MultiSubscribable() readonly accountDataSubs = new MultiSubscribable()
readonly emojiRoomsSub = new Subscribable() readonly emojiRoomsSub = new Subscribable()
readonly preferences: Preferences = getPreferenceProxy(this) readonly preferences = getPreferenceProxy(this)
#frequentlyUsedEmoji: Map<string, number> | null = null #frequentlyUsedEmoji: Map<string, number> | null = null
#emojiPackKeys: RoomStateGUID[] | null = null #emojiPackKeys: RoomStateGUID[] | null = null
#watchedRoomEmojiPacks: Record<string, CustomEmojiPack> | null = null #watchedRoomEmojiPacks: Record<string, CustomEmojiPack> | null = null

View file

@ -112,7 +112,7 @@ export class RoomStateStore {
readonly accountDataSubs = new MultiSubscribable() readonly accountDataSubs = new MultiSubscribable()
readonly openNotifications: Map<EventRowID, Notification> = new Map() readonly openNotifications: Map<EventRowID, Notification> = new Map()
readonly #emojiPacksCache: Map<string, CustomEmojiPack | null> = new Map() readonly #emojiPacksCache: Map<string, CustomEmojiPack | null> = new Map()
readonly preferences: Preferences readonly preferences: Required<Preferences>
readonly localPreferenceCache: Preferences readonly localPreferenceCache: Preferences
readonly preferenceSub = new NoDataSubscribable() readonly preferenceSub = new NoDataSubscribable()
serverPreferenceCache: Preferences = {} serverPreferenceCache: Preferences = {}

View file

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import type { ContentURI } from "../../types" import type { ContentURI } from "../../types"
import { Preference, anyContext } from "./types.ts" import { Preference, anyContext, anyGlobalContext } from "./types.ts"
export const codeBlockStyles = [ export const codeBlockStyles = [
"auto", "abap", "algol_nu", "algol", "arduino", "autumn", "average", "base16-snazzy", "borland", "bw", "auto", "abap", "algol_nu", "algol", "arduino", "autumn", "average", "base16-snazzy", "borland", "bw",
@ -171,6 +171,18 @@ export const preferences = {
allowedContexts: anyContext, allowedContexts: anyContext,
defaultValue: "", defaultValue: "",
}), }),
room_window_title: new Preference<string>({
displayName: "In-room window title",
description: "The title to use for the window when viewing a room. $room will be replaced with the room name",
allowedContexts: anyContext,
defaultValue: "$room - gomuks web",
}),
window_title: new Preference<string>({
displayName: "Default window title",
description: "The title to use for the window when not in a room.",
allowedContexts: anyGlobalContext,
defaultValue: "gomuks web",
}),
} as const } as const
export const existingPreferenceKeys = new Set(Object.keys(preferences)) export const existingPreferenceKeys = new Set(Object.keys(preferences))

View file

@ -19,7 +19,7 @@ import { PreferenceContext, PreferenceValueType } from "./types.ts"
const prefKeys = Object.keys(preferences) const prefKeys = Object.keys(preferences)
export function getPreferenceProxy(store: StateStore, room?: RoomStateStore): Preferences { export function getPreferenceProxy(store: StateStore, room?: RoomStateStore): Required<Preferences> {
return new Proxy({}, { return new Proxy({}, {
set(): boolean { set(): boolean {
throw new Error("The preference proxy is read-only") throw new Error("The preference proxy is read-only")
@ -61,5 +61,5 @@ export function getPreferenceProxy(store: StateStore, room?: RoomStateStore): Pr
writable: false, writable: false,
} : undefined } : undefined
}, },
}) }) as Required<Preferences>
} }

View file

@ -124,6 +124,13 @@ class ContextFields implements MainScreenContextFields {
} }
} }
#getWindowTitle(room?: RoomStateStore, name?: string) {
if (!room) {
return this.client.store.preferences.window_title
}
return room.preferences.room_window_title.replace("$room", name!)
}
#setActiveRoom(room: RoomStateStore, pushState: boolean) { #setActiveRoom(room: RoomStateStore, pushState: boolean) {
window.activeRoom = room window.activeRoom = room
this.directSetActiveRoom(room) this.directSetActiveRoom(room)
@ -147,7 +154,7 @@ class ContextFields implements MainScreenContextFields {
if (roomNameForTitle && roomNameForTitle.length > 48) { if (roomNameForTitle && roomNameForTitle.length > 48) {
roomNameForTitle = roomNameForTitle.slice(0, 45) + "…" roomNameForTitle = roomNameForTitle.slice(0, 45) + "…"
} }
document.title = `${roomNameForTitle} - gomuks web` document.title = this.#getWindowTitle(room, roomNameForTitle)
} }
#closeActiveRoom(pushState: boolean) { #closeActiveRoom(pushState: boolean) {
@ -161,7 +168,7 @@ class ContextFields implements MainScreenContextFields {
if (pushState) { if (pushState) {
history.pushState({}, "") history.pushState({}, "")
} }
document.title = "gomuks web" document.title = this.#getWindowTitle()
} }
clickRoom = (evt: React.MouseEvent) => { clickRoom = (evt: React.MouseEvent) => {

View file

@ -110,6 +110,9 @@ const PreferenceRow = ({
val: PreferenceValueType | undefined, val: PreferenceValueType | undefined,
inheritedVal: PreferenceValueType, inheritedVal: PreferenceValueType,
) => { ) => {
if (!pref.allowedContexts.includes(context)) {
return null
}
if (prefType === "boolean") { if (prefType === "boolean") {
return <BooleanPreferenceCell return <BooleanPreferenceCell
name={name} name={name}