mirror of
https://github.com/open-webui/open-webui
synced 2025-05-15 19:16:35 +00:00
feat: save user settings to db
This commit is contained in:
parent
9d4c07b76a
commit
ccbafca74c
@ -198,7 +198,7 @@ async def fetch_url(url, key):
|
|||||||
|
|
||||||
|
|
||||||
def merge_models_lists(model_lists):
|
def merge_models_lists(model_lists):
|
||||||
log.info(f"merge_models_lists {model_lists}")
|
log.debug(f"merge_models_lists {model_lists}")
|
||||||
merged_list = []
|
merged_list = []
|
||||||
|
|
||||||
for idx, models in enumerate(model_lists):
|
for idx, models in enumerate(model_lists):
|
||||||
@ -237,7 +237,7 @@ async def get_all_models():
|
|||||||
]
|
]
|
||||||
|
|
||||||
responses = await asyncio.gather(*tasks)
|
responses = await asyncio.gather(*tasks)
|
||||||
log.info(f"get_all_models:responses() {responses}")
|
log.debug(f"get_all_models:responses() {responses}")
|
||||||
|
|
||||||
models = {
|
models = {
|
||||||
"data": merge_models_lists(
|
"data": merge_models_lists(
|
||||||
@ -254,7 +254,7 @@ async def get_all_models():
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info(f"models: {models}")
|
log.debug(f"models: {models}")
|
||||||
app.state.MODELS = {model["id"]: model for model in models["data"]}
|
app.state.MODELS = {model["id"]: model for model in models["data"]}
|
||||||
|
|
||||||
return models
|
return models
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
"""Peewee migrations -- 002_add_local_sharing.py.
|
||||||
|
|
||||||
|
Some examples (model - class or model name)::
|
||||||
|
|
||||||
|
> Model = migrator.orm['table_name'] # Return model in current state by name
|
||||||
|
> Model = migrator.ModelClass # Return model in current state by name
|
||||||
|
|
||||||
|
> migrator.sql(sql) # Run custom SQL
|
||||||
|
> migrator.run(func, *args, **kwargs) # Run python function with the given args
|
||||||
|
> migrator.create_model(Model) # Create a model (could be used as decorator)
|
||||||
|
> migrator.remove_model(model, cascade=True) # Remove a model
|
||||||
|
> migrator.add_fields(model, **fields) # Add fields to a model
|
||||||
|
> migrator.change_fields(model, **fields) # Change fields
|
||||||
|
> migrator.remove_fields(model, *field_names, cascade=True)
|
||||||
|
> migrator.rename_field(model, old_field_name, new_field_name)
|
||||||
|
> migrator.rename_table(model, new_table_name)
|
||||||
|
> migrator.add_index(model, *col_names, unique=False)
|
||||||
|
> migrator.add_not_null(model, *field_names)
|
||||||
|
> migrator.add_default(model, field_name, default)
|
||||||
|
> migrator.add_constraint(model, name, sql)
|
||||||
|
> migrator.drop_index(model, *col_names)
|
||||||
|
> migrator.drop_not_null(model, *field_names)
|
||||||
|
> migrator.drop_constraints(model, *constraints)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from contextlib import suppress
|
||||||
|
|
||||||
|
import peewee as pw
|
||||||
|
from peewee_migrate import Migrator
|
||||||
|
|
||||||
|
|
||||||
|
with suppress(ImportError):
|
||||||
|
import playhouse.postgres_ext as pw_pext
|
||||||
|
|
||||||
|
|
||||||
|
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
|
||||||
|
"""Write your migrations here."""
|
||||||
|
|
||||||
|
# Adding fields settings to the 'user' table
|
||||||
|
migrator.add_fields("user", settings=pw.TextField(null=True))
|
||||||
|
|
||||||
|
|
||||||
|
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
|
||||||
|
"""Write your rollback migrations here."""
|
||||||
|
|
||||||
|
# Remove the settings field
|
||||||
|
migrator.remove_fields("user", "settings")
|
@ -1,11 +1,11 @@
|
|||||||
from pydantic import BaseModel
|
from pydantic import BaseModel, ConfigDict
|
||||||
from peewee import *
|
from peewee import *
|
||||||
from playhouse.shortcuts import model_to_dict
|
from playhouse.shortcuts import model_to_dict
|
||||||
from typing import List, Union, Optional
|
from typing import List, Union, Optional
|
||||||
import time
|
import time
|
||||||
from utils.misc import get_gravatar_url
|
from utils.misc import get_gravatar_url
|
||||||
|
|
||||||
from apps.webui.internal.db import DB
|
from apps.webui.internal.db import DB, JSONField
|
||||||
from apps.webui.models.chats import Chats
|
from apps.webui.models.chats import Chats
|
||||||
|
|
||||||
####################
|
####################
|
||||||
@ -25,11 +25,18 @@ class User(Model):
|
|||||||
created_at = BigIntegerField()
|
created_at = BigIntegerField()
|
||||||
|
|
||||||
api_key = CharField(null=True, unique=True)
|
api_key = CharField(null=True, unique=True)
|
||||||
|
settings = JSONField(null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
database = DB
|
database = DB
|
||||||
|
|
||||||
|
|
||||||
|
class UserSettings(BaseModel):
|
||||||
|
ui: Optional[dict] = {}
|
||||||
|
model_config = ConfigDict(extra="allow")
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class UserModel(BaseModel):
|
class UserModel(BaseModel):
|
||||||
id: str
|
id: str
|
||||||
name: str
|
name: str
|
||||||
@ -42,6 +49,7 @@ class UserModel(BaseModel):
|
|||||||
created_at: int # timestamp in epoch
|
created_at: int # timestamp in epoch
|
||||||
|
|
||||||
api_key: Optional[str] = None
|
api_key: Optional[str] = None
|
||||||
|
settings: Optional[UserSettings] = None
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -9,7 +9,13 @@ import time
|
|||||||
import uuid
|
import uuid
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from apps.webui.models.users import UserModel, UserUpdateForm, UserRoleUpdateForm, Users
|
from apps.webui.models.users import (
|
||||||
|
UserModel,
|
||||||
|
UserUpdateForm,
|
||||||
|
UserRoleUpdateForm,
|
||||||
|
UserSettings,
|
||||||
|
Users,
|
||||||
|
)
|
||||||
from apps.webui.models.auths import Auths
|
from apps.webui.models.auths import Auths
|
||||||
from apps.webui.models.chats import Chats
|
from apps.webui.models.chats import Chats
|
||||||
|
|
||||||
@ -68,6 +74,42 @@ async def update_user_role(form_data: UserRoleUpdateForm, user=Depends(get_admin
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
############################
|
||||||
|
# GetUserSettingsBySessionUser
|
||||||
|
############################
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/user/settings", response_model=Optional[UserSettings])
|
||||||
|
async def get_user_settings_by_session_user(user=Depends(get_verified_user)):
|
||||||
|
user = Users.get_user_by_id(user.id)
|
||||||
|
if user:
|
||||||
|
return user.settings
|
||||||
|
else:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=ERROR_MESSAGES.USER_NOT_FOUND,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
############################
|
||||||
|
# UpdateUserSettingsBySessionUser
|
||||||
|
############################
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/user/settings/update", response_model=UserSettings)
|
||||||
|
async def update_user_settings_by_session_user(
|
||||||
|
form_data: UserSettings, user=Depends(get_verified_user)
|
||||||
|
):
|
||||||
|
user = Users.update_user_by_id(user.id, {"settings": form_data.model_dump()})
|
||||||
|
if user:
|
||||||
|
return user.settings
|
||||||
|
else:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=ERROR_MESSAGES.USER_NOT_FOUND,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
############################
|
############################
|
||||||
# GetUserById
|
# GetUserById
|
||||||
############################
|
############################
|
||||||
@ -81,6 +123,8 @@ class UserResponse(BaseModel):
|
|||||||
@router.get("/{user_id}", response_model=UserResponse)
|
@router.get("/{user_id}", response_model=UserResponse)
|
||||||
async def get_user_by_id(user_id: str, user=Depends(get_verified_user)):
|
async def get_user_by_id(user_id: str, user=Depends(get_verified_user)):
|
||||||
|
|
||||||
|
# Check if user_id is a shared chat
|
||||||
|
# If it is, get the user_id from the chat
|
||||||
if user_id.startswith("shared-"):
|
if user_id.startswith("shared-"):
|
||||||
chat_id = user_id.replace("shared-", "")
|
chat_id = user_id.replace("shared-", "")
|
||||||
chat = Chats.get_chat_by_id(chat_id)
|
chat = Chats.get_chat_by_id(chat_id)
|
||||||
|
@ -115,6 +115,62 @@ export const getUsers = async (token: string) => {
|
|||||||
return res ? res : [];
|
return res ? res : [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getUserSettings = async (token: string) => {
|
||||||
|
let error = null;
|
||||||
|
const res = await fetch(`${WEBUI_API_BASE_URL}/users/user/settings`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(async (res) => {
|
||||||
|
if (!res.ok) throw await res.json();
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
error = err.detail;
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateUserSettings = async (token: string, settings: object) => {
|
||||||
|
let error = null;
|
||||||
|
|
||||||
|
const res = await fetch(`${WEBUI_API_BASE_URL}/users/user/settings/update`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${token}`
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
...settings
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(async (res) => {
|
||||||
|
if (!res.ok) throw await res.json();
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
error = err.detail;
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
export const getUserById = async (token: string, userId: string) => {
|
export const getUserById = async (token: string, userId: string) => {
|
||||||
let error = null;
|
let error = null;
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
import type { Writable } from 'svelte/store';
|
import type { Writable } from 'svelte/store';
|
||||||
import type { i18n as i18nType } from 'i18next';
|
import type { i18n as i18nType } from 'i18next';
|
||||||
import Banner from '../common/Banner.svelte';
|
import Banner from '../common/Banner.svelte';
|
||||||
|
import { getUserSettings } from '$lib/apis/users';
|
||||||
|
|
||||||
const i18n: Writable<i18nType> = getContext('i18n');
|
const i18n: Writable<i18nType> = getContext('i18n');
|
||||||
|
|
||||||
@ -154,10 +155,13 @@
|
|||||||
$models.map((m) => m.id).includes(modelId) ? modelId : ''
|
$models.map((m) => m.id).includes(modelId) ? modelId : ''
|
||||||
);
|
);
|
||||||
|
|
||||||
let _settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
|
const userSettings = await getUserSettings(localStorage.token);
|
||||||
settings.set({
|
|
||||||
..._settings
|
if (userSettings) {
|
||||||
});
|
settings.set(userSettings.ui);
|
||||||
|
} else {
|
||||||
|
settings.set(JSON.parse(localStorage.getItem('settings') ?? '{}'));
|
||||||
|
}
|
||||||
|
|
||||||
const chatInput = document.getElementById('chat-textarea');
|
const chatInput = document.getElementById('chat-textarea');
|
||||||
setTimeout(() => chatInput?.focus(), 0);
|
setTimeout(() => chatInput?.focus(), 0);
|
||||||
@ -187,11 +191,18 @@
|
|||||||
: convertMessagesToHistory(chatContent.messages);
|
: convertMessagesToHistory(chatContent.messages);
|
||||||
title = chatContent.title;
|
title = chatContent.title;
|
||||||
|
|
||||||
let _settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
|
const userSettings = await getUserSettings(localStorage.token);
|
||||||
|
|
||||||
|
if (userSettings) {
|
||||||
|
await settings.set(userSettings.ui);
|
||||||
|
} else {
|
||||||
|
await settings.set(JSON.parse(localStorage.getItem('settings') ?? '{}'));
|
||||||
|
}
|
||||||
|
|
||||||
await settings.set({
|
await settings.set({
|
||||||
..._settings,
|
...$settings,
|
||||||
system: chatContent.system ?? _settings.system,
|
system: chatContent.system ?? $settings.system,
|
||||||
params: chatContent.options ?? _settings.params
|
params: chatContent.options ?? $settings.params
|
||||||
});
|
});
|
||||||
autoScroll = true;
|
autoScroll = true;
|
||||||
await tick();
|
await tick();
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Collapsible } from 'bits-ui';
|
|
||||||
|
|
||||||
import { setDefaultModels } from '$lib/apis/configs';
|
|
||||||
import { models, showSettings, settings, user, mobile } from '$lib/stores';
|
import { models, showSettings, settings, user, mobile } from '$lib/stores';
|
||||||
import { onMount, tick, getContext } from 'svelte';
|
import { onMount, tick, getContext } from 'svelte';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import Selector from './ModelSelector/Selector.svelte';
|
import Selector from './ModelSelector/Selector.svelte';
|
||||||
import Tooltip from '../common/Tooltip.svelte';
|
import Tooltip from '../common/Tooltip.svelte';
|
||||||
|
|
||||||
|
import { setDefaultModels } from '$lib/apis/configs';
|
||||||
|
import { updateUserSettings } from '$lib/apis/users';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
export let selectedModels = [''];
|
export let selectedModels = [''];
|
||||||
@ -22,7 +22,9 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
settings.set({ ...$settings, models: selectedModels });
|
settings.set({ ...$settings, models: selectedModels });
|
||||||
|
|
||||||
localStorage.setItem('settings', JSON.stringify($settings));
|
localStorage.setItem('settings', JSON.stringify($settings));
|
||||||
|
await updateUserSettings(localStorage.token, { ui: $settings });
|
||||||
|
|
||||||
if ($user.role === 'admin') {
|
if ($user.role === 'admin') {
|
||||||
console.log('setting default models globally');
|
console.log('setting default models globally');
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getAudioConfig, updateAudioConfig } from '$lib/apis/audio';
|
import { getAudioConfig, updateAudioConfig } from '$lib/apis/audio';
|
||||||
import { user } from '$lib/stores';
|
import { user, settings } from '$lib/stores';
|
||||||
import { createEventDispatcher, onMount, getContext } from 'svelte';
|
import { createEventDispatcher, onMount, getContext } from 'svelte';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
@ -99,16 +99,14 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
|
conversationMode = $settings.conversationMode ?? false;
|
||||||
|
speechAutoSend = $settings.speechAutoSend ?? false;
|
||||||
|
responseAutoPlayback = $settings.responseAutoPlayback ?? false;
|
||||||
|
|
||||||
conversationMode = settings.conversationMode ?? false;
|
STTEngine = $settings?.audio?.STTEngine ?? '';
|
||||||
speechAutoSend = settings.speechAutoSend ?? false;
|
TTSEngine = $settings?.audio?.TTSEngine ?? '';
|
||||||
responseAutoPlayback = settings.responseAutoPlayback ?? false;
|
speaker = $settings?.audio?.speaker ?? '';
|
||||||
|
model = $settings?.audio?.model ?? '';
|
||||||
STTEngine = settings?.audio?.STTEngine ?? '';
|
|
||||||
TTSEngine = settings?.audio?.TTSEngine ?? '';
|
|
||||||
speaker = settings?.audio?.speaker ?? '';
|
|
||||||
model = settings?.audio?.model ?? '';
|
|
||||||
|
|
||||||
if (TTSEngine === 'openai') {
|
if (TTSEngine === 'openai') {
|
||||||
getOpenAIVoices();
|
getOpenAIVoices();
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import fileSaver from 'file-saver';
|
import fileSaver from 'file-saver';
|
||||||
const { saveAs } = fileSaver;
|
const { saveAs } = fileSaver;
|
||||||
|
|
||||||
import { chats, user, config } from '$lib/stores';
|
import { chats, user, settings } from '$lib/stores';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
archiveAllChats,
|
archiveAllChats,
|
||||||
@ -99,9 +99,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
|
saveChatHistory = $settings.saveChatHistory ?? true;
|
||||||
|
|
||||||
saveChatHistory = settings.saveChatHistory ?? true;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import { getLanguages } from '$lib/i18n';
|
import { getLanguages } from '$lib/i18n';
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
import { models, user, theme } from '$lib/stores';
|
import { models, settings, theme } from '$lib/stores';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
@ -71,23 +71,22 @@
|
|||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
selectedTheme = localStorage.theme ?? 'system';
|
selectedTheme = localStorage.theme ?? 'system';
|
||||||
|
|
||||||
let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
|
|
||||||
languages = await getLanguages();
|
languages = await getLanguages();
|
||||||
|
|
||||||
notificationEnabled = settings.notificationEnabled ?? false;
|
notificationEnabled = $settings.notificationEnabled ?? false;
|
||||||
system = settings.system ?? '';
|
system = $settings.system ?? '';
|
||||||
|
|
||||||
requestFormat = settings.requestFormat ?? '';
|
requestFormat = $settings.requestFormat ?? '';
|
||||||
keepAlive = settings.keepAlive ?? null;
|
keepAlive = $settings.keepAlive ?? null;
|
||||||
|
|
||||||
params.seed = settings.seed ?? 0;
|
params.seed = $settings.seed ?? 0;
|
||||||
params.temperature = settings.temperature ?? '';
|
params.temperature = $settings.temperature ?? '';
|
||||||
params.frequency_penalty = settings.frequency_penalty ?? '';
|
params.frequency_penalty = $settings.frequency_penalty ?? '';
|
||||||
params.top_k = settings.top_k ?? '';
|
params.top_k = $settings.top_k ?? '';
|
||||||
params.top_p = settings.top_p ?? '';
|
params.top_p = $settings.top_p ?? '';
|
||||||
params.num_ctx = settings.num_ctx ?? '';
|
params.num_ctx = $settings.num_ctx ?? '';
|
||||||
params = { ...params, ...settings.params };
|
params = { ...params, ...$settings.params };
|
||||||
params.stop = settings?.params?.stop ? (settings?.params?.stop ?? []).join(',') : null;
|
params.stop = $settings?.params?.stop ? ($settings?.params?.stop ?? []).join(',') : null;
|
||||||
});
|
});
|
||||||
|
|
||||||
const applyTheme = (_theme: string) => {
|
const applyTheme = (_theme: string) => {
|
||||||
|
@ -104,23 +104,18 @@
|
|||||||
promptSuggestions = $config?.default_prompt_suggestions;
|
promptSuggestions = $config?.default_prompt_suggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
|
titleAutoGenerate = $settings?.title?.auto ?? true;
|
||||||
|
titleAutoGenerateModel = $settings?.title?.model ?? '';
|
||||||
titleAutoGenerate = settings?.title?.auto ?? true;
|
titleAutoGenerateModelExternal = $settings?.title?.modelExternal ?? '';
|
||||||
titleAutoGenerateModel = settings?.title?.model ?? '';
|
|
||||||
titleAutoGenerateModelExternal = settings?.title?.modelExternal ?? '';
|
|
||||||
titleGenerationPrompt =
|
titleGenerationPrompt =
|
||||||
settings?.title?.prompt ??
|
$settings?.title?.prompt ??
|
||||||
$i18n.t(
|
`Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title': {{prompt}}`;
|
||||||
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':"
|
responseAutoCopy = $settings.responseAutoCopy ?? false;
|
||||||
) + ' {{prompt}}';
|
showUsername = $settings.showUsername ?? false;
|
||||||
|
chatBubble = $settings.chatBubble ?? true;
|
||||||
responseAutoCopy = settings.responseAutoCopy ?? false;
|
fullScreenMode = $settings.fullScreenMode ?? false;
|
||||||
showUsername = settings.showUsername ?? false;
|
splitLargeChunks = $settings.splitLargeChunks ?? false;
|
||||||
chatBubble = settings.chatBubble ?? true;
|
chatDirection = $settings.chatDirection ?? 'LTR';
|
||||||
fullScreenMode = settings.fullScreenMode ?? false;
|
|
||||||
splitLargeChunks = settings.splitLargeChunks ?? false;
|
|
||||||
chatDirection = settings.chatDirection ?? 'LTR';
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -19,8 +19,7 @@
|
|||||||
let enableMemory = false;
|
let enableMemory = false;
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
|
enableMemory = $settings?.memory ?? false;
|
||||||
enableMemory = settings?.memory ?? false;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
import Images from './Settings/Images.svelte';
|
import Images from './Settings/Images.svelte';
|
||||||
import User from '../icons/User.svelte';
|
import User from '../icons/User.svelte';
|
||||||
import Personalization from './Settings/Personalization.svelte';
|
import Personalization from './Settings/Personalization.svelte';
|
||||||
|
import { updateUserSettings } from '$lib/apis/users';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
@ -26,7 +27,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());
|
||||||
|
|
||||||
localStorage.setItem('settings', JSON.stringify($settings));
|
localStorage.setItem('settings', JSON.stringify($settings));
|
||||||
|
await updateUserSettings(localStorage.token, { ui: $settings });
|
||||||
};
|
};
|
||||||
|
|
||||||
const getModels = async () => {
|
const getModels = async () => {
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
import ArchiveBox from '../icons/ArchiveBox.svelte';
|
import ArchiveBox from '../icons/ArchiveBox.svelte';
|
||||||
import ArchivedChatsModal from './Sidebar/ArchivedChatsModal.svelte';
|
import ArchivedChatsModal from './Sidebar/ArchivedChatsModal.svelte';
|
||||||
import UserMenu from './Sidebar/UserMenu.svelte';
|
import UserMenu from './Sidebar/UserMenu.svelte';
|
||||||
|
import { updateUserSettings } from '$lib/apis/users';
|
||||||
|
|
||||||
const BREAKPOINT = 768;
|
const BREAKPOINT = 768;
|
||||||
|
|
||||||
@ -184,6 +185,8 @@
|
|||||||
const saveSettings = async (updated) => {
|
const saveSettings = async (updated) => {
|
||||||
await settings.set({ ...$settings, ...updated });
|
await settings.set({ ...$settings, ...updated });
|
||||||
localStorage.setItem('settings', JSON.stringify($settings));
|
localStorage.setItem('settings', JSON.stringify($settings));
|
||||||
|
await updateUserSettings(localStorage.token, { ui: $settings });
|
||||||
|
|
||||||
location.href = '/';
|
location.href = '/';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
import ChangelogModal from '$lib/components/ChangelogModal.svelte';
|
import ChangelogModal from '$lib/components/ChangelogModal.svelte';
|
||||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||||
import { getBanners } from '$lib/apis/configs';
|
import { getBanners } from '$lib/apis/configs';
|
||||||
|
import { getUserSettings } from '$lib/apis/users';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
@ -72,7 +73,13 @@
|
|||||||
// IndexedDB Not Found
|
// IndexedDB Not Found
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.set(JSON.parse(localStorage.getItem('settings') ?? '{}'));
|
const userSettings = await getUserSettings(localStorage.token);
|
||||||
|
|
||||||
|
if (userSettings) {
|
||||||
|
await settings.set(userSettings.ui);
|
||||||
|
} else {
|
||||||
|
await settings.set(JSON.parse(localStorage.getItem('settings') ?? '{}'));
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
(async () => {
|
(async () => {
|
||||||
|
@ -98,12 +98,6 @@
|
|||||||
: convertMessagesToHistory(chatContent.messages);
|
: convertMessagesToHistory(chatContent.messages);
|
||||||
title = chatContent.title;
|
title = chatContent.title;
|
||||||
|
|
||||||
let _settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
|
|
||||||
await settings.set({
|
|
||||||
..._settings,
|
|
||||||
system: chatContent.system ?? _settings.system,
|
|
||||||
options: chatContent.options ?? _settings.options
|
|
||||||
});
|
|
||||||
autoScroll = true;
|
autoScroll = true;
|
||||||
await tick();
|
await tick();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user