This commit is contained in:
Timothy Jaeryang Baek committed 2026-08-10 19:16:21 -06:00
1 parent ec03e88144
commit 72a909fd2f
6 files changed
+129 -32

No files matched your search

+6 -1
View File
@@ -469,9 +469,14 @@ async def get_default_user_permissions_defaults(user=Depends(get_admin_user)):
@router.get('/user/settings', response_model=UserSettings | None) @router.get('/user/settings', response_model=UserSettings | None)
async def get_user_settings_by_session_user( async def get_user_settings_by_session_user(
user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) raw: bool = False,
user=Depends(get_verified_user),
db: AsyncSession = Depends(get_async_session),
): ):
# user already fetched by get_verified_user — no need to refetch # user already fetched by get_verified_user — no need to refetch
if raw:
return user.settings
default_interface_settings = await Config.get('ui.default_interface_settings') default_interface_settings = await Config.get('ui.default_interface_settings')
if not isinstance(default_interface_settings, dict) or not default_interface_settings: if not isinstance(default_interface_settings, dict) or not default_interface_settings:
return user.settings return user.settings
+2 -2
View File
@@ -271,9 +271,9 @@ export const getAllUsers = async (token: string) => {
return res; return res;
}; };
export const getUserSettings = async (token: string) => { export const getUserSettings = async (token: string, raw = false) => {
let error = null; let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/users/user/settings`, { const res = await fetch(`${WEBUI_API_BASE_URL}/users/user/settings${raw ? '?raw=true' : ''}`, {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -6,6 +6,7 @@
const i18n: any = getContext('i18n'); const i18n: any = getContext('i18n');
export let saveSettings: Function; export let saveSettings: Function;
export let personalSettingsValue: Record<string, any> = {};
let interfaceSettings: any; let interfaceSettings: any;
</script> </script>
@@ -21,7 +22,7 @@
<h2 class="text-sm font-medium text-gray-900 dark:text-white mb-4">{$i18n.t('Interface')}</h2> <h2 class="text-sm font-medium text-gray-900 dark:text-white mb-4">{$i18n.t('Interface')}</h2>
<div class="flex-1 min-h-0 overflow-y-auto scrollbar-hover pr-1.5"> <div class="flex-1 min-h-0 overflow-y-auto scrollbar-hover pr-1.5">
<InterfaceSettings bind:this={interfaceSettings} {saveSettings} /> <InterfaceSettings bind:this={interfaceSettings} {saveSettings} {personalSettingsValue} />
</div> </div>
<div class="shrink-0 flex justify-end text-sm font-normal"> <div class="shrink-0 flex justify-end text-sm font-normal">
+22 -2
View File
@@ -5,7 +5,7 @@
import { toast } from 'svelte-sonner'; import { toast } from 'svelte-sonner';
import { config, models, settings, user } from '$lib/stores'; import { config, models, settings, user } from '$lib/stores';
import type { SettingsModalRequest } from '$lib/stores'; import type { SettingsModalRequest } from '$lib/stores';
import { updateUserSettings } from '$lib/apis/users'; import { getUserSettings, updateUserSettings } from '$lib/apis/users';
import { getBackendConfig, getModels as _getModels } from '$lib/apis'; import { getBackendConfig, getModels as _getModels } from '$lib/apis';
import Modal from '../common/Modal.svelte'; import Modal from '../common/Modal.svelte';
@@ -61,6 +61,18 @@
let modalShow = false; let modalShow = false;
let lastShow: boolean | string | SettingsModalRequest = false; let lastShow: boolean | string | SettingsModalRequest = false;
let tabState: Record<string, unknown> | null = null; let tabState: Record<string, unknown> | null = null;
let personalUiSettings: Record<string, any> = {};
const loadPersonalUiSettings = async () => {
const userSettings = await getUserSettings(localStorage.token, true).catch((error) => {
console.error(error);
return null;
});
personalUiSettings =
userSettings?.ui && typeof userSettings.ui === 'object' && !Array.isArray(userSettings.ui)
? userSettings.ui
: {};
};
$: if (show !== lastShow) { $: if (show !== lastShow) {
lastShow = show; lastShow = show;
@@ -70,13 +82,18 @@
show = true; show = true;
lastShow = true; lastShow = true;
modalShow = true; modalShow = true;
loadPersonalUiSettings();
} else if (typeof show === 'string') { } else if (typeof show === 'string') {
selectedTab = show; selectedTab = show;
show = true; show = true;
lastShow = true; lastShow = true;
modalShow = true; modalShow = true;
loadPersonalUiSettings();
} else { } else {
modalShow = show; modalShow = show;
if (show) {
loadPersonalUiSettings();
}
if (!show) { if (!show) {
selectedTab = 'general'; selectedTab = 'general';
tabState = null; tabState = null;
@@ -818,7 +835,9 @@
console.log(updated); console.log(updated);
await settings.set({ ...$settings, ...updated }); await settings.set({ ...$settings, ...updated });
await models.set(await getModels()); await models.set(await getModels());
await updateUserSettings(localStorage.token, { ui: $settings }); const saved = await updateUserSettings(localStorage.token, { ui: $settings });
personalUiSettings =
saved?.ui && typeof saved.ui === 'object' && !Array.isArray(saved.ui) ? saved.ui : {};
}; };
const getModels = async () => { const getModels = async () => {
@@ -1169,6 +1188,7 @@
{:else if selectedTab === 'interface'} {:else if selectedTab === 'interface'}
<Interface <Interface
{saveSettings} {saveSettings}
personalSettingsValue={personalUiSettings}
on:save={() => { on:save={() => {
toast.success($i18n.t('Settings saved successfully!')); toast.success($i18n.t('Settings saved successfully!'));
}} }}
@@ -16,6 +16,7 @@
export let saveSettings: Function; export let saveSettings: Function;
export let settingsValue: Record<string, any> | null = null; export let settingsValue: Record<string, any> | null = null;
export let personalSettingsValue: Record<string, any> = {};
$: currentSettings = (settingsValue ?? $settings ?? {}) as Record<string, any>; $: currentSettings = (settingsValue ?? $settings ?? {}) as Record<string, any>;
$: externalSettings = settingsValue !== null; $: externalSettings = settingsValue !== null;
@@ -118,10 +119,29 @@
const actionButtonClass = const actionButtonClass =
'text-xs text-gray-500 transition-colors hover:text-gray-900 dark:text-gray-500 dark:hover:text-white'; 'text-xs text-gray-500 transition-colors hover:text-gray-900 dark:text-gray-500 dark:hover:text-white';
const matchesDefaultSetting = (key: string, value: unknown) => const hasSettingPath = (source: Record<string, any>, path: string) => {
!externalSettings && let current: any = source;
Object.prototype.hasOwnProperty.call(defaultSettings, key) && for (const part of path.split('.')) {
JSON.stringify(defaultSettings[key]) === JSON.stringify(value); if (!current || typeof current !== 'object' || !Object.prototype.hasOwnProperty.call(current, part)) {
return false;
}
current = current[part];
}
return true;
};
const settingPathByState: Record<string, string> = {
titleAutoGenerate: 'title.auto'
};
const isDefaultSetting = (stateKey: string) => {
const path = settingPathByState[stateKey] ?? stateKey;
return (
!externalSettings &&
hasSettingPath(defaultSettings, path) &&
!hasSettingPath(personalSettingsValue, path)
);
};
const toggleLandingPageMode = async () => { const toggleLandingPageMode = async () => {
landingPageMode = landingPageMode === '' ? 'chat' : ''; landingPageMode = landingPageMode === '' ? 'chat' : '';
@@ -315,7 +335,7 @@
lastSettingsValue = settingsValue; lastSettingsValue = settingsValue;
init(); init();
} }
$: textScaleUsesDefault = textScale === null || matchesDefaultSetting('textScale', textScale); $: textScaleUsesDefault = textScale === null || isDefaultSetting('textScale');
onMount(async () => { onMount(async () => {
init(); init();
@@ -463,6 +483,7 @@
ariaLabelledbyId="high-contrast-mode-label" ariaLabelledbyId="high-contrast-mode-label"
tooltip={true} tooltip={true}
bind:state={highContrastMode} bind:state={highContrastMode}
inherited={isDefaultSetting('highContrastMode')}
on:change={() => { on:change={() => {
saveSettings({ highContrastMode }); saveSettings({ highContrastMode });
}} }}
@@ -485,6 +506,7 @@
ariaLabelledbyId="use-chat-title-as-tab-title-label" ariaLabelledbyId="use-chat-title-as-tab-title-label"
tooltip={true} tooltip={true}
bind:state={showChatTitleInTab} bind:state={showChatTitleInTab}
inherited={isDefaultSetting('showChatTitleInTab')}
on:change={() => { on:change={() => {
saveSettings({ showChatTitleInTab }); saveSettings({ showChatTitleInTab });
}} }}
@@ -505,6 +527,7 @@
ariaLabelledbyId="allow-user-location-label" ariaLabelledbyId="allow-user-location-label"
tooltip={true} tooltip={true}
bind:state={userLocation} bind:state={userLocation}
inherited={isDefaultSetting('userLocation')}
on:change={() => { on:change={() => {
toggleUserLocation(); toggleUserLocation();
}} }}
@@ -527,6 +550,7 @@
ariaLabelledbyId="haptic-feedback-label" ariaLabelledbyId="haptic-feedback-label"
tooltip={true} tooltip={true}
bind:state={hapticFeedback} bind:state={hapticFeedback}
inherited={isDefaultSetting('hapticFeedback')}
on:change={() => { on:change={() => {
saveSettings({ hapticFeedback }); saveSettings({ hapticFeedback });
}} }}
@@ -549,6 +573,7 @@
ariaLabelledbyId="copy-formatted-label" ariaLabelledbyId="copy-formatted-label"
tooltip={true} tooltip={true}
bind:state={copyFormatted} bind:state={copyFormatted}
inherited={isDefaultSetting('copyFormatted')}
on:change={() => { on:change={() => {
saveSettings({ copyFormatted }); saveSettings({ copyFormatted });
}} }}
@@ -572,6 +597,7 @@
ariaLabelledbyId="toast-notifications-label" ariaLabelledbyId="toast-notifications-label"
tooltip={true} tooltip={true}
bind:state={showUpdateToast} bind:state={showUpdateToast}
inherited={isDefaultSetting('showUpdateToast')}
on:change={() => { on:change={() => {
saveSettings({ showUpdateToast }); saveSettings({ showUpdateToast });
}} }}
@@ -594,6 +620,7 @@
ariaLabelledbyId="whats-new-label" ariaLabelledbyId="whats-new-label"
tooltip={true} tooltip={true}
bind:state={showChangelog} bind:state={showChangelog}
inherited={isDefaultSetting('showChangelog')}
on:change={() => { on:change={() => {
saveSettings({ showChangelog }); saveSettings({ showChangelog });
}} }}
@@ -619,6 +646,7 @@
ariaLabelledbyId="enable-message-queue-label" ariaLabelledbyId="enable-message-queue-label"
tooltip={true} tooltip={true}
bind:state={enableMessageQueue} bind:state={enableMessageQueue}
inherited={isDefaultSetting('enableMessageQueue')}
on:change={() => { on:change={() => {
saveSettings({ enableMessageQueue }); saveSettings({ enableMessageQueue });
}} }}
@@ -720,6 +748,7 @@
tooltip={true} tooltip={true}
ariaLabelledbyId="chat-bubble-ui-label" ariaLabelledbyId="chat-bubble-ui-label"
bind:state={chatBubble} bind:state={chatBubble}
inherited={isDefaultSetting('chatBubble')}
on:change={() => { on:change={() => {
saveSettings({ chatBubble }); saveSettings({ chatBubble });
}} }}
@@ -743,6 +772,7 @@
ariaLabelledbyId="chat-bubble-username-label" ariaLabelledbyId="chat-bubble-username-label"
tooltip={true} tooltip={true}
bind:state={showUsername} bind:state={showUsername}
inherited={isDefaultSetting('showUsername')}
on:change={() => { on:change={() => {
saveSettings({ showUsername }); saveSettings({ showUsername });
}} }}
@@ -766,6 +796,7 @@
ariaLabelledbyId="widescreen-mode-label" ariaLabelledbyId="widescreen-mode-label"
tooltip={true} tooltip={true}
bind:state={widescreenMode} bind:state={widescreenMode}
inherited={isDefaultSetting('widescreenMode')}
on:change={() => { on:change={() => {
saveSettings({ widescreenMode }); saveSettings({ widescreenMode });
}} }}
@@ -789,6 +820,7 @@
ariaLabelledbyId="temp-chat-default-label" ariaLabelledbyId="temp-chat-default-label"
tooltip={true} tooltip={true}
bind:state={temporaryChatByDefault} bind:state={temporaryChatByDefault}
inherited={isDefaultSetting('temporaryChatByDefault')}
on:change={() => { on:change={() => {
saveSettings({ temporaryChatByDefault }); saveSettings({ temporaryChatByDefault });
}} }}
@@ -812,6 +844,7 @@
ariaLabelledbyId="fade-streaming-label" ariaLabelledbyId="fade-streaming-label"
tooltip={true} tooltip={true}
bind:state={chatFadeStreamingText} bind:state={chatFadeStreamingText}
inherited={isDefaultSetting('chatFadeStreamingText')}
on:change={() => { on:change={() => {
saveSettings({ chatFadeStreamingText }); saveSettings({ chatFadeStreamingText });
}} }}
@@ -834,6 +867,7 @@
ariaLabelledbyId="render-markdown-user-label" ariaLabelledbyId="render-markdown-user-label"
tooltip={true} tooltip={true}
bind:state={renderMarkdownInUserMessages} bind:state={renderMarkdownInUserMessages}
inherited={isDefaultSetting('renderMarkdownInUserMessages')}
on:change={() => { on:change={() => {
saveSettings({ renderMarkdownInUserMessages }); saveSettings({ renderMarkdownInUserMessages });
}} }}
@@ -856,6 +890,7 @@
ariaLabelledbyId="render-markdown-assistant-label" ariaLabelledbyId="render-markdown-assistant-label"
tooltip={true} tooltip={true}
bind:state={renderMarkdownInAssistantMessages} bind:state={renderMarkdownInAssistantMessages}
inherited={isDefaultSetting('renderMarkdownInAssistantMessages')}
on:change={() => { on:change={() => {
saveSettings({ renderMarkdownInAssistantMessages }); saveSettings({ renderMarkdownInAssistantMessages });
}} }}
@@ -878,6 +913,7 @@
ariaLabelledbyId="auto-generation-label" ariaLabelledbyId="auto-generation-label"
tooltip={true} tooltip={true}
bind:state={titleAutoGenerate} bind:state={titleAutoGenerate}
inherited={isDefaultSetting('titleAutoGenerate')}
on:change={() => { on:change={() => {
toggleTitleAutoGenerate(); toggleTitleAutoGenerate();
}} }}
@@ -900,6 +936,7 @@
ariaLabelledbyId="follow-up-auto-generation-label" ariaLabelledbyId="follow-up-auto-generation-label"
tooltip={true} tooltip={true}
bind:state={autoFollowUps} bind:state={autoFollowUps}
inherited={isDefaultSetting('autoFollowUps')}
on:change={() => { on:change={() => {
saveSettings({ autoFollowUps }); saveSettings({ autoFollowUps });
}} }}
@@ -922,6 +959,7 @@
ariaLabelledbyId="chat-tags-label" ariaLabelledbyId="chat-tags-label"
tooltip={true} tooltip={true}
bind:state={autoTags} bind:state={autoTags}
inherited={isDefaultSetting('autoTags')}
on:change={() => { on:change={() => {
saveSettings({ autoTags }); saveSettings({ autoTags });
}} }}
@@ -944,6 +982,7 @@
ariaLabelledbyId="auto-copy-label" ariaLabelledbyId="auto-copy-label"
tooltip={true} tooltip={true}
bind:state={responseAutoCopy} bind:state={responseAutoCopy}
inherited={isDefaultSetting('responseAutoCopy')}
on:change={() => { on:change={() => {
toggleResponseAutoCopy(); toggleResponseAutoCopy();
}} }}
@@ -966,6 +1005,7 @@
ariaLabelledbyId="response-auto-scroll-label" ariaLabelledbyId="response-auto-scroll-label"
tooltip={true} tooltip={true}
bind:state={scrollOnResponseGeneration} bind:state={scrollOnResponseGeneration}
inherited={isDefaultSetting('scrollOnResponseGeneration')}
on:change={() => { on:change={() => {
saveSettings({ scrollOnResponseGeneration }); saveSettings({ scrollOnResponseGeneration });
}} }}
@@ -988,6 +1028,7 @@
ariaLabelledbyId="insert-suggestion-prompt-label" ariaLabelledbyId="insert-suggestion-prompt-label"
tooltip={true} tooltip={true}
bind:state={insertSuggestionPrompt} bind:state={insertSuggestionPrompt}
inherited={isDefaultSetting('insertSuggestionPrompt')}
on:change={() => { on:change={() => {
saveSettings({ insertSuggestionPrompt }); saveSettings({ insertSuggestionPrompt });
}} }}
@@ -1010,6 +1051,7 @@
ariaLabelledbyId="keep-follow-up-prompts-label" ariaLabelledbyId="keep-follow-up-prompts-label"
tooltip={true} tooltip={true}
bind:state={keepFollowUpPrompts} bind:state={keepFollowUpPrompts}
inherited={isDefaultSetting('keepFollowUpPrompts')}
on:change={() => { on:change={() => {
saveSettings({ keepFollowUpPrompts }); saveSettings({ keepFollowUpPrompts });
}} }}
@@ -1032,6 +1074,7 @@
ariaLabelledbyId="insert-follow-up-prompt-label" ariaLabelledbyId="insert-follow-up-prompt-label"
tooltip={true} tooltip={true}
bind:state={insertFollowUpPrompt} bind:state={insertFollowUpPrompt}
inherited={isDefaultSetting('insertFollowUpPrompt')}
on:change={() => { on:change={() => {
saveSettings({ insertFollowUpPrompt }); saveSettings({ insertFollowUpPrompt });
}} }}
@@ -1054,6 +1097,7 @@
ariaLabelledbyId="regenerate-menu-label" ariaLabelledbyId="regenerate-menu-label"
tooltip={true} tooltip={true}
bind:state={regenerateMenu} bind:state={regenerateMenu}
inherited={isDefaultSetting('regenerateMenu')}
on:change={() => { on:change={() => {
saveSettings({ regenerateMenu }); saveSettings({ regenerateMenu });
}} }}
@@ -1076,6 +1120,7 @@
ariaLabelledbyId="always-collapse-label" ariaLabelledbyId="always-collapse-label"
tooltip={true} tooltip={true}
bind:state={collapseCodeBlocks} bind:state={collapseCodeBlocks}
inherited={isDefaultSetting('collapseCodeBlocks')}
on:change={() => { on:change={() => {
saveSettings({ collapseCodeBlocks }); saveSettings({ collapseCodeBlocks });
}} }}
@@ -1098,6 +1143,7 @@
ariaLabelledbyId="always-expand-label" ariaLabelledbyId="always-expand-label"
tooltip={true} tooltip={true}
bind:state={expandDetails} bind:state={expandDetails}
inherited={isDefaultSetting('expandDetails')}
on:change={() => { on:change={() => {
saveSettings({ expandDetails }); saveSettings({ expandDetails });
}} }}
@@ -1120,6 +1166,7 @@
ariaLabelledbyId="render-markdown-in-previews-label" ariaLabelledbyId="render-markdown-in-previews-label"
tooltip={true} tooltip={true}
bind:state={renderMarkdownInPreviews} bind:state={renderMarkdownInPreviews}
inherited={isDefaultSetting('renderMarkdownInPreviews')}
on:change={() => { on:change={() => {
saveSettings({ renderMarkdownInPreviews }); saveSettings({ renderMarkdownInPreviews });
}} }}
@@ -1142,6 +1189,7 @@
ariaLabelledbyId="keep-followup-prompts-label" ariaLabelledbyId="keep-followup-prompts-label"
tooltip={true} tooltip={true}
bind:state={displayMultiModelResponsesInTabs} bind:state={displayMultiModelResponsesInTabs}
inherited={isDefaultSetting('displayMultiModelResponsesInTabs')}
on:change={() => { on:change={() => {
saveSettings({ displayMultiModelResponsesInTabs }); saveSettings({ displayMultiModelResponsesInTabs });
}} }}
@@ -1164,6 +1212,7 @@
ariaLabelledbyId="scroll-on-branch-change-label" ariaLabelledbyId="scroll-on-branch-change-label"
tooltip={true} tooltip={true}
bind:state={scrollOnBranchChange} bind:state={scrollOnBranchChange}
inherited={isDefaultSetting('scrollOnBranchChange')}
on:change={() => { on:change={() => {
saveSettings({ scrollOnBranchChange }); saveSettings({ scrollOnBranchChange });
}} }}
@@ -1186,6 +1235,7 @@
ariaLabelledbyId="show-files-on-terminal-select-label" ariaLabelledbyId="show-files-on-terminal-select-label"
tooltip={true} tooltip={true}
bind:state={showFilesOnTerminalSelect} bind:state={showFilesOnTerminalSelect}
inherited={isDefaultSetting('showFilesOnTerminalSelect')}
on:change={() => { on:change={() => {
saveSettings({ showFilesOnTerminalSelect }); saveSettings({ showFilesOnTerminalSelect });
}} }}
@@ -1208,6 +1258,7 @@
ariaLabelledbyId="stylized-pdf-export-label" ariaLabelledbyId="stylized-pdf-export-label"
tooltip={true} tooltip={true}
bind:state={stylizedPdfExport} bind:state={stylizedPdfExport}
inherited={isDefaultSetting('stylizedPdfExport')}
on:change={() => { on:change={() => {
saveSettings({ stylizedPdfExport }); saveSettings({ stylizedPdfExport });
}} }}
@@ -1243,6 +1294,7 @@
ariaLabelledbyId="floating-action-buttons-label" ariaLabelledbyId="floating-action-buttons-label"
tooltip={true} tooltip={true}
bind:state={showFloatingActionButtons} bind:state={showFloatingActionButtons}
inherited={isDefaultSetting('showFloatingActionButtons')}
on:change={() => { on:change={() => {
saveSettings({ showFloatingActionButtons }); saveSettings({ showFloatingActionButtons });
}} }}
@@ -1317,6 +1369,7 @@
tooltip={true} tooltip={true}
ariaLabelledbyId="rich-input-label" ariaLabelledbyId="rich-input-label"
bind:state={richTextInput} bind:state={richTextInput}
inherited={isDefaultSetting('richTextInput')}
on:change={() => { on:change={() => {
saveSettings({ richTextInput }); saveSettings({ richTextInput });
}} }}
@@ -1340,6 +1393,7 @@
ariaLabelledbyId="prompt-autocompletion-label" ariaLabelledbyId="prompt-autocompletion-label"
tooltip={true} tooltip={true}
bind:state={promptAutocomplete} bind:state={promptAutocomplete}
inherited={isDefaultSetting('promptAutocomplete')}
on:change={() => { on:change={() => {
saveSettings({ promptAutocomplete }); saveSettings({ promptAutocomplete });
}} }}
@@ -1364,6 +1418,7 @@
ariaLabelledbyId="show-formatting-toolbar-label" ariaLabelledbyId="show-formatting-toolbar-label"
tooltip={true} tooltip={true}
bind:state={showFormattingToolbar} bind:state={showFormattingToolbar}
inherited={isDefaultSetting('showFormattingToolbar')}
on:change={() => { on:change={() => {
saveSettings({ showFormattingToolbar }); saveSettings({ showFormattingToolbar });
}} }}
@@ -1386,6 +1441,7 @@
ariaLabelledbyId="insert-prompt-as-rich-text-label" ariaLabelledbyId="insert-prompt-as-rich-text-label"
tooltip={true} tooltip={true}
bind:state={insertPromptAsRichText} bind:state={insertPromptAsRichText}
inherited={isDefaultSetting('insertPromptAsRichText')}
on:change={() => { on:change={() => {
saveSettings({ insertPromptAsRichText }); saveSettings({ insertPromptAsRichText });
}} }}
@@ -1409,6 +1465,7 @@
tooltip={true} tooltip={true}
ariaLabelledbyId="paste-large-label" ariaLabelledbyId="paste-large-label"
bind:state={largeTextAsFile} bind:state={largeTextAsFile}
inherited={isDefaultSetting('largeTextAsFile')}
on:change={() => { on:change={() => {
saveSettings({ largeTextAsFile }); saveSettings({ largeTextAsFile });
}} }}
@@ -1433,6 +1490,7 @@
ariaLabelledbyId="detect-artifacts-label" ariaLabelledbyId="detect-artifacts-label"
tooltip={true} tooltip={true}
bind:state={detectArtifacts} bind:state={detectArtifacts}
inherited={isDefaultSetting('detectArtifacts')}
on:change={() => { on:change={() => {
saveSettings({ detectArtifacts }); saveSettings({ detectArtifacts });
}} }}
@@ -1455,6 +1513,7 @@
ariaLabelledbyId="iframe-sandbox-allow-same-origin-label" ariaLabelledbyId="iframe-sandbox-allow-same-origin-label"
tooltip={true} tooltip={true}
bind:state={iframeSandboxAllowSameOrigin} bind:state={iframeSandboxAllowSameOrigin}
inherited={isDefaultSetting('iframeSandboxAllowSameOrigin')}
on:change={() => { on:change={() => {
saveSettings({ iframeSandboxAllowSameOrigin }); saveSettings({ iframeSandboxAllowSameOrigin });
}} }}
@@ -1477,6 +1536,7 @@
ariaLabelledbyId="iframe-sandbox-allow-forms-label" ariaLabelledbyId="iframe-sandbox-allow-forms-label"
tooltip={true} tooltip={true}
bind:state={iframeSandboxAllowForms} bind:state={iframeSandboxAllowForms}
inherited={isDefaultSetting('iframeSandboxAllowForms')}
on:change={() => { on:change={() => {
saveSettings({ iframeSandboxAllowForms }); saveSettings({ iframeSandboxAllowForms });
}} }}
@@ -1501,6 +1561,7 @@
ariaLabelledbyId="allow-voice-interruption-in-call-label" ariaLabelledbyId="allow-voice-interruption-in-call-label"
tooltip={true} tooltip={true}
bind:state={voiceInterruption} bind:state={voiceInterruption}
inherited={isDefaultSetting('voiceInterruption')}
on:change={() => { on:change={() => {
saveSettings({ voiceInterruption }); saveSettings({ voiceInterruption });
}} }}
@@ -1523,6 +1584,7 @@
ariaLabelledbyId="display-emoji-label" ariaLabelledbyId="display-emoji-label"
tooltip={true} tooltip={true}
bind:state={showEmojiInCall} bind:state={showEmojiInCall}
inherited={isDefaultSetting('showEmojiInCall')}
on:change={() => { on:change={() => {
saveSettings({ showEmojiInCall }); saveSettings({ showEmojiInCall });
}} }}
@@ -1587,6 +1649,7 @@
ariaLabelledbyId="image-compression-label" ariaLabelledbyId="image-compression-label"
tooltip={true} tooltip={true}
bind:state={imageCompression} bind:state={imageCompression}
inherited={isDefaultSetting('imageCompression')}
on:change={() => { on:change={() => {
saveSettings({ imageCompression }); saveSettings({ imageCompression });
}} }}
@@ -1610,6 +1673,7 @@
ariaLabelledbyId="image-compression-in-channels-label" ariaLabelledbyId="image-compression-in-channels-label"
tooltip={true} tooltip={true}
bind:state={imageCompressionInChannels} bind:state={imageCompressionInChannels}
inherited={isDefaultSetting('imageCompressionInChannels')}
on:change={() => { on:change={() => {
saveSettings({ imageCompressionInChannels }); saveSettings({ imageCompressionInChannels });
}} }}
+28 -21
View File
@@ -10,8 +10,9 @@
export let ariaLabelledbyId = ''; export let ariaLabelledbyId = '';
export let ariaLabel = ''; export let ariaLabel = '';
export let tooltip = false; export let tooltip = false;
export let inherited = false;
const i18n = getContext('i18n'); const i18n: any = getContext('i18n');
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
</script> </script>
@@ -25,24 +26,30 @@
: ''} : ''}
placement="top" placement="top"
> >
<Switch.Root <div class="flex items-center gap-1.5">
bind:checked={state} {#if inherited}
{id} <span class="text-[0.6875rem] text-gray-400 dark:text-gray-600">{$i18n.t('Default')}</span>
aria-labelledby={ariaLabelledbyId || undefined} {/if}
aria-label={ariaLabel || undefined}
class="relative h-4 min-h-4 w-7 shrink-0 cursor-pointer rounded-full mx-[0.0625rem] transition-colors duration-150 {($settings?.highContrastMode ?? <Switch.Root
false) bind:checked={state}
? 'focus:outline focus:outline-2 focus:outline-gray-800 focus:dark:outline-gray-200' {id}
: 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-400 dark:focus-visible:outline-gray-500'} {state aria-labelledby={ariaLabelledbyId || undefined}
? 'bg-gray-900 dark:bg-white' aria-label={ariaLabel || undefined}
: 'bg-gray-300 dark:bg-gray-700'}" class="relative h-4 min-h-4 w-7 shrink-0 cursor-pointer rounded-full mx-[0.0625rem] transition-colors duration-150 {($settings?.highContrastMode ??
onCheckedChange={async () => { false)
await tick(); ? 'focus:outline focus:outline-2 focus:outline-gray-800 focus:dark:outline-gray-200'
dispatch('change', state); : 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-400 dark:focus-visible:outline-gray-500'} {state
}} ? 'bg-gray-900 dark:bg-white'
> : 'bg-gray-300 dark:bg-gray-700'}"
<Switch.Thumb onCheckedChange={async () => {
class="pointer-events-none absolute top-[0.125rem] block h-3 w-3 shrink-0 rounded-full transition-all duration-150 data-[state=checked]:left-[0.875rem] data-[state=checked]:bg-white data-[state=checked]:dark:bg-black data-[state=unchecked]:left-[0.125rem] data-[state=unchecked]:bg-white data-[state=unchecked]:dark:bg-gray-500" await tick();
/> dispatch('change', state);
</Switch.Root> }}
>
<Switch.Thumb
class="pointer-events-none absolute top-[0.125rem] block h-3 w-3 shrink-0 rounded-full transition-all duration-150 data-[state=checked]:left-[0.875rem] data-[state=checked]:bg-white data-[state=checked]:dark:bg-black data-[state=unchecked]:left-[0.125rem] data-[state=unchecked]:bg-white data-[state=unchecked]:dark:bg-gray-500"
/>
</Switch.Root>
</div>
</Tooltip> </Tooltip>