mirror of
https://github.com/movie-web/movie-web.git
synced 2024-12-27 00:16:05 +00:00
Language dropdown, language in settings, add temporary confirmation to delete account
This commit is contained in:
parent
54cd1d52ca
commit
2b23353e40
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
@ -4,5 +4,8 @@
|
||||||
"eslint.format.enable": true,
|
"eslint.format.enable": true,
|
||||||
"[json]": {
|
"[json]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[typescriptreact]": {
|
||||||
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
||||||
}
|
}
|
||||||
}
|
}
|
1
public/skull.svg
Normal file
1
public/skull.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#CCD6DD" d="M27.865 16.751c0-6.242-4.411-9.988-9.927-9.988s-9.835 3.746-9.835 9.988c0 3.48-.103 6.485 3.897 7.89v2.722c0 1.034.966 1.872 2 1.872 1.035 0 2-.838 2-1.872v-1.97 1.97c0 1.034.965 1.872 2 1.872 1.036 0 2-.838 2-1.872v-1.97 1.97c0 1.034.966 1.872 2 1.872s2-.838 2-1.872v-2.722c4-1.405 3.865-4.41 3.865-7.89z"/><circle fill="#292F33" cx="13.629" cy="15.503" r="3.121"/><path fill="#292F33" d="M25.488 15.503c0 1.724 0 3.121-3.121 3.121-3.12 0-3.12-1.397-3.12-3.121s1.396-3.121 3.12-3.121c1.725 0 3.121 1.397 3.121 3.121zm-6.301 5.656c-.157-.382-.626-.662-1.189-.662-.561 0-1.031.28-1.188.662-.394.11-.685.469-.685.898 0 .517.419.936.937.936.409 0 .753-.263.88-.628.019 0 .037.004.056.004.019 0 .037-.004.057-.004.128.365.472.628.88.628.517 0 .936-.419.936-.936 0-.429-.291-.786-.684-.898z"/><path d="M11 27c0-.367.075-.713.195-1.038-.984-.447-1.831-1.082-2.503-1.97-1.107.969-2.163 1.876-3.127 2.695C4.985 26.26 4.275 26 3.5 26 1.567 26 0 27.566 0 29.5c0 1.778 1.33 3.229 3.046 3.454C3.271 34.671 4.722 36 6.5 36c1.933 0 3.5-1.566 3.5-3.5 0-.775-.26-1.485-.686-2.065.6-.706 1.246-1.46 1.931-2.25C11.088 27.821 11 27.421 11 27zm16.872-15.482c.884-.769 1.729-1.495 2.515-2.163.569.403 1.262.645 2.013.645 1.934 0 3.5-1.567 3.5-3.5 0-1.743-1.277-3.177-2.945-3.444C32.735 1.335 31.281 0 29.5 0 27.566 0 26 1.567 26 3.5c0 .775.26 1.485.687 2.065-.594.7-1.233 1.445-1.911 2.227 1.3.871 2.361 2.095 3.096 3.726zM3.5 10c.775 0 1.485-.26 2.065-.687.799.679 1.661 1.419 2.564 2.204.735-1.631 1.795-2.855 3.096-3.726-.679-.781-1.317-1.527-1.912-2.226.427-.58.687-1.29.687-2.065C10 1.567 8.433 0 6.5 0 4.722 0 3.271 1.33 3.046 3.046 1.33 3.271 0 4.722 0 6.5 0 8.433 1.567 10 3.5 10zm28.9 16c-.752 0-1.444.242-2.014.645-.952-.809-1.99-1.701-3.079-2.653-.672.889-1.519 1.523-2.503 1.971.121.324.196.67.196 1.037 0 .421-.088.821-.245 1.185.685.79 1.331 1.544 1.931 2.25-.426.58-.686 1.29-.686 2.065 0 1.934 1.566 3.5 3.5 3.5 1.781 0 3.235-1.334 3.455-3.056 1.668-.267 2.945-1.701 2.945-3.444 0-1.934-1.566-3.5-3.5-3.5z" fill="#AAB8C2"/></svg>
|
After Width: | Height: | Size: 2.1 KiB |
|
@ -6,6 +6,7 @@ import { Icon, Icons } from "@/components/Icon";
|
||||||
export interface OptionItem {
|
export interface OptionItem {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
leftIcon?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DropdownProps {
|
interface DropdownProps {
|
||||||
|
@ -20,12 +21,17 @@ export function Dropdown(props: DropdownProps) {
|
||||||
<Listbox value={props.selectedItem} onChange={props.setSelectedItem}>
|
<Listbox value={props.selectedItem} onChange={props.setSelectedItem}>
|
||||||
{({ open }) => (
|
{({ open }) => (
|
||||||
<>
|
<>
|
||||||
<Listbox.Button className="relative w-full cursor-default rounded-lg bg-denim-500 py-2 pl-3 pr-10 text-left text-white shadow-md focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-bink-500 focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-bink-300 sm:text-sm">
|
<Listbox.Button className="relative w-full cursor-default rounded-lg bg-dropdown-background py-3 pl-3 pr-10 text-left text-white shadow-md focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-bink-500 focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-bink-300">
|
||||||
<span className="block truncate">{props.selectedItem.name}</span>
|
<span className="flex gap-4 items-center truncate">
|
||||||
|
{props.selectedItem.leftIcon
|
||||||
|
? props.selectedItem.leftIcon
|
||||||
|
: null}
|
||||||
|
{props.selectedItem.name}
|
||||||
|
</span>
|
||||||
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
||||||
<Icon
|
<Icon
|
||||||
icon={Icons.CHEVRON_DOWN}
|
icon={Icons.CHEVRON_DOWN}
|
||||||
className={`transform transition-transform ${
|
className={`transform transition-transform text-xl ${
|
||||||
open ? "rotate-180" : ""
|
open ? "rotate-180" : ""
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
|
@ -37,17 +43,18 @@ export function Dropdown(props: DropdownProps) {
|
||||||
leaveFrom="opacity-100"
|
leaveFrom="opacity-100"
|
||||||
leaveTo="opacity-0"
|
leaveTo="opacity-0"
|
||||||
>
|
>
|
||||||
<Listbox.Options className="absolute left-0 right-0 top-10 z-10 mt-1 max-h-60 overflow-auto rounded-md bg-denim-500 py-1 text-white shadow-lg ring-1 ring-black ring-opacity-5 scrollbar-thin scrollbar-track-denim-400 scrollbar-thumb-denim-200 focus:outline-none sm:top-10 sm:text-sm">
|
<Listbox.Options className="absolute left-0 right-0 top-10 z-[1] mt-4 max-h-60 overflow-auto rounded-md bg-dropdown-background py-1 text-white shadow-lg ring-1 ring-black ring-opacity-5 scrollbar-thin scrollbar-track-denim-400 scrollbar-thumb-denim-200 focus:outline-none sm:top-10">
|
||||||
{props.options.map((opt) => (
|
{props.options.map((opt) => (
|
||||||
<Listbox.Option
|
<Listbox.Option
|
||||||
className={({ active }) =>
|
className={({ active }) =>
|
||||||
`relative cursor-default select-none py-2 pl-10 pr-4 ${
|
`flex gap-4 items-center relative cursor-default select-none py-3 pl-4 pr-4 ${
|
||||||
active ? "bg-denim-400 text-bink-700" : "text-white"
|
active ? "bg-denim-400 text-bink-700" : "text-white"
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
key={opt.id}
|
key={opt.id}
|
||||||
value={opt}
|
value={opt}
|
||||||
>
|
>
|
||||||
|
{opt.leftIcon ? opt.leftIcon : null}
|
||||||
{opt.name}
|
{opt.name}
|
||||||
</Listbox.Option>
|
</Listbox.Option>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -6,11 +6,40 @@ export interface FlagIconProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FlagIcon(props: FlagIconProps) {
|
export function FlagIcon(props: FlagIconProps) {
|
||||||
|
// Country code overrides
|
||||||
|
const countryOverrides: Record<string, string> = {
|
||||||
|
en: "gb",
|
||||||
|
cs: "cz",
|
||||||
|
el: "gr",
|
||||||
|
fa: "ir",
|
||||||
|
ko: "kr",
|
||||||
|
he: "il",
|
||||||
|
ze: "cn",
|
||||||
|
ar: "sa",
|
||||||
|
ja: "jp",
|
||||||
|
bs: "ba",
|
||||||
|
vi: "vn",
|
||||||
|
zh: "cn",
|
||||||
|
sl: "si",
|
||||||
|
};
|
||||||
|
|
||||||
|
let countryCode =
|
||||||
|
(props.countryCode || "")?.split("-").pop()?.toLowerCase() || "";
|
||||||
|
if (countryOverrides[countryCode])
|
||||||
|
countryCode = countryOverrides[countryCode];
|
||||||
|
|
||||||
|
if (countryCode === "pirate")
|
||||||
|
return (
|
||||||
|
<div className="w-8 h-6 rounded bg-[#2E3439] flex justify-center items-center">
|
||||||
|
<img src="/skull.svg" className="w-4 h-4" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"!w-8 h-6 rounded overflow-hidden bg-video-context-flagBg bg-cover bg-center block fi",
|
"!w-8 h-6 rounded overflow-hidden bg-video-context-flagBg bg-cover bg-center block fi",
|
||||||
props.countryCode ? `fi-${props.countryCode}` : undefined
|
props.countryCode ? `fi-${countryCode}` : undefined
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { getLanguageFromIETF } from "@/components/player/utils/language";
|
||||||
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
|
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
|
||||||
import { usePlayerStore } from "@/stores/player/store";
|
import { usePlayerStore } from "@/stores/player/store";
|
||||||
import { useSubtitleStore } from "@/stores/subtitles";
|
import { useSubtitleStore } from "@/stores/subtitles";
|
||||||
|
import { sortLangCodes } from "@/utils/sortLangCodes";
|
||||||
|
|
||||||
export function CaptionOption(props: {
|
export function CaptionOption(props: {
|
||||||
countryCode?: string;
|
countryCode?: string;
|
||||||
|
@ -22,24 +23,6 @@ export function CaptionOption(props: {
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
error?: React.ReactNode;
|
error?: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
// Country code overrides
|
|
||||||
const countryOverrides: Record<string, string> = {
|
|
||||||
en: "gb",
|
|
||||||
cs: "cz",
|
|
||||||
el: "gr",
|
|
||||||
fa: "ir",
|
|
||||||
ko: "kr",
|
|
||||||
he: "il",
|
|
||||||
ze: "cn",
|
|
||||||
ar: "sa",
|
|
||||||
ja: "jp",
|
|
||||||
bs: "ba",
|
|
||||||
};
|
|
||||||
let countryCode =
|
|
||||||
(props.countryCode || "")?.split("-").pop()?.toLowerCase() || "";
|
|
||||||
if (countryOverrides[countryCode])
|
|
||||||
countryCode = countryOverrides[countryCode];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SelectableLink
|
<SelectableLink
|
||||||
selected={props.selected}
|
selected={props.selected}
|
||||||
|
@ -52,7 +35,7 @@ export function CaptionOption(props: {
|
||||||
className="flex items-center"
|
className="flex items-center"
|
||||||
>
|
>
|
||||||
<span data-code={props.countryCode} className="mr-3">
|
<span data-code={props.countryCode} className="mr-3">
|
||||||
<FlagIcon countryCode={countryCode} />
|
<FlagIcon countryCode={props.countryCode} />
|
||||||
</span>
|
</span>
|
||||||
<span>{props.children}</span>
|
<span>{props.children}</span>
|
||||||
</span>
|
</span>
|
||||||
|
@ -64,19 +47,12 @@ function searchSubs(
|
||||||
subs: (SubtitleSearchItem & { languageName: string })[],
|
subs: (SubtitleSearchItem & { languageName: string })[],
|
||||||
searchQuery: string
|
searchQuery: string
|
||||||
) {
|
) {
|
||||||
const languagesOrder = ["en", "hi", "fr", "de", "nl", "pt"].reverse(); // Reverse is neccesary, not sure why
|
const sorted = sortLangCodes(subs.map((t) => t.attributes.language));
|
||||||
|
|
||||||
let results = subs.sort((a, b) => {
|
let results = subs.sort((a, b) => {
|
||||||
if (
|
return (
|
||||||
languagesOrder.indexOf(b.attributes.language) !== -1 ||
|
sorted.indexOf(a.attributes.language) -
|
||||||
languagesOrder.indexOf(a.attributes.language) !== -1
|
sorted.indexOf(b.attributes.language)
|
||||||
)
|
);
|
||||||
return (
|
|
||||||
languagesOrder.indexOf(b.attributes.language) -
|
|
||||||
languagesOrder.indexOf(a.attributes.language)
|
|
||||||
);
|
|
||||||
|
|
||||||
return a.languageName.localeCompare(b.languageName);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (searchQuery.trim().length > 0) {
|
if (searchQuery.trim().length > 0) {
|
||||||
|
@ -152,7 +128,7 @@ export function CaptionsView({ id }: { id: string }) {
|
||||||
if (req.loading) content = <p>loading...</p>;
|
if (req.loading) content = <p>loading...</p>;
|
||||||
else if (req.error) content = <p>errored!</p>;
|
else if (req.error) content = <p>errored!</p>;
|
||||||
else if (req.value) {
|
else if (req.value) {
|
||||||
const subs = req.value.map((v) => {
|
const subs = req.value.filter(Boolean).map((v) => {
|
||||||
const languageName =
|
const languageName =
|
||||||
getLanguageFromIETF(v.attributes.language) ?? "unknown";
|
getLanguageFromIETF(v.attributes.language) ?? "unknown";
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { AccountWithToken, useAuthStore } from "@/stores/auth";
|
||||||
import { useThemeStore } from "@/stores/theme";
|
import { useThemeStore } from "@/stores/theme";
|
||||||
|
|
||||||
import { SubPageLayout } from "./layouts/SubPageLayout";
|
import { SubPageLayout } from "./layouts/SubPageLayout";
|
||||||
|
import { LocalePart } from "./settings/LocalePart";
|
||||||
|
|
||||||
function SettingsLayout(props: { children: React.ReactNode }) {
|
function SettingsLayout(props: { children: React.ReactNode }) {
|
||||||
const { isMobile } = useIsMobile();
|
const { isMobile } = useIsMobile();
|
||||||
|
@ -79,6 +80,9 @@ export function SettingsPage() {
|
||||||
<RegisterCalloutPart />
|
<RegisterCalloutPart />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div id="settings-locale">
|
||||||
|
<LocalePart />
|
||||||
|
</div>
|
||||||
<div id="settings-appearance">
|
<div id="settings-appearance">
|
||||||
<ThemePart active={activeTheme} setTheme={setTheme} />
|
<ThemePart active={activeTheme} setTheme={setTheme} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,6 +14,8 @@ export function AccountActionsPart() {
|
||||||
const { logout } = useAuthData();
|
const { logout } = useAuthData();
|
||||||
const [deleteResult, deleteExec] = useAsyncFn(async () => {
|
const [deleteResult, deleteExec] = useAsyncFn(async () => {
|
||||||
if (!account) return;
|
if (!account) return;
|
||||||
|
// eslint-disable-next-line no-restricted-globals
|
||||||
|
if (!confirm("You sure bro?")) return;
|
||||||
await deleteUser(url, account);
|
await deleteUser(url, account);
|
||||||
logout();
|
logout();
|
||||||
}, [logout, account, url]);
|
}, [logout, account, url]);
|
||||||
|
|
36
src/pages/settings/LocalePart.tsx
Normal file
36
src/pages/settings/LocalePart.tsx
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { Dropdown } from "@/components/Dropdown";
|
||||||
|
import { FlagIcon } from "@/components/FlagIcon";
|
||||||
|
import { Heading1 } from "@/components/utils/Text";
|
||||||
|
import { appLanguageOptions } from "@/setup/i18n";
|
||||||
|
import { useLanguageStore } from "@/stores/language";
|
||||||
|
import { sortLangCodes } from "@/utils/sortLangCodes";
|
||||||
|
|
||||||
|
export function LocalePart() {
|
||||||
|
const sorted = sortLangCodes(appLanguageOptions.map((t) => t.id));
|
||||||
|
const { language, setLanguage } = useLanguageStore();
|
||||||
|
|
||||||
|
const options = appLanguageOptions
|
||||||
|
.sort((a, b) => sorted.indexOf(a.id) - sorted.indexOf(b.id))
|
||||||
|
.map((opt) => ({
|
||||||
|
id: opt.id,
|
||||||
|
name: `${opt.englishName} — ${opt.nativeName}`,
|
||||||
|
leftIcon: <FlagIcon countryCode={opt.id} />,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const selected = options.find((t) => t.id === language);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Heading1 border>Locale</Heading1>
|
||||||
|
<p className="text-white font-bold mb-3">Application language</p>
|
||||||
|
<p className="max-w-[20rem] font-medium">
|
||||||
|
Language applied to the entire application.
|
||||||
|
</p>
|
||||||
|
<Dropdown
|
||||||
|
options={options}
|
||||||
|
selectedItem={selected || options[0]}
|
||||||
|
setSelectedItem={(opt) => setLanguage(opt.id)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ export function SidebarPart() {
|
||||||
|
|
||||||
const settingLinks = [
|
const settingLinks = [
|
||||||
{ text: "Account", id: "settings-account", icon: Icons.USER },
|
{ text: "Account", id: "settings-account", icon: Icons.USER },
|
||||||
|
{ text: "Locale", id: "settings-locale", icon: Icons.LINK },
|
||||||
{ text: "Appearance", id: "settings-appearance", icon: Icons.GITHUB },
|
{ text: "Appearance", id: "settings-appearance", icon: Icons.GITHUB },
|
||||||
{ text: "Captions", id: "settings-captions", icon: Icons.CAPTIONS },
|
{ text: "Captions", id: "settings-captions", icon: Icons.CAPTIONS },
|
||||||
];
|
];
|
||||||
|
@ -35,10 +36,10 @@ export function SidebarPart() {
|
||||||
|
|
||||||
const visible = !(
|
const visible = !(
|
||||||
Math.floor(
|
Math.floor(
|
||||||
100 - ((rect.top >= 0 ? 0 : rect.top) / +-rect.height) * 100
|
50 - ((rect.top >= 0 ? 0 : rect.top) / +-rect.height) * 100
|
||||||
) < percentageVisible ||
|
) < percentageVisible ||
|
||||||
Math.floor(
|
Math.floor(
|
||||||
100 - ((rect.bottom - windowHeight) / rect.height) * 100
|
50 - ((rect.bottom - windowHeight) / rect.height) * 100
|
||||||
) < percentageVisible
|
) < percentageVisible
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -80,6 +81,7 @@ export function SidebarPart() {
|
||||||
icon={v.icon}
|
icon={v.icon}
|
||||||
active={v.id === activeLink}
|
active={v.id === activeLink}
|
||||||
onClick={() => scrollTo(v.id)}
|
onClick={() => scrollTo(v.id)}
|
||||||
|
key={v.id}
|
||||||
>
|
>
|
||||||
{v.text}
|
{v.text}
|
||||||
</SidebarLink>
|
</SidebarLink>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
|
import { persist } from "zustand/middleware";
|
||||||
import { immer } from "zustand/middleware/immer";
|
import { immer } from "zustand/middleware/immer";
|
||||||
|
|
||||||
import i18n from "@/setup/i18n";
|
import i18n from "@/setup/i18n";
|
||||||
|
@ -10,14 +11,17 @@ export interface LanguageStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useLanguageStore = create(
|
export const useLanguageStore = create(
|
||||||
immer<LanguageStore>((set) => ({
|
persist(
|
||||||
language: "en",
|
immer<LanguageStore>((set) => ({
|
||||||
setLanguage(v) {
|
language: "en",
|
||||||
set((s) => {
|
setLanguage(v) {
|
||||||
s.language = v;
|
set((s) => {
|
||||||
});
|
s.language = v;
|
||||||
},
|
});
|
||||||
}))
|
},
|
||||||
|
})),
|
||||||
|
{ name: "__MW::locale" }
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
export function useLanguageListener() {
|
export function useLanguageListener() {
|
||||||
|
|
12
src/utils/sortLangCodes.ts
Normal file
12
src/utils/sortLangCodes.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
export function sortLangCodes(langCodes: string[]) {
|
||||||
|
const languagesOrder = ["en", "hi", "fr", "de", "nl", "pt"].reverse(); // Reverse is neccesary, not sure why
|
||||||
|
|
||||||
|
const results = langCodes.sort((a, b) => {
|
||||||
|
if (languagesOrder.indexOf(b) !== -1 || languagesOrder.indexOf(a) !== -1)
|
||||||
|
return languagesOrder.indexOf(b) - languagesOrder.indexOf(a);
|
||||||
|
|
||||||
|
return a.localeCompare(b);
|
||||||
|
});
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
|
@ -4,23 +4,23 @@ export const defaultTheme = {
|
||||||
themePreview: {
|
themePreview: {
|
||||||
primary: "#505DBD",
|
primary: "#505DBD",
|
||||||
secondary: "#73739D",
|
secondary: "#73739D",
|
||||||
ghost: "white"
|
ghost: "white",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Branding
|
// Branding
|
||||||
pill: {
|
pill: {
|
||||||
background: "#1C1C36"
|
background: "#1C1C36",
|
||||||
},
|
},
|
||||||
|
|
||||||
// meta data for the theme itself
|
// meta data for the theme itself
|
||||||
global: {
|
global: {
|
||||||
accentA: "#505DBD",
|
accentA: "#505DBD",
|
||||||
accentB: "#3440A1"
|
accentB: "#3440A1",
|
||||||
},
|
},
|
||||||
|
|
||||||
// light bar
|
// light bar
|
||||||
lightBar: {
|
lightBar: {
|
||||||
light: "#2A2A71"
|
light: "#2A2A71",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
|
@ -39,14 +39,14 @@ export const defaultTheme = {
|
||||||
purple: "#6b298a",
|
purple: "#6b298a",
|
||||||
purpleHover: "#7f35a1",
|
purpleHover: "#7f35a1",
|
||||||
cancel: "#252533",
|
cancel: "#252533",
|
||||||
cancelHover: "#3C3C4A"
|
cancelHover: "#3C3C4A",
|
||||||
},
|
},
|
||||||
|
|
||||||
// only used for body colors/textures
|
// only used for body colors/textures
|
||||||
background: {
|
background: {
|
||||||
main: "#0A0A10",
|
main: "#0A0A10",
|
||||||
accentA: "#6E3B80",
|
accentA: "#6E3B80",
|
||||||
accentB: "#1F1F50"
|
accentB: "#1F1F50",
|
||||||
},
|
},
|
||||||
|
|
||||||
// typography
|
// typography
|
||||||
|
@ -55,7 +55,7 @@ export const defaultTheme = {
|
||||||
text: "#73739D",
|
text: "#73739D",
|
||||||
dimmed: "#926CAD",
|
dimmed: "#926CAD",
|
||||||
divider: "#262632",
|
divider: "#262632",
|
||||||
secondary: "#64647B"
|
secondary: "#64647B",
|
||||||
},
|
},
|
||||||
|
|
||||||
// search bar
|
// search bar
|
||||||
|
@ -64,7 +64,7 @@ export const defaultTheme = {
|
||||||
focused: "#24243C",
|
focused: "#24243C",
|
||||||
placeholder: "#4A4A71",
|
placeholder: "#4A4A71",
|
||||||
icon: "#545476",
|
icon: "#545476",
|
||||||
text: "#FFFFFF"
|
text: "#FFFFFF",
|
||||||
},
|
},
|
||||||
|
|
||||||
// media cards
|
// media cards
|
||||||
|
@ -76,13 +76,18 @@ export const defaultTheme = {
|
||||||
barColor: "#4B4B63",
|
barColor: "#4B4B63",
|
||||||
barFillColor: "#BA7FD6",
|
barFillColor: "#BA7FD6",
|
||||||
badge: "#151522",
|
badge: "#151522",
|
||||||
badgeText: "#5F5F7A"
|
badgeText: "#5F5F7A",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Large card
|
// Large card
|
||||||
largeCard: {
|
largeCard: {
|
||||||
background: "#171728",
|
background: "#171728",
|
||||||
icon: "#6741A5"
|
icon: "#6741A5",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Dropdown
|
||||||
|
dropdown: {
|
||||||
|
background: "#171728",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Passphrase
|
// Passphrase
|
||||||
|
@ -92,7 +97,7 @@ export const defaultTheme = {
|
||||||
wordBackground: "#171728",
|
wordBackground: "#171728",
|
||||||
copyText: "#58587A",
|
copyText: "#58587A",
|
||||||
copyTextHover: "#8888AA",
|
copyTextHover: "#8888AA",
|
||||||
errorText: "#DB3D62"
|
errorText: "#DB3D62",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Settings page
|
// Settings page
|
||||||
|
@ -105,19 +110,19 @@ export const defaultTheme = {
|
||||||
inactive: "#8D68A9",
|
inactive: "#8D68A9",
|
||||||
icon: "#926CAD",
|
icon: "#926CAD",
|
||||||
iconActivated: "#6942A8",
|
iconActivated: "#6942A8",
|
||||||
activated: "#CBA1E8"
|
activated: "#CBA1E8",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
card: {
|
card: {
|
||||||
border: "#2A243E",
|
border: "#2A243E",
|
||||||
background: "#29243D",
|
background: "#29243D",
|
||||||
altBackground: "#29243D"
|
altBackground: "#29243D",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
utils: {
|
utils: {
|
||||||
divider: "#353549"
|
divider: "#353549",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Error page
|
// Error page
|
||||||
|
@ -126,20 +131,20 @@ export const defaultTheme = {
|
||||||
border: "#252534",
|
border: "#252534",
|
||||||
|
|
||||||
type: {
|
type: {
|
||||||
secondary: "#62627D"
|
secondary: "#62627D",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// About page
|
// About page
|
||||||
about: {
|
about: {
|
||||||
circle: "#262632",
|
circle: "#262632",
|
||||||
circleText: "#9A9AC3"
|
circleText: "#9A9AC3",
|
||||||
},
|
},
|
||||||
|
|
||||||
progress: {
|
progress: {
|
||||||
background: "#8787A8",
|
background: "#8787A8",
|
||||||
preloaded: "#8787A8",
|
preloaded: "#8787A8",
|
||||||
filled: "#A75FC9"
|
filled: "#A75FC9",
|
||||||
},
|
},
|
||||||
|
|
||||||
// video player
|
// video player
|
||||||
|
@ -151,11 +156,11 @@ export const defaultTheme = {
|
||||||
error: "#E44F4F",
|
error: "#E44F4F",
|
||||||
success: "#40B44B",
|
success: "#40B44B",
|
||||||
loading: "#B759D8",
|
loading: "#B759D8",
|
||||||
noresult: "#64647B"
|
noresult: "#64647B",
|
||||||
},
|
},
|
||||||
|
|
||||||
audio: {
|
audio: {
|
||||||
set: "#A75FC9"
|
set: "#A75FC9",
|
||||||
},
|
},
|
||||||
|
|
||||||
context: {
|
context: {
|
||||||
|
@ -175,16 +180,16 @@ export const defaultTheme = {
|
||||||
|
|
||||||
buttons: {
|
buttons: {
|
||||||
list: "#161C26",
|
list: "#161C26",
|
||||||
active: "#0D1317"
|
active: "#0D1317",
|
||||||
},
|
},
|
||||||
|
|
||||||
type: {
|
type: {
|
||||||
main: "#617A8A",
|
main: "#617A8A",
|
||||||
secondary: "#374A56",
|
secondary: "#374A56",
|
||||||
accent: "#A570FA"
|
accent: "#A570FA",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
Loading…
Reference in a new issue