diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aa06bc..bb0ceab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Added "Aliases" page. - Form for adding aliases. +- Store appearance settings on server. + +### Changed + +- Move dark mode toggle out of "Experiments" section. ## [1.19.0] - 2023-03-30 diff --git a/src/api/settings.ts b/src/api/settings.ts index 1cec7e1..2b020c6 100644 --- a/src/api/settings.ts +++ b/src/api/settings.ts @@ -1,7 +1,25 @@ -import { BACKEND_URL } from "@/constants" +import { APP_NAME, BACKEND_URL } from "@/constants" import { http } from "./common" import { Aliases, User } from "./users" +export async function updateClientConfig( + authToken: string, + clientConfig: { [property: string]: any }, +): Promise { + const url = `${BACKEND_URL}/api/v1/settings/client_config` + const response = await http(url, { + method: "POST", + json: { [APP_NAME]: clientConfig }, + authToken, + }) + const data = await response.json() + if (response.status !== 200) { + throw new Error(data.error_description) + } else { + return data + } +} + export async function changePassword( authToken: string, newPassword: string, diff --git a/src/api/users.ts b/src/api/users.ts index fd3c1b7..d5c1958 100644 --- a/src/api/users.ts +++ b/src/api/users.ts @@ -83,6 +83,7 @@ export function defaultProfile(): Profile { export interface User extends Profile { source: Source; role: Role, + client_config: { [clientName: string]: { [property: string]: any } }, } export interface ProfileWrapper extends Profile {} diff --git a/src/composables/theme.ts b/src/composables/theme.ts index d0bf9ab..631abb2 100644 --- a/src/composables/theme.ts +++ b/src/composables/theme.ts @@ -1,6 +1,8 @@ import { ref } from "vue" -const THEME_STORAGE_KEY = "theme" +import { updateClientConfig } from "@/api/settings" +import { APP_NAME } from "@/constants" +import { useCurrentUser } from "@/store/user" enum Theme { Light = "light", @@ -14,20 +16,39 @@ export function useTheme() { function setTheme(theme: Theme) { document.documentElement.setAttribute("data-theme", theme) currentTheme.value = theme - localStorage.setItem(THEME_STORAGE_KEY, theme) + } + + async function persistTheme(theme: Theme) { + const { + ensureAuthToken, + ensureCurrentUser, + setCurrentUser, + } = useCurrentUser() + const currentUser = ensureCurrentUser() + let clientConfig = currentUser.client_config[APP_NAME] || {} + clientConfig = { ...clientConfig, theme } + const authToken = ensureAuthToken() + const user = await updateClientConfig(authToken, clientConfig) + setCurrentUser(user) } function loadTheme() { - const theme = localStorage.getItem(THEME_STORAGE_KEY) || Theme.Light + const { ensureCurrentUser } = useCurrentUser() + const currentUser = ensureCurrentUser() + const clientConfig = currentUser.client_config[APP_NAME] || {} + const theme = clientConfig.theme || Theme.Light setTheme(theme as Theme) } - function toggleDarkMode() { + async function toggleDarkMode() { + let theme if (currentTheme.value === Theme.Light) { - setTheme(Theme.Dark) + theme = Theme.Dark } else { - setTheme(Theme.Light) + theme = Theme.Light } + setTheme(theme) + await persistTheme(theme) } return { diff --git a/src/constants.ts b/src/constants.ts index 561882a..9a7bef0 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,4 +1,5 @@ export const ENV = process.env.NODE_ENV export const BACKEND_URL = process.env.VUE_APP_BACKEND_URL +export const APP_NAME = "mitra-web" export const APP_VERSION = process.env.VUE_APP_VERSION diff --git a/src/views/Settings.vue b/src/views/Settings.vue index 263447d..55063b5 100644 --- a/src/views/Settings.vue +++ b/src/views/Settings.vue @@ -11,6 +11,16 @@ Edit profile +
+

Appearance

+ +

Change password

@@ -70,9 +80,6 @@ Move followers -
@@ -93,6 +100,13 @@ const { toggleDarkMode } = useTheme() let newPassword = $ref("") let newPasswordConfirmation = $ref("") let passwordFormMessage = $ref(null) +let isLoading = $ref(false) + +async function onToggleDarkMode() { + isLoading = true + await toggleDarkMode() + isLoading = false +} function canChangePassword(): boolean { return newPassword && newPassword === newPasswordConfirmation