diff --git a/src/modules/settings/profile/components/LoggedInView.tsx b/src/modules/settings/profile/components/LoggedInView.tsx
deleted file mode 100644
index 3c6ae7d..0000000
--- a/src/modules/settings/profile/components/LoggedInView.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { Focusable } from "@decky/ui";
-import { ProfileInstalledEntry } from "./ProfileInstalledEntry";
-import { useProfileContext } from "../state";
-import { SectionTitle } from "./SectionTitle";
-import { SectionSubtitle } from "./SectionSubtitle";
-import { ProfileUploadedEntry } from "./ProfileUploadedEntry";
-
-export function LoggedInView() {
- const { downloadedProfiles, localProfiles, uploadedProfiles } = useProfileContext();
- return (
-
-
- Downloaded Profiles
-
- {downloadedProfiles.map((profile) => (
-
- ))}
-
-
-
-
- Your Profiles
-
- Local
-
- {localProfiles.map((profile) => (
-
- ))}
-
-
-
- On DeckThemes
-
- {uploadedProfiles.map((profile) => (
-
- ))}
-
-
-
-
- );
-}
diff --git a/src/modules/settings/profile/components/LoggedOutView.tsx b/src/modules/settings/profile/components/LoggedOutView.tsx
deleted file mode 100644
index f2e57e1..0000000
--- a/src/modules/settings/profile/components/LoggedOutView.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { Focusable } from "@decky/ui";
-import { ProfileInstalledEntry } from "./ProfileInstalledEntry";
-import { useProfileContext } from "../state";
-import { SectionTitle } from "./SectionTitle";
-
-export function LoggedOutView() {
- const { downloadedProfiles, localProfiles } = useProfileContext();
- return (
-
-
- Downloaded Profiles
-
- {downloadedProfiles.map((profile) => (
-
- ))}
-
-
-
-
- Your Profiles
-
- {localProfiles.map((profile) => (
-
- ))}
-
-
-
- );
-}
diff --git a/src/modules/settings/profile/components/OnlineView.tsx b/src/modules/settings/profile/components/OnlineView.tsx
new file mode 100644
index 0000000..e558e2d
--- /dev/null
+++ b/src/modules/settings/profile/components/OnlineView.tsx
@@ -0,0 +1,52 @@
+import { Focusable } from "@decky/ui";
+import { ProfileInstalledEntry } from "./ProfileInstalledEntry";
+import { useProfileContext } from "../state";
+import { SectionTitle } from "./SectionTitle";
+import { SectionSubtitle } from "./SectionSubtitle";
+import { ProfileUploadedEntry } from "./ProfileUploadedEntry";
+
+export function OnlineView() {
+ const { downloadedProfiles, localProfiles, uploadedProfiles } = useProfileContext();
+ return (
+
+ {downloadedProfiles.length > 0 && (
+ <>
+
+ Downloaded Profiles
+
+ {downloadedProfiles.map((profile) => (
+
+ ))}
+
+
+
+ >
+ )}
+ {(localProfiles.length > 0 || uploadedProfiles.length > 0) && (
+
+ Your Profiles
+ {localProfiles.length > 0 && (
+
+ Local
+
+ {localProfiles.map((profile) => (
+
+ ))}
+
+
+ )}
+ {uploadedProfiles.length > 0 && (
+
+ On DeckThemes
+
+ {uploadedProfiles.map((profile) => (
+
+ ))}
+
+
+ )}
+
+ )}
+
+ );
+}
diff --git a/src/modules/settings/profile/components/index.ts b/src/modules/settings/profile/components/index.ts
index 13d5f51..cc4d39f 100644
--- a/src/modules/settings/profile/components/index.ts
+++ b/src/modules/settings/profile/components/index.ts
@@ -1,4 +1,2 @@
-export * from "./ProfileInstalledEntry";
-export * from "./ProfileUploadedEntry";
-export * from "./SectionSubtitle";
-export * from "./SectionTitle";
+export * from "./OfflineView";
+export * from "./OnlineView";
diff --git a/src/modules/settings/profile/pages/ProfileSettingsPage.tsx b/src/modules/settings/profile/pages/ProfileSettingsPage.tsx
index ab36895..5fee354 100644
--- a/src/modules/settings/profile/pages/ProfileSettingsPage.tsx
+++ b/src/modules/settings/profile/pages/ProfileSettingsPage.tsx
@@ -1,45 +1,37 @@
-import { useCSSLoaderActions, useCSSLoaderValues } from "@/backend";
import { PresetSelectionDropdown } from "@/lib";
-import { Flags, PartialCSSThemeInfo, Theme } from "@/types";
-import { DialogButton, Focusable } from "@decky/ui";
-import { useEffect, useMemo, useState } from "react";
+import { Focusable } from "@decky/ui";
import { ProfileContextProvider, useProfileContext } from "../state";
-import { OfflineView } from "../components/OfflineView";
-import { LoggedInView } from "../components/LoggedInView";
-import { LoggedOutView } from "../components/LoggedOutView";
+import { OfflineView, OnlineView } from "../components";
+import { ImSpinner5 } from "react-icons/im";
export function ProfileSettingsPage() {
return (
-
-
-
-
-
+
);
}
-function ProfileSettingsContent() {
+function ProfileSettingsPageContent() {
+ const { loading } = useProfileContext();
+ return (
+
+
+
+
+ {loading && (
+
+
+
+ )}
+
+ );
+}
+
+function ProfileSettingsModeSwitcher() {
const { displayMode } = useProfileContext();
- if (displayMode === "loggedin") {
- return ;
- }
- if (displayMode === "loggedout") {
- return ;
+ if (displayMode === "online") {
+ return ;
}
return ;
}
-
-// function UploadProfileButton() {
-// const { publishProfile } = useCSSLoaderActions();
-// return (
-// {
-// publishProfile("LCD Hero.profile", false);
-// }}
-// >
-// Upload Profile
-//
-// );
-// }
diff --git a/src/modules/settings/profile/state/ProfileContext.tsx b/src/modules/settings/profile/state/ProfileContext.tsx
index af83b16..c89c846 100644
--- a/src/modules/settings/profile/state/ProfileContext.tsx
+++ b/src/modules/settings/profile/state/ProfileContext.tsx
@@ -7,7 +7,8 @@ const ProfileContext = createContext({} as IProfileContext);
// TODO: Potentially this should be moved to @cssloader as it isn't decky dependent
// TODO: Also, this should be zustand using .subscribe on the cssloader store, I just was lazy implementing it this way here
interface IProfileContextValues {
- displayMode: "offline" | "loggedout" | "loggedin";
+ displayMode: "offline" | "online";
+ loading: boolean;
downloadedProfiles: Theme[];
localProfiles: Theme[];
uploadedProfiles: PartialCSSThemeInfo[];
@@ -24,15 +25,20 @@ export function ProfileContextProvider({ children }: { children: React.ReactNode
const { getUploadedThemes } = useCSSLoaderActions();
const profiles = themes.filter((e) => e.flags.includes(Flags.isPreset));
- const [displayMode, setDisplayMode] = useState<"offline" | "loggedout" | "loggedin">("offline");
- const localProfiles = profiles.filter(
- (e) => updateStatuses.find((status) => status[0] === e.id)?.[1] === "local"
- );
+ const [displayMode, setDisplayMode] = useState<"offline" | "online">("offline");
+ const [loading, setLoading] = useState(true);
const [uploadedProfileRemoteEntries, setUploadedProfileRemoteEntries] = useState<
PartialCSSThemeInfo[]
>([]);
+ const localProfiles = profiles.filter((e) => {
+ const isLocal = updateStatuses.find((status) => status[0] === e.id)?.[1] === "local";
+ const isInUploaded = uploadedProfileRemoteEntries.some(
+ (uploadedProfile) => uploadedProfile.id === e.id
+ );
+ return isLocal && !isInUploaded;
+ });
const downloadedProfiles = profiles.filter((profile) => {
const isInLocal = localProfiles.some((localProfile) => localProfile.id === profile.id);
const isInUploaded = uploadedProfileRemoteEntries.some(
@@ -46,18 +52,20 @@ export function ProfileContextProvider({ children }: { children: React.ReactNode
setDisplayMode("offline");
return;
}
+
+ setDisplayMode("online");
if (!apiMeData) {
- setDisplayMode("loggedout");
return;
}
+ setLoading(true);
// Logged in mode, separate downloaded and local, and show uploaded profiles
const uploadedThemes = await getUploadedThemes();
const uploadedProfileRemoteEntries = uploadedThemes.filter((theme) =>
theme.targets.includes("Profile")
);
setUploadedProfileRemoteEntries(uploadedProfileRemoteEntries);
- setDisplayMode("loggedin");
+ setLoading(false);
}
useEffect(() => {
@@ -68,6 +76,7 @@ export function ProfileContextProvider({ children }: { children: React.ReactNode
useContext(ProfileContext);
-
-// const profileStore = createStore((set, get) => {
-// return {
-// displayMode: "offline",
-// downloadedProfiles: [],
-// localProfiles: [],
-// uploadedProfiles: [],
-// async initialize() {
-// const { apiMeData, updateStatuses, themes, getUploadedThemes } = getCSSLoaderState();
-// const profiles = themes.filter((e) => e.flags.includes(Flags.isPreset));
-// if (!updateStatuses) {
-// // Offline mode, no profile sorting, just one list
-// set({ displayMode: "offline", downloadedProfiles: profiles });
-// return;
-// }
-
-// let downloadedProfiles: Theme[] = [];
-// let localProfiles: Theme[] = [];
-// profiles.forEach((e) => {
-// if (updateStatuses.find((status) => status[0] === e.id)?.[1] === "local") {
-// localProfiles.push(e);
-// } else {
-// downloadedProfiles.push(e);
-// }
-// });
-
-// if (!apiMeData) {
-// // Logged out mode, separate downloaded and local, but no 'Uploaded' section
-// set({ displayMode: "loggedout", downloadedProfiles, localProfiles });
-// return;
-// }
-
-// // Logged in mode, separate downloaded and local, and show uploaded profiles
-// const uploadedThemes = await getUploadedThemes();
-// const uploadedProfileRemoteEntries = uploadedThemes.filter((theme) =>
-// theme.targets.includes("Profile")
-// );
-
-// // Since uploaded profiles are also technically 'downloaded', we have to manually filter them out
-// downloadedProfiles = downloadedProfiles.filter(
-// (profile) =>
-// !uploadedProfileRemoteEntries.some((uploadedProfile) => uploadedProfile.id === profile.id)
-// );
-// set({
-// displayMode: "loggedin",
-// downloadedProfiles,
-// localProfiles,
-// uploadedProfiles: uploadedProfileRemoteEntries,
-// });
-// },
-// };
-// });
-
-// export const useProfileStoreValues = generateStoreSelector(profileStore);
-// export const useProfileStoreActions = generateStoreSelector(profileStore);