diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 01cfcdf8..a17875ad 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -253,7 +253,8 @@ "must_be_valid_url": "The source must be a valid URL", "blocked_users": "Blocked users", "user_unblocked": "User has been unblocked", - "enable_achievement_notifications": "When an achievement in unlocked" + "enable_achievement_notifications": "When an achievement in unlocked", + "launch_minimized": "Launch Hydra minimized" }, "notifications": { "download_complete": "Download complete", diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index 694a805d..e0f59e24 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -249,7 +249,8 @@ "must_be_valid_url": "A fonte deve ser uma URL válida", "blocked_users": "Usuários bloqueados", "user_unblocked": "Usuário desbloqueado", - "enable_achievement_notifications": "Quando uma conquista é desbloqueada" + "enable_achievement_notifications": "Quando uma conquista é desbloqueada", + "launch_minimized": "Iniciar o Hydra minimizado" }, "notifications": { "download_complete": "Download concluído", diff --git a/src/main/entity/user-preferences.entity.ts b/src/main/entity/user-preferences.entity.ts index dc6d465d..b43d463e 100644 --- a/src/main/entity/user-preferences.entity.ts +++ b/src/main/entity/user-preferences.entity.ts @@ -35,6 +35,9 @@ export class UserPreferences { @Column("boolean", { default: false }) runAtStartup: boolean; + @Column("boolean", { default: false }) + startMinimized: boolean; + @CreateDateColumn() createdAt: Date; diff --git a/src/main/events/user-preferences/auto-launch.ts b/src/main/events/user-preferences/auto-launch.ts index 1f4f9cc3..0b1bba21 100644 --- a/src/main/events/user-preferences/auto-launch.ts +++ b/src/main/events/user-preferences/auto-launch.ts @@ -16,15 +16,16 @@ const windowsStartupPath = path.join( const autoLaunch = async ( _event: Electron.IpcMainInvokeEvent, - enabled: boolean + autoLaunchProps: { enabled: boolean; minimized: boolean } ) => { if (!app.isPackaged) return; const appLauncher = new AutoLaunch({ name: app.getName(), + isHidden: autoLaunchProps.minimized, }); - if (enabled) { + if (autoLaunchProps.enabled) { appLauncher.enable().catch((err) => { logger.error(err); }); diff --git a/src/main/index.ts b/src/main/index.ts index 1b1629ef..7f35c317 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -101,7 +101,10 @@ app.whenReady().then(async () => { i18n.changeLanguage(userPreferences.language); } - WindowManager.createMainWindow(); + if (!process.argv.includes("--hidden")) { + WindowManager.createMainWindow(); + } + WindowManager.createNotificationWindow(); WindowManager.createSystemTray(userPreferences?.language || "en"); }); diff --git a/src/main/knex-client.ts b/src/main/knex-client.ts index 5f81ffbc..eec5b054 100644 --- a/src/main/knex-client.ts +++ b/src/main/knex-client.ts @@ -11,7 +11,7 @@ import { AddAchievementNotificationPreference } from "./migrations/2024101301290 import { CreateUserSubscription } from "./migrations/20241015235142_create_user_subscription"; import { AddBackgroundImageUrl } from "./migrations/20241016100249_add_background_image_url"; import { AddWinePrefixToGame } from "./migrations/20241019081648_add_wine_prefix_to_game"; - +import { AddStartMinimizedColumn } from "./migrations/20241030171454_add_start_minimized_column"; export type HydraMigration = Knex.Migration & { name: string }; class MigrationSource implements Knex.MigrationSource { @@ -27,6 +27,7 @@ class MigrationSource implements Knex.MigrationSource { CreateUserSubscription, AddBackgroundImageUrl, AddWinePrefixToGame, + AddStartMinimizedColumn, ]); } getMigrationName(migration: HydraMigration): string { diff --git a/src/main/migrations/20241030171454_add_start_minimized_column.ts b/src/main/migrations/20241030171454_add_start_minimized_column.ts new file mode 100644 index 00000000..69ede189 --- /dev/null +++ b/src/main/migrations/20241030171454_add_start_minimized_column.ts @@ -0,0 +1,17 @@ +import type { HydraMigration } from "@main/knex-client"; +import type { Knex } from "knex"; + +export const AddStartMinimizedColumn: HydraMigration = { + name: "AddStartMinimizedColumn", + up: (knex: Knex) => { + return knex.schema.alterTable("user_preferences", (table) => { + return table.boolean("startMinimized").notNullable().defaultTo(0); + }); + }, + + down: async (knex: Knex) => { + return knex.schema.alterTable("user_preferences", (table) => { + return table.dropColumn("startMinimized"); + }); + }, +}; diff --git a/src/main/services/window-manager.ts b/src/main/services/window-manager.ts index e1dc4dfc..b61c991a 100644 --- a/src/main/services/window-manager.ts +++ b/src/main/services/window-manager.ts @@ -310,14 +310,15 @@ export class WindowManager { if (process.platform !== "darwin") { tray.addListener("click", () => { if (this.mainWindow) { - if (WindowManager.mainWindow?.isMinimized()) - WindowManager.mainWindow.restore(); - - WindowManager.mainWindow?.focus(); - return; + if ( + WindowManager.mainWindow?.isMinimized() || + !WindowManager.mainWindow?.isVisible() + ) { + WindowManager.mainWindow?.show(); + } + } else { + this.createMainWindow(); } - - this.createMainWindow(); }); tray.addListener("right-click", showContextMenu); diff --git a/src/preload/index.ts b/src/preload/index.ts index 90c50763..9baa8325 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -101,7 +101,8 @@ contextBridge.exposeInMainWorld("electron", { getUserPreferences: () => ipcRenderer.invoke("getUserPreferences"), updateUserPreferences: (preferences: UserPreferences) => ipcRenderer.invoke("updateUserPreferences", preferences), - autoLaunch: (enabled: boolean) => ipcRenderer.invoke("autoLaunch", enabled), + autoLaunch: (autoLaunchProps: { enabled: boolean; minimized: boolean }) => + ipcRenderer.invoke("autoLaunch", autoLaunchProps), authenticateRealDebrid: (apiToken: string) => ipcRenderer.invoke("authenticateRealDebrid", apiToken), diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index 929b00e9..a12862b3 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -114,7 +114,10 @@ declare global { updateUserPreferences: ( preferences: Partial ) => Promise; - autoLaunch: (enabled: boolean) => Promise; + autoLaunch: (autoLaunchProps: { + enabled: boolean; + minimized: boolean; + }) => Promise; authenticateRealDebrid: (apiToken: string) => Promise; /* Download sources */ diff --git a/src/renderer/src/pages/settings/settings-behavior.tsx b/src/renderer/src/pages/settings/settings-behavior.tsx index f0b4b4c4..4e3ef2f3 100644 --- a/src/renderer/src/pages/settings/settings-behavior.tsx +++ b/src/renderer/src/pages/settings/settings-behavior.tsx @@ -17,6 +17,7 @@ export function SettingsBehavior() { const [form, setForm] = useState({ preferQuitInsteadOfHiding: false, runAtStartup: false, + startMinimized: false, }); const { t } = useTranslation("settings"); @@ -26,6 +27,7 @@ export function SettingsBehavior() { setForm({ preferQuitInsteadOfHiding: userPreferences.preferQuitInsteadOfHiding, runAtStartup: userPreferences.runAtStartup, + startMinimized: userPreferences.startMinimized, }); } }, [userPreferences]); @@ -58,11 +60,32 @@ export function SettingsBehavior() { label={t("launch_with_system")} onChange={() => { handleChange({ runAtStartup: !form.runAtStartup }); - window.electron.autoLaunch(!form.runAtStartup); + window.electron.autoLaunch({ + enabled: !form.runAtStartup, + minimized: form.startMinimized, + }); }} checked={form.runAtStartup} /> )} + + {showRunAtStartup && ( +
+ { + handleChange({ startMinimized: !form.startMinimized }); + window.electron.autoLaunch({ + minimized: !form.startMinimized, + enabled: form.runAtStartup, + }); + }} + /> +
+ )} ); } diff --git a/src/types/index.ts b/src/types/index.ts index 7f970d63..9bb25e3f 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -160,6 +160,7 @@ export interface UserPreferences { realDebridApiToken: string | null; preferQuitInsteadOfHiding: boolean; runAtStartup: boolean; + startMinimized: boolean; } export interface Steam250Game {