feat: updating translations

This commit is contained in:
Chubby Granny Chaser 2025-02-16 01:25:36 +00:00
commit 730184de77
No known key found for this signature in database
14 changed files with 110 additions and 99 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "hydralauncher", "name": "hydralauncher",
"version": "3.1.5", "version": "3.2.0",
"description": "Hydra", "description": "Hydra",
"main": "./out/main/index.js", "main": "./out/main/index.js",
"author": "Los Broxas", "author": "Los Broxas",

View file

@ -311,7 +311,7 @@
"web_store": "Web store", "web_store": "Web store",
"clear_themes": "Clear", "clear_themes": "Clear",
"add_theme": "Add", "add_theme": "Add",
"add_theme_modal_title": "Add custom theme", "add_theme_modal_title": "Create custom theme",
"add_theme_modal_description": "Create a new theme to customize Hydra's appearance", "add_theme_modal_description": "Create a new theme to customize Hydra's appearance",
"theme_name": "Name", "theme_name": "Name",
"insert_theme_name": "Insert theme name", "insert_theme_name": "Insert theme name",

View file

@ -294,6 +294,26 @@
"subscription_renew_cancelled": "A renovação automática está desativada", "subscription_renew_cancelled": "A renovação automática está desativada",
"subscription_renews_on": "Sua assinatura renova dia {{date}}", "subscription_renews_on": "Sua assinatura renova dia {{date}}",
"bill_sent_until": "Sua próxima cobrança será enviada até esse dia", "bill_sent_until": "Sua próxima cobrança será enviada até esse dia",
"no_themes": "Parace que você ainda não tem nenhum tema. Não se preocupe, clique aqui para criar sua primeira obra de arte.",
"editor_tab_code": "Código",
"editor_tab_info": "Info",
"editor_tab_save": "Salvar",
"web_store": "Loja de temas",
"clear_themes": "Limpar",
"add_theme": "Adicionar",
"add_theme_modal_title": "Criar tema customizado",
"add_theme_modal_description": "Criar novo tema para customizar a aparência do Hydra",
"theme_name": "Nome",
"insert_theme_name": "Insira o nome do tema",
"set_theme": "Habilitar tema",
"unset_theme": "Desabilitar tema",
"delete_theme": "Deletar tema",
"edit_theme": "Editar tema",
"delete_all_themes": "Deletar todos os temas",
"delete_all_themes_description": "Isso irá deletar todos os seus temas",
"delete_theme_description": "Isso irá deletar o tema {{theme}}",
"cancel": "Cancelar",
"appearance": "Aparência",
"enable_torbox": "Habilitar Torbox", "enable_torbox": "Habilitar Torbox",
"torbox_description": "TorBox é o seu serviço de seedbox premium que rivaliza até com os melhores servidores do mercado.", "torbox_description": "TorBox é o seu serviço de seedbox premium que rivaliza até com os melhores servidores do mercado.",
"torbox_account_linked": "Conta do TorBox vinculada", "torbox_account_linked": "Conta do TorBox vinculada",

View file

@ -0,0 +1,38 @@
import { themes } from "@main/level/sublevels/themes";
import { WindowManager } from "@main/services";
import { Theme } from "@types";
export const handleDeepLinkTheme = async (
themeName: string,
authorCode: string
) => {
const theme: Theme = {
id: crypto.randomUUID(),
name: themeName,
isActive: false,
author: authorCode,
authorName: "spectre",
code: `https://hydrathemes.shop/themes/${themeName}.css`,
createdAt: new Date(),
updatedAt: new Date(),
};
await themes.put(theme.id, theme);
const allThemes = await themes.values().all();
const activeTheme = allThemes.find((theme: Theme) => theme.isActive);
if (activeTheme) {
await themes.put(activeTheme.id, {
...activeTheme,
isActive: false,
});
}
WindowManager.mainWindow?.webContents.send("css-injected", theme.code);
await themes.put(theme.id, {
...theme,
isActive: true,
});
};

View file

@ -10,6 +10,7 @@ import { PythonRPC } from "./services/python-rpc";
import { Aria2 } from "./services/aria2"; import { Aria2 } from "./services/aria2";
import { db, levelKeys } from "./level"; import { db, levelKeys } from "./level";
import { loadState } from "./main"; import { loadState } from "./main";
import { handleDeepLinkTheme } from "./events/themes/deeplink";
const { autoUpdater } = updater; const { autoUpdater } = updater;
@ -86,6 +87,15 @@ const handleDeepLinkPath = (uri?: string) => {
if (url.host === "install-source") { if (url.host === "install-source") {
WindowManager.redirect(`settings${url.search}`); WindowManager.redirect(`settings${url.search}`);
} }
if (url.host === "install-theme") {
const themeName = url.searchParams.get("theme");
const authorCode = url.searchParams.get("author");
if (themeName && authorCode) {
handleDeepLinkTheme(themeName, authorCode);
}
}
} catch (error) { } catch (error) {
logger.error("Error handling deep link", uri, error); logger.error("Error handling deep link", uri, error);
} }

View file

@ -1,6 +1,6 @@
import { Downloader } from "@shared"; import { Downloader } from "@shared";
export const VERSION_CODENAME = "Spectre"; export const VERSION_CODENAME = "Polychrome";
export const DOWNLOADER_NAME = { export const DOWNLOADER_NAME = {
[Downloader.RealDebrid]: "Real-Debrid", [Downloader.RealDebrid]: "Real-Debrid",

View file

@ -61,13 +61,20 @@ export const injectCustomCss = (css: string) => {
currentCustomCss.remove(); currentCustomCss.remove();
} }
const style = document.createElement("style"); if (css.startsWith("https://hydrathemes.shop/")) {
const link = document.createElement("link");
style.id = "custom-css"; link.id = "custom-css";
style.textContent = ` link.rel = "stylesheet";
${css} link.href = css;
`; document.head.appendChild(link);
document.head.appendChild(style); } else {
const style = document.createElement("style");
style.id = "custom-css";
style.textContent = `
${css}
`;
document.head.appendChild(style);
}
} catch (error) { } catch (error) {
console.error("failed to inject custom css:", error); console.error("failed to inject custom css:", error);
} }

View file

@ -85,6 +85,10 @@
flex-direction: row; flex-direction: row;
gap: 8px; gap: 8px;
&--external {
display: none;
}
Button { Button {
padding: 8px 11px; padding: 8px 11px;
} }

View file

@ -81,17 +81,6 @@ export const ThemeCard = ({ theme, onListUpdated }: ThemeCardProps) => {
> >
<div className="theme-card__header"> <div className="theme-card__header">
<div className="theme-card__header__title">{theme.name}</div> <div className="theme-card__header__title">{theme.name}</div>
<div className="theme-card__header__colors">
{Object.entries(theme.colors).map(([key, color]) => (
<div
title={color}
style={{ backgroundColor: color }}
className="theme-card__header__colors__color"
key={key}
></div>
))}
</div>
</div> </div>
{theme.authorName && ( {theme.authorName && (
@ -122,6 +111,11 @@ export const ThemeCard = ({ theme, onListUpdated }: ThemeCardProps) => {
<div className="theme-card__actions__right"> <div className="theme-card__actions__right">
<Button <Button
className={
theme.code.startsWith("https://hydrathemes.shop/")
? "theme-card__actions__right--external"
: ""
}
onClick={() => window.electron.openEditorWindow(theme.id)} onClick={() => window.electron.openEditorWindow(theme.id)}
title={t("edit_theme")} title={t("edit_theme")}
theme="outline" theme="outline"

View file

@ -41,11 +41,6 @@ export const AddThemeModal = ({
isActive: false, isActive: false,
author: userDetails?.id || undefined, author: userDetails?.id || undefined,
authorName: userDetails?.username || undefined, authorName: userDetails?.username || undefined,
colors: {
accent: "",
background: "",
surface: "",
},
code: "", code: "",
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),

View file

@ -17,8 +17,6 @@ export const SettingsAppearance = () => {
return ( return (
<div className="settings-appearance"> <div className="settings-appearance">
<p className="settings-appearance__description">Appearance</p>
<ThemeActions onListUpdated={loadThemes} themesCount={themes.length} /> <ThemeActions onListUpdated={loadThemes} themesCount={themes.length} />
<div className="settings-appearance__themes"> <div className="settings-appearance__themes">

View file

@ -9,7 +9,7 @@
&__header { &__header {
display: flex; display: flex;
align-items: center; align-items: center;
padding: calc(globals.$spacing-unit * 2); padding: calc(globals.$spacing-unit + 1px);
background-color: globals.$dark-background-color; background-color: globals.$dark-background-color;
font-size: 8px; font-size: 8px;
z-index: 50; z-index: 50;
@ -47,7 +47,7 @@
&-actions { &-actions {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: flex-end;
align-items: center; align-items: center;
&__tabs { &__tabs {

View file

@ -4,11 +4,7 @@ import Editor from "@monaco-editor/react";
import { Theme } from "@types"; import { Theme } from "@types";
import { useSearchParams } from "react-router-dom"; import { useSearchParams } from "react-router-dom";
import { Button } from "@renderer/components"; import { Button } from "@renderer/components";
import { import { CheckIcon } from "@primer/octicons-react";
CheckIcon,
CodeIcon,
ProjectRoadmapIcon,
} from "@primer/octicons-react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import cn from "classnames"; import cn from "classnames";
@ -16,17 +12,12 @@ export default function ThemeEditor() {
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const [theme, setTheme] = useState<Theme | null>(null); const [theme, setTheme] = useState<Theme | null>(null);
const [code, setCode] = useState(""); const [code, setCode] = useState("");
const [activeTab, setActiveTab] = useState("code");
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
const themeId = searchParams.get("themeId"); const themeId = searchParams.get("themeId");
const { t } = useTranslation("settings"); const { t } = useTranslation("settings");
const handleTabChange = (tab: string) => {
setActiveTab(tab);
};
useEffect(() => { useEffect(() => {
if (themeId) { if (themeId) {
window.electron.getCustomThemeById(themeId).then((loadedTheme) => { window.electron.getCustomThemeById(themeId).then((loadedTheme) => {
@ -90,50 +81,22 @@ export default function ThemeEditor() {
)} )}
</div> </div>
{activeTab === "code" && ( <Editor
<Editor theme="vs-dark"
theme="vs-dark" defaultLanguage="css"
defaultLanguage="css" value={code}
value={code} onChange={handleEditorChange}
onChange={handleEditorChange} options={{
options={{ minimap: { enabled: false },
minimap: { enabled: false }, fontSize: 14,
fontSize: 14, lineNumbers: "on",
lineNumbers: "on", wordWrap: "on",
wordWrap: "on", automaticLayout: true,
automaticLayout: true, }}
}} />
/>
)}
{activeTab === "info" && (
<div className="theme-editor__info">
entao mano eu ate fiz isso aqui mas tava feio dms ai deu vergonha e
removi kkkk
</div>
)}
<div className="theme-editor__footer"> <div className="theme-editor__footer">
<div className="theme-editor__footer-actions"> <div className="theme-editor__footer-actions">
<div className="theme-editor__footer-actions__tabs">
<Button
onClick={() => handleTabChange("code")}
theme="dark"
className={activeTab === "code" ? "active" : ""}
>
<CodeIcon />
{t("editor_tab_code")}
</Button>
<Button
onClick={() => handleTabChange("info")}
theme="dark"
className={activeTab === "info" ? "active" : ""}
>
<ProjectRoadmapIcon />
{t("editor_tab_info")}
</Button>
</div>
<Button onClick={handleSave}> <Button onClick={handleSave}>
<CheckIcon /> <CheckIcon />
{t("editor_tab_save")} {t("editor_tab_save")}

View file

@ -1,24 +1,6 @@
import { z } from "zod";
const isValidHexColor = (color: string): boolean => {
const hexColorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
return hexColorRegex.test(color);
};
const hexColorSchema = z.string().refine(isValidHexColor);
type HexColorType = z.infer<typeof hexColorSchema>;
export interface Theme { export interface Theme {
id: string; id: string;
name: string; name: string;
colors: {
accent: HexColorType;
background: HexColorType;
surface: HexColorType;
optional1?: HexColorType;
optional2?: HexColorType;
};
description?: string;
author: string | undefined; author: string | undefined;
authorName: string | undefined; authorName: string | undefined;
isActive: boolean; isActive: boolean;