feat: update theme installation with author details

This commit is contained in:
Hachi-R 2025-02-16 17:40:51 -03:00
parent 4f725d08dc
commit 7064da8b05
5 changed files with 54 additions and 31 deletions

View file

@ -100,11 +100,12 @@ const handleDeepLinkPath = (uri?: string) => {
if (url.host === "install-theme") {
const themeName = url.searchParams.get("theme");
const authorCode = url.searchParams.get("author");
const authorId = url.searchParams.get("authorId");
const authorName = url.searchParams.get("authorName");
if (themeName && authorCode) {
if (themeName && authorId && authorName) {
WindowManager.redirect(
`settings?theme=${themeName}&author=${authorCode}`
`settings?theme=${themeName}&authorId=${authorId}&authorName=${authorName}`
);
}
}

View file

@ -14,7 +14,8 @@ export interface SettingsContext {
blockedUsers: UserBlocks["blocks"];
fetchBlockedUsers: () => Promise<void>;
appearanceTheme: string | null;
appearanceAuthor: string | null;
appearanceAuthorId: string | null;
appearanceAuthorName: string | null;
}
export const settingsContext = createContext<SettingsContext>({
@ -26,7 +27,8 @@ export const settingsContext = createContext<SettingsContext>({
blockedUsers: [],
fetchBlockedUsers: async () => {},
appearanceTheme: null,
appearanceAuthor: null,
appearanceAuthorId: null,
appearanceAuthorName: null,
});
const { Provider } = settingsContext;
@ -42,7 +44,12 @@ export function SettingsContextProvider({
const dispatch = useAppDispatch();
const [sourceUrl, setSourceUrl] = useState<string | null>(null);
const [appearanceTheme, setAppearanceTheme] = useState<string | null>(null);
const [appearanceAuthor, setAppearanceAuthor] = useState<string | null>(null);
const [appearanceAuthorId, setAppearanceAuthorId] = useState<string | null>(
null
);
const [appearanceAuthorName, setAppearanceAuthorName] = useState<string | null>(
null
);
const [currentCategoryIndex, setCurrentCategoryIndex] = useState(0);
const [blockedUsers, setBlockedUsers] = useState<UserBlocks["blocks"]>([]);
@ -50,7 +57,8 @@ export function SettingsContextProvider({
const [searchParams] = useSearchParams();
const defaultSourceUrl = searchParams.get("urls");
const defaultAppearanceTheme = searchParams.get("theme");
const defaultAppearanceAuthor = searchParams.get("author");
const defaultAppearanceAuthorId = searchParams.get("authorId");
const defaultAppearanceAuthorName = searchParams.get("authorName");
useEffect(() => {
if (sourceUrl) setCurrentCategoryIndex(2);
@ -67,11 +75,16 @@ export function SettingsContextProvider({
}, [appearanceTheme]);
useEffect(() => {
if (defaultAppearanceTheme && defaultAppearanceAuthor) {
if (defaultAppearanceTheme && defaultAppearanceAuthorId && defaultAppearanceAuthorName) {
setAppearanceTheme(defaultAppearanceTheme);
setAppearanceAuthor(defaultAppearanceAuthor);
setAppearanceAuthorId(defaultAppearanceAuthorId);
setAppearanceAuthorName(defaultAppearanceAuthorName);
}
}, [defaultAppearanceTheme, defaultAppearanceAuthor]);
}, [
defaultAppearanceTheme,
defaultAppearanceAuthorId,
defaultAppearanceAuthorName,
]);
const fetchBlockedUsers = useCallback(async () => {
const blockedUsers = await window.electron.getBlockedUsers(12, 0);
@ -102,7 +115,8 @@ export function SettingsContextProvider({
sourceUrl,
blockedUsers,
appearanceTheme,
appearanceAuthor,
appearanceAuthorId,
appearanceAuthorName,
}}
>
{children}

View file

@ -2,7 +2,7 @@ import { Button } from "@renderer/components/button/button";
import { Modal } from "@renderer/components/modal/modal";
import { useTranslation } from "react-i18next";
import "./modals.scss";
import { Theme, UserProfile } from "@types";
import { Theme } from "@types";
import { injectCustomCss, removeCustomCss } from "@renderer/helpers";
import { useToast } from "@renderer/hooks";
import { THEME_WEB_STORE_URL } from "@renderer/constants";
@ -13,7 +13,8 @@ interface ImportThemeModalProps {
onClose: () => void;
onThemeImported: () => void;
themeName: string;
authorCode: string;
authorId: string;
authorName: string;
}
export const ImportThemeModal = ({
@ -21,23 +22,19 @@ export const ImportThemeModal = ({
onClose,
onThemeImported,
themeName,
authorCode,
authorId,
authorName,
}: ImportThemeModalProps) => {
const { t } = useTranslation("settings");
const { showSuccessToast, showErrorToast } = useToast();
let author: UserProfile | null = null;
window.electron.getUser(authorCode).then((user) => {
author = user;
});
const handleImportTheme = async () => {
const theme: Theme = {
id: crypto.randomUUID(),
name: themeName,
isActive: false,
author: author?.id,
authorName: author?.displayName,
author: authorId,
authorName: authorName,
code: `${THEME_WEB_STORE_URL}/themes/${themeName.toLowerCase()}/theme.css`,
createdAt: new Date(),
updatedAt: new Date(),

View file

@ -6,19 +6,22 @@ import { ImportThemeModal } from "./modals/import-theme-modal";
interface SettingsAppearanceProps {
appearanceTheme: string | null;
appearanceAuthor: string | null;
appearanceAuthorId: string | null;
appearanceAuthorName: string | null;
}
export const SettingsAppearance = ({
appearanceTheme,
appearanceAuthor,
appearanceAuthorId,
appearanceAuthorName,
}: SettingsAppearanceProps) => {
const [themes, setThemes] = useState<Theme[]>([]);
const [isImportThemeModalVisible, setIsImportThemeModalVisible] =
useState(false);
const [importTheme, setImportTheme] = useState<{
theme: string;
author: string;
authorId: string;
authorName: string;
} | null>(null);
const loadThemes = async () => {
@ -39,14 +42,15 @@ export const SettingsAppearance = ({
}, []);
useEffect(() => {
if (appearanceTheme && appearanceAuthor) {
if (appearanceTheme && appearanceAuthorId && appearanceAuthorName) {
setIsImportThemeModalVisible(true);
setImportTheme({
theme: appearanceTheme,
author: appearanceAuthor,
authorId: appearanceAuthorId,
authorName: appearanceAuthorName,
});
}
}, [appearanceTheme, appearanceAuthor]);
}, [appearanceTheme, appearanceAuthorId, appearanceAuthorName]);
return (
<div className="settings-appearance">
@ -81,7 +85,8 @@ export const SettingsAppearance = ({
loadThemes();
}}
themeName={importTheme.theme}
authorCode={importTheme.author}
authorId={importTheme.authorId}
authorName={importTheme.authorName}
/>
)}
</div>

View file

@ -39,7 +39,11 @@ export default function Settings() {
{
tabLabel: (
<>
<img src={torBoxLogo} alt="TorBox" style={{ width: 13 }} />
<img
src={torBoxLogo}
alt="TorBox"
style={{ width: 13, height: 13 }}
/>
Torbox
</>
),
@ -65,7 +69,8 @@ export default function Settings() {
currentCategoryIndex,
setCurrentCategoryIndex,
appearanceTheme,
appearanceAuthor,
appearanceAuthorId,
appearanceAuthorName,
}) => {
const renderCategory = () => {
if (currentCategoryIndex === 0) {
@ -84,7 +89,8 @@ export default function Settings() {
return (
<SettingsAppearance
appearanceTheme={appearanceTheme}
appearanceAuthor={appearanceAuthor}
appearanceAuthorId={appearanceAuthorId}
appearanceAuthorName={appearanceAuthorName}
/>
);
}