Merge branch 'theme-discovery-presets' into development
This commit is contained in:
@@ -17,6 +17,7 @@ interface AuthData {
|
|||||||
colorScheme: MantineColorScheme;
|
colorScheme: MantineColorScheme;
|
||||||
theme?: string;
|
theme?: string;
|
||||||
locale?: string;
|
locale?: string;
|
||||||
|
seenThemesHint?: boolean;
|
||||||
};
|
};
|
||||||
roles: string[];
|
roles: string[];
|
||||||
phone: string;
|
phone: string;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { UnstyledButton } from "@mantine/core"
|
import { Tooltip, UnstyledButton } from "@mantine/core"
|
||||||
import { GearIcon } from "@phosphor-icons/react"
|
import { GearIcon } from "@phosphor-icons/react"
|
||||||
import { useNavigate } from "@tanstack/react-router"
|
import { useNavigate } from "@tanstack/react-router"
|
||||||
import { useLingui } from "@lingui/react/macro"
|
import { useLingui } from "@lingui/react/macro"
|
||||||
import { memo } from "react";
|
import { memo, useEffect, useState } from "react";
|
||||||
|
import { useThemeDiscovery } from "@/features/settings/hooks/use-theme-discovery";
|
||||||
|
|
||||||
interface SettingButtonProps {
|
interface SettingButtonProps {
|
||||||
to: string;
|
to: string;
|
||||||
@@ -10,21 +11,48 @@ interface SettingButtonProps {
|
|||||||
right?: number;
|
right?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HINT_SHOW_DELAY_MS = 900;
|
||||||
|
const HINT_VISIBLE_MS = 4000;
|
||||||
|
|
||||||
const SettingsButton = ({ to }: SettingButtonProps) => {
|
const SettingsButton = ({ to }: SettingButtonProps) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { t } = useLingui();
|
const { t } = useLingui();
|
||||||
|
const { showHint, markSeen } = useThemeDiscovery();
|
||||||
|
const [hintOpen, setHintOpen] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!showHint) return;
|
||||||
|
const show = setTimeout(() => setHintOpen(true), HINT_SHOW_DELAY_MS);
|
||||||
|
const hide = setTimeout(() => {
|
||||||
|
setHintOpen(false);
|
||||||
|
markSeen();
|
||||||
|
}, HINT_SHOW_DELAY_MS + HINT_VISIBLE_MS);
|
||||||
|
return () => {
|
||||||
|
clearTimeout(show);
|
||||||
|
clearTimeout(hide);
|
||||||
|
};
|
||||||
|
}, [showHint, markSeen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UnstyledButton
|
<Tooltip
|
||||||
aria-label={t`Settings`}
|
label={t`Try the new themes`}
|
||||||
style={{ cursor: 'pointer', zIndex: 1000, display: 'flex' }}
|
opened={hintOpen}
|
||||||
onClick={() => navigate({ to })}
|
withArrow
|
||||||
pos='absolute'
|
position="bottom-end"
|
||||||
right={20}
|
offset={8}
|
||||||
top={6}
|
transitionProps={{ transition: "fade-down", duration: 250 }}
|
||||||
>
|
>
|
||||||
<GearIcon weight='bold' size={20} />
|
<UnstyledButton
|
||||||
</UnstyledButton>
|
aria-label={t`Settings`}
|
||||||
|
style={{ cursor: 'pointer', zIndex: 1000, display: 'flex' }}
|
||||||
|
onClick={() => navigate({ to })}
|
||||||
|
pos='absolute'
|
||||||
|
right={20}
|
||||||
|
top={6}
|
||||||
|
>
|
||||||
|
<GearIcon weight='bold' size={20} />
|
||||||
|
</UnstyledButton>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { useCallback } from "react";
|
||||||
|
import { useAuth } from "@/contexts/auth-context";
|
||||||
|
import { updateUserSeenThemesHint } from "@/features/settings/server";
|
||||||
|
|
||||||
|
/** Drives the one-time "new themes" tooltip on the profile settings gear.
|
||||||
|
* markSeen persists the flag, so each account sees the hint only once. */
|
||||||
|
export const useThemeDiscovery = () => {
|
||||||
|
const { metadata, user, set } = useAuth();
|
||||||
|
const showHint = !!user && !metadata.seenThemesHint;
|
||||||
|
|
||||||
|
const markSeen = useCallback(() => {
|
||||||
|
if (!user || metadata.seenThemesHint) return;
|
||||||
|
set({ metadata: { ...metadata, seenThemesHint: true } });
|
||||||
|
void updateUserSeenThemesHint();
|
||||||
|
}, [user, metadata, set]);
|
||||||
|
|
||||||
|
return { showHint, markSeen };
|
||||||
|
};
|
||||||
@@ -95,6 +95,28 @@ export const updateUserTheme = createServerFn({ method: "POST" })
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const updateUserSeenThemesHint = createServerFn({ method: "POST" })
|
||||||
|
.middleware([superTokensFunctionMiddleware, serverFnLoggingMiddleware])
|
||||||
|
.handler(async ({ context }) => {
|
||||||
|
const { userAuthId, metadata } = context;
|
||||||
|
if (!userAuthId) return;
|
||||||
|
|
||||||
|
const { updateUserMetadataFields } = await import(
|
||||||
|
"@/utils/supertokens-core.server"
|
||||||
|
);
|
||||||
|
|
||||||
|
await updateUserMetadataFields(userAuthId, {
|
||||||
|
seenThemesHint: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
metadata: {
|
||||||
|
...metadata,
|
||||||
|
seenThemesHint: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
export const updateUserAccentColor = createServerFn({ method: "POST" })
|
export const updateUserAccentColor = createServerFn({ method: "POST" })
|
||||||
.validator((data: string) => data)
|
.validator((data: string) => data)
|
||||||
.middleware([superTokensFunctionMiddleware, serverFnLoggingMiddleware])
|
.middleware([superTokensFunctionMiddleware, serverFnLoggingMiddleware])
|
||||||
|
|||||||
@@ -2152,7 +2152,7 @@ msgid "serverFn name"
|
|||||||
msgstr "serverFn-Name"
|
msgstr "serverFn-Name"
|
||||||
|
|
||||||
#: src/app/routes/_authed/settings.tsx:16
|
#: src/app/routes/_authed/settings.tsx:16
|
||||||
#: src/features/core/components/settings-button.tsx:19
|
#: src/features/core/components/settings-button.tsx:46
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr "Einstellungen"
|
msgstr "Einstellungen"
|
||||||
|
|
||||||
@@ -2515,6 +2515,10 @@ msgstr "Turniere"
|
|||||||
msgid "trackId is required for playTrack action"
|
msgid "trackId is required for playTrack action"
|
||||||
msgstr "trackId ist für die playTrack-Aktion erforderlich"
|
msgstr "trackId ist für die playTrack-Aktion erforderlich"
|
||||||
|
|
||||||
|
#: src/features/core/components/settings-button.tsx:38
|
||||||
|
msgid "Try the new themes"
|
||||||
|
msgstr "Probier die neuen Designs aus"
|
||||||
|
|
||||||
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
|
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
|
||||||
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
|
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
|
||||||
msgid "Unenroll"
|
msgid "Unenroll"
|
||||||
|
|||||||
@@ -2152,7 +2152,7 @@ msgid "serverFn name"
|
|||||||
msgstr "serverFn name"
|
msgstr "serverFn name"
|
||||||
|
|
||||||
#: src/app/routes/_authed/settings.tsx:16
|
#: src/app/routes/_authed/settings.tsx:16
|
||||||
#: src/features/core/components/settings-button.tsx:19
|
#: src/features/core/components/settings-button.tsx:46
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr "Settings"
|
msgstr "Settings"
|
||||||
|
|
||||||
@@ -2515,6 +2515,10 @@ msgstr "Tournaments"
|
|||||||
msgid "trackId is required for playTrack action"
|
msgid "trackId is required for playTrack action"
|
||||||
msgstr "trackId is required for playTrack action"
|
msgstr "trackId is required for playTrack action"
|
||||||
|
|
||||||
|
#: src/features/core/components/settings-button.tsx:38
|
||||||
|
msgid "Try the new themes"
|
||||||
|
msgstr "Try the new themes"
|
||||||
|
|
||||||
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
|
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
|
||||||
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
|
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
|
||||||
msgid "Unenroll"
|
msgid "Unenroll"
|
||||||
|
|||||||
@@ -2152,7 +2152,7 @@ msgid "serverFn name"
|
|||||||
msgstr "nombre de serverFn"
|
msgstr "nombre de serverFn"
|
||||||
|
|
||||||
#: src/app/routes/_authed/settings.tsx:16
|
#: src/app/routes/_authed/settings.tsx:16
|
||||||
#: src/features/core/components/settings-button.tsx:19
|
#: src/features/core/components/settings-button.tsx:46
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr "Configuración"
|
msgstr "Configuración"
|
||||||
|
|
||||||
@@ -2515,6 +2515,10 @@ msgstr "Torneos"
|
|||||||
msgid "trackId is required for playTrack action"
|
msgid "trackId is required for playTrack action"
|
||||||
msgstr "Se requiere trackId para la acción playTrack"
|
msgstr "Se requiere trackId para la acción playTrack"
|
||||||
|
|
||||||
|
#: src/features/core/components/settings-button.tsx:38
|
||||||
|
msgid "Try the new themes"
|
||||||
|
msgstr "Prueba los nuevos temas"
|
||||||
|
|
||||||
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
|
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
|
||||||
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
|
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
|
||||||
msgid "Unenroll"
|
msgid "Unenroll"
|
||||||
|
|||||||
@@ -2152,7 +2152,7 @@ msgid "serverFn name"
|
|||||||
msgstr "serverFn名"
|
msgstr "serverFn名"
|
||||||
|
|
||||||
#: src/app/routes/_authed/settings.tsx:16
|
#: src/app/routes/_authed/settings.tsx:16
|
||||||
#: src/features/core/components/settings-button.tsx:19
|
#: src/features/core/components/settings-button.tsx:46
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr "設定"
|
msgstr "設定"
|
||||||
|
|
||||||
@@ -2515,6 +2515,10 @@ msgstr "トーナメント"
|
|||||||
msgid "trackId is required for playTrack action"
|
msgid "trackId is required for playTrack action"
|
||||||
msgstr "playTrackアクションにはtrackIdが必要です"
|
msgstr "playTrackアクションにはtrackIdが必要です"
|
||||||
|
|
||||||
|
#: src/features/core/components/settings-button.tsx:38
|
||||||
|
msgid "Try the new themes"
|
||||||
|
msgstr "新しいテーマを試してみましょう"
|
||||||
|
|
||||||
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
|
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
|
||||||
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
|
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
|
||||||
msgid "Unenroll"
|
msgid "Unenroll"
|
||||||
|
|||||||
Reference in New Issue
Block a user