Skip to content

Commit

Permalink
Fixes for #63 #64 & #65
Browse files Browse the repository at this point in the history
issue #65 still needs some more fixing up, but the other 2 are bueno
  • Loading branch information
beebls committed Feb 2, 2023
1 parent e88deb0 commit d0d2fd9
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 96 deletions.
190 changes: 97 additions & 93 deletions src/components/AllThemesModal.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useEffect, useRef, useState } from "react";
import {
ButtonItem,
DialogButton,
Expand All @@ -7,13 +8,13 @@ import {
showModal,
ToggleField,
} from "decky-frontend-lib";
import { BsPinAngle, BsPinAngleFill } from "react-icons/bs";
import { CssLoaderContextProvider, CssLoaderState, useCssLoaderState } from "../state";
import { ThemeSettingsModalRoot } from "./ThemeSettingsModal";
import * as python from "../python";
import { Flags } from "../ThemeTypes";
import { Flags, Theme } from "../ThemeTypes";
import { ImCog } from "react-icons/im";
import { CreatePresetModal } from "./CreatePresetModal";
import { AiFillEye, AiOutlineEyeInvisible } from "react-icons/ai";

export function AllThemesModalRoot({
stateClass,
Expand All @@ -38,7 +39,23 @@ export function AllThemesModal({
stateClass: CssLoaderState;
closeModal: any;
}) {
const { localThemeList, unpinnedThemes, setGlobalState } = useCssLoaderState();
const { localThemeList, unpinnedThemes } = useCssLoaderState();
const [sortedList, setSortedList] = useState<Theme[]>([]);

useEffect(() => {
setSortedList(
localThemeList.sort((a, b) => {
const aPinned = !unpinnedThemes.includes(a.id);
const bPinned = !unpinnedThemes.includes(b.id);
// This sorts the pinned themes alphabetically, then the non-pinned alphabetically
if (aPinned === bPinned) {
return a.name.localeCompare(b.name);
}
return Number(bPinned) - Number(aPinned);
})
);
}, [localThemeList.length]);

return (
<>
<h1 style={{ marginBlockEnd: "10px", marginBlockStart: "0px" }}>Your Themes</h1>
Expand Down Expand Up @@ -81,100 +98,87 @@ export function AllThemesModal({
`}
</style>
<Focusable style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gridGap: "1em" }}>
{localThemeList
.sort((a, b) => {
const aPinned = !unpinnedThemes.includes(a.id);
const bPinned = !unpinnedThemes.includes(b.id);
// This sorts the pinned themes alphabetically, then the non-pinned alphabetically
if (aPinned === bPinned) {
return a.name.localeCompare(b.name);
}
return Number(bPinned) - Number(aPinned);
})
.map((e) => {
const isPinned = !unpinnedThemes.includes(e.id);
return (
<>
<div className="CSSLoader_FullTheme_EntryContainer">
<div className="CSSLoader_FullTheme_ToggleContainer">
<ToggleField
bottomSeparator="none"
label={<span className="CSSLoader_FullTheme_ThemeLabel">{e.name}</span>}
checked={e.enabled}
onChange={(switchValue: boolean) => {
// Actually enabling the theme
python.resolve(python.setThemeState(e.name, switchValue), () => {
python.getInstalledThemes();
});
// Dependency Toast
if (e.dependencies.length > 0) {
if (switchValue === true) {
python.toast(
`${e.name} enabled other themes`,
// This lists out the themes by name, but often overflowed off screen
// @ts-ignore
// `${new Intl.ListFormat().format(data.dependencies)} ${
// data.dependencies.length > 1 ? "are" : "is"
// } required for this theme`
// This just gives the number of themes
`${
e.dependencies.length === 1
? `1 other theme is required by ${e.name}`
: `${e.dependencies.length} other themes are required by ${e.name}`
}`
);
return;
}
if (!e.flags.includes(Flags.dontDisableDeps)) {
python.toast(
`${e.name} disabled other themes`,
// @ts-ignore
`${
e.dependencies.length === 1
? `1 theme was originally enabled by ${e.name}`
: `${e.dependencies.length} themes were originally enabled by ${e.name}`
}`
);
return;
}
{sortedList.map((e, i) => {
const isPinned = !unpinnedThemes.includes(e.id);
return (
<>
<div className="CSSLoader_FullTheme_EntryContainer">
<div className="CSSLoader_FullTheme_ToggleContainer">
<ToggleField
bottomSeparator="none"
label={<span className="CSSLoader_FullTheme_ThemeLabel">{e.name}</span>}
checked={e.enabled}
onChange={(switchValue: boolean) => {
// Actually enabling the theme
python.resolve(python.setThemeState(e.name, switchValue), () => {
python.getInstalledThemes();
});
// Dependency Toast
if (e.dependencies.length > 0) {
if (switchValue === true) {
python.toast(
`${e.name} enabled other themes`,
// This lists out the themes by name, but often overflowed off screen
// @ts-ignore
// `${new Intl.ListFormat().format(data.dependencies)} ${
// data.dependencies.length > 1 ? "are" : "is"
// } required for this theme`
// This just gives the number of themes
`${
e.dependencies.length === 1
? `1 other theme is required by ${e.name}`
: `${e.dependencies.length} other themes are required by ${e.name}`
}`
);
return;
}
if (!e.flags.includes(Flags.dontDisableDeps)) {
python.toast(
`${e.name} disabled other themes`,
// @ts-ignore
`${
e.dependencies.length === 1
? `1 theme was originally enabled by ${e.name}`
: `${e.dependencies.length} themes were originally enabled by ${e.name}`
}`
);
return;
}
}}
/>
</div>
<DialogButton
className="CSSLoader_FullTheme_DialogButton"
onClick={() => {
if (isPinned) {
python.unpinTheme(e.id);
} else {
python.pinTheme(e.id);
}
}}
>
{isPinned ? (
<BsPinAngleFill
color="#FFA500"
className="CSSLoader_FullTheme_IconTranslate"
/>
) : (
<BsPinAngle className="CSSLoader_FullTheme_IconTranslate" />
)}
</DialogButton>
<DialogButton
className="CSSLoader_FullTheme_DialogButton"
onClick={() => {
showModal(
// @ts-ignore
<ThemeSettingsModalRoot stateClass={stateClass} selectedTheme={e.id} />
);
}}
>
<ImCog className="CSSLoader_FullTheme_IconTranslate" />
</DialogButton>
/>
</div>
</>
);
})}
<DialogButton
className="CSSLoader_FullTheme_DialogButton"
onClick={() => {
if (isPinned) {
python.unpinTheme(e.id);
} else {
python.pinTheme(e.id);
}
}}
>
{isPinned ? (
<AiFillEye className="CSSLoader_FullTheme_IconTranslate" />
) : (
<AiOutlineEyeInvisible className="CSSLoader_FullTheme_IconTranslate" />
)}
</DialogButton>
<DialogButton
className="CSSLoader_FullTheme_DialogButton"
onClick={() => {
showModal(
// @ts-ignore
<ThemeSettingsModalRoot stateClass={stateClass} selectedTheme={e.id} />
);
}}
>
<ImCog className="CSSLoader_FullTheme_IconTranslate" />
</DialogButton>
</div>
</>
);
})}
</Focusable>
<PanelSectionRow>
<ButtonItem
Expand Down
13 changes: 10 additions & 3 deletions src/components/ThemeToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ButtonItem, DialogButton, PanelSectionRow, ToggleField } from "decky-frontend-lib";
import { VFC, useState } from "react";
import { ButtonItem, PanelSectionRow, ToggleField } from "decky-frontend-lib";
import { VFC, useState, useMemo } from "react";
import { Flags, Theme } from "../ThemeTypes";

import * as python from "../python";
Expand All @@ -11,6 +11,13 @@ export const ThemeToggle: VFC<{ data: Theme; collapsible?: boolean }> = ({
collapsible = false,
}) => {
const [collapsed, setCollapsed] = useState<boolean>(true);
const isPreset = useMemo(() => {
if (data.flags.includes(Flags.isPreset)) {
return true;
}
return false;
// This might not actually memoize it as data.flags is an array, so idk if it deep checks the values here
}, [data.flags]);

return (
<>
Expand All @@ -19,7 +26,7 @@ export const ThemeToggle: VFC<{ data: Theme; collapsible?: boolean }> = ({
bottomSeparator={data.enabled && data?.patches?.length > 0 ? "none" : "standard"}
checked={data.enabled}
label={data.name}
description={`${data.version} | ${data.author}`}
description={isPreset ? `Preset` : `${data.version} | ${data.author}`}
onChange={(switchValue: boolean) => {
// Actually enabling the theme
python.resolve(python.setThemeState(data.name, switchValue), () => {
Expand Down

0 comments on commit d0d2fd9

Please sign in to comment.