move some settings to server side

This commit is contained in:
sam 2023-09-09 00:58:02 +02:00
parent 6c8f2b648e
commit c780470afe
No known key found for this signature in database
GPG Key ID: B4EF20DDE721CAA1
5 changed files with 107 additions and 27 deletions

View File

@ -62,6 +62,11 @@ export interface MeUser extends User {
timezone: string | null;
}
export interface Settings {
read_changelog: string;
read_settings_notice: string;
}
export interface Field {
name: string;
entries: FieldEntry[];

View File

@ -11,9 +11,16 @@ export async function apiFetch<T>(
body,
token,
headers,
}: { method?: string; body?: any; token?: string; headers?: Record<string, string> },
version,
}: {
method?: string;
body?: any;
token?: string;
headers?: Record<string, string>;
version?: number;
},
) {
const resp = await fetch(`${PUBLIC_BASE_URL}/api/v1${path}`, {
const resp = await fetch(`${PUBLIC_BASE_URL}/api/v${version || 1}${path}`, {
method: method || "GET",
headers: {
...(token ? { Authorization: token } : {}),
@ -28,12 +35,18 @@ export async function apiFetch<T>(
return data as T;
}
export const apiFetchClient = async <T>(path: string, method = "GET", body: any = null) => {
export const apiFetchClient = async <T>(
path: string,
method = "GET",
body: any = null,
version = 1,
) => {
try {
const data = await apiFetch<T>(path, {
method,
body,
token: localStorage.getItem("pronouns-token") || undefined,
version,
});
return data;
} catch (e) {
@ -55,9 +68,16 @@ export async function fastFetch(
body,
token,
headers,
}: { method?: string; body?: any; token?: string; headers?: Record<string, string> },
version,
}: {
method?: string;
body?: any;
token?: string;
headers?: Record<string, string>;
version?: number;
},
) {
const resp = await fetch(`${PUBLIC_BASE_URL}/api/v1${path}`, {
const resp = await fetch(`${PUBLIC_BASE_URL}/api/v${version || 1}${path}`, {
method: method || "GET",
headers: {
...(token ? { Authorization: token } : {}),
@ -71,12 +91,18 @@ export async function fastFetch(
}
/** Fetches the specified path without parsing the response body. */
export const fastFetchClient = async (path: string, method = "GET", body: any = null) => {
export const fastFetchClient = async (
path: string,
method = "GET",
body: any = null,
version = 1,
) => {
try {
await fastFetch(path, {
method,
body,
token: localStorage.getItem("pronouns-token") || undefined,
version,
});
} catch (e) {
if ((e as APIError).code === ErrorCode.InvalidToken) {

View File

@ -1,7 +1,7 @@
import { writable } from "svelte/store";
import { browser } from "$app/environment";
import type { MeUser } from "./api/entities";
import type { MeUser, Settings } from "./api/entities";
const initialUserValue = null;
export const userStore = writable<MeUser | null>(initialUserValue);
@ -13,4 +13,10 @@ const initialThemeValue = browser
export const themeStore = writable<string>(initialThemeValue);
const defaultSettingsValue = {
settings: { read_changelog: "0.0.0", read_settings_notice: "0" } as Settings,
current: false,
};
export const settingsStore = writable(defaultSettingsValue);
export const CURRENT_CHANGELOG = "0.6.0";

View File

@ -17,13 +17,14 @@
} from "sveltestrap";
import Logo from "./Logo.svelte";
import { userStore, themeStore, CURRENT_CHANGELOG } from "$lib/store";
import { userStore, themeStore, CURRENT_CHANGELOG, settingsStore } from "$lib/store";
import {
ErrorCode,
type APIError,
type MeUser,
type Report,
type Warning,
type Settings,
} from "$lib/api/entities";
import { apiFetch, apiFetchClient } from "$lib/api/fetch";
import { addToast } from "$lib/toast";
@ -37,14 +38,11 @@
let isAdmin = false;
let numReports = 0;
let numWarnings = 0;
let changelogRead = "99.99.99";
$: currentUser = $userStore;
$: theme = $themeStore;
onMount(() => {
changelogRead = localStorage.getItem("changelog-read") || "0.0.0";
const localUser = localStorage.getItem("pronouns-user");
userStore.set(localUser ? JSON.parse(localUser) : null);
@ -78,6 +76,38 @@
});
}
apiFetchClient<Settings>("/users/@me/settings", "GET", null, 2)
.then((data) => {
settingsStore.set({ current: true, settings: data });
})
.catch((e) => {
console.log("getting user settings:", e);
});
// TODO: is there a cleaner way to do this? also, remove this eventually
const oldChangelogRead = localStorage.getItem("changelog-read");
const oldSettingsNotice = localStorage.getItem("alert-1681976313");
if (oldChangelogRead || oldSettingsNotice) {
localStorage.removeItem("changelog-read");
localStorage.removeItem("alert-1681976313");
apiFetchClient<Settings>(
"/users/@me/settings",
"PATCH",
{
read_changelog: oldChangelogRead ? oldChangelogRead : undefined,
read_settings_notice: oldSettingsNotice ? "1681976313" : undefined,
},
2,
)
.then((data) => {
settingsStore.set({ current: true, settings: data });
})
.catch((e) => {
console.log("updating user settings:", e);
});
}
apiFetchClient<Warning[]>("/auth/warnings")
.then((warnings) => {
if (warnings.length !== 0) {
@ -157,7 +187,7 @@
</NavLink>
</NavItem>
{/if}
{#if changelogRead < CURRENT_CHANGELOG}
{#if $settingsStore.current && $settingsStore.settings.read_changelog < CURRENT_CHANGELOG}
<NavItem>
<NavLink href="/page/changelog" active={$page.url.pathname === "/page/changelog"}>
Changelog <Badge color="secondary">v{CURRENT_CHANGELOG}</Badge>

View File

@ -6,12 +6,13 @@
type APIError,
MAX_MEMBERS,
MAX_FIELDS,
type Settings,
} from "$lib/api/entities";
import { apiFetchClient, fastFetchClient } from "$lib/api/fetch";
import { usernameRegex } from "$lib/api/regex";
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
import FallbackImage from "$lib/components/FallbackImage.svelte";
import { userStore } from "$lib/store";
import { settingsStore, userStore } from "$lib/store";
import { addToast } from "$lib/toast";
import {
Alert,
@ -91,21 +92,36 @@
}
};
const DONATE_ALERT_STORE = "alert-1681976313";
let donateAlertOpen = false;
const closeDonateAlert = () => {
donateAlertOpen = false;
localStorage.setItem(DONATE_ALERT_STORE, "dismissed");
};
const CURRENT_ALERT = "1681976313";
const closeDonateAlert = async () => {
try {
const settings = await apiFetchClient<Settings>(
"/users/@me/settings",
"PATCH",
{
read_settings_notice: CURRENT_ALERT,
},
2,
);
onMount(() => {
if (!localStorage.getItem(DONATE_ALERT_STORE)) {
donateAlertOpen = true;
settingsStore.set({ current: true, settings });
error = null;
} catch (e) {
error = e as APIError;
}
});
};
</script>
<Alert color="secondary" fade={false} isOpen={donateAlertOpen} toggle={closeDonateAlert}>
{#if error}
<ErrorAlert {error} />
{/if}
<Alert
color="secondary"
fade={false}
isOpen={$settingsStore.current && $settingsStore.settings.read_settings_notice < CURRENT_ALERT}
toggle={closeDonateAlert}
>
If you find pronouns.cc useful and have the means, I would really appreciate a <a
href="https://liberapay.com/u1f320/"
target="_blank">donation</a
@ -150,9 +166,6 @@
{/if}
</p>
{/if}
{#if error}
<ErrorAlert {error} />
{/if}
</div>
<div class="col-lg-4">
<p class="text-center">