diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 1561820..b8e1df8 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -13,6 +13,8 @@ "core:window:allow-minimize", "core:window:allow-maximize", "core:window:allow-unmaximize", + "core:window:allow-close", + "core:window:allow-destroy", "core:window:allow-start-dragging", "opener:default", "shell:default", diff --git a/src/App.tsx b/src/App.tsx index 1fb15a9..33c82bd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,7 +4,7 @@ import { AppContext } from "@/providers/appContextProvider"; import { useEffect, useRef, useState } from "react"; import { arch, exeExtension } from "@tauri-apps/plugin-os"; import { downloadDir, join, resourceDir, tempDir, dataDir } from "@tauri-apps/api/path"; -import { useBasePathsStore, useCurrentVideoMetadataStore, useDownloaderPageStatesStore, useDownloadStatesStore, useEnvironmentStore, useKvPairsStatesStore, useSettingsPageStatesStore } from "@/services/store"; +import { useBasePathsStore, useCurrentVideoMetadataStore, useDownloadActionStatesStore, useDownloaderPageStatesStore, useDownloadStatesStore, useEnvironmentStore, useKvPairsStatesStore, useSettingsPageStatesStore } from "@/services/store"; import { isObjEmpty} from "@/utils"; import { Command } from "@tauri-apps/plugin-shell"; import { useUpdateDownloadStatus } from "@/services/mutations"; @@ -60,6 +60,7 @@ export default function App({ children }: { children: React.ReactNode }) { theme: APP_THEME, color_scheme: APP_COLOR_SCHEME, use_potoken: USE_POTOKEN, + quit_on_close: QUIT_ON_CLOSE } = useSettingsPageStatesStore(state => state.settings); const erroredDownloadIds = useDownloaderPageStatesStore((state) => state.erroredDownloadIds); @@ -96,6 +97,24 @@ export default function App({ children }: { children: React.ReactNode }) { const { fetchVideoMetadata, startDownload, pauseDownload, resumeDownload, cancelDownload, processQueuedDownloads } = useDownloader(); + const ongoingDownloadsCloseable = globalDownloadStates.filter(state => ['starting', 'downloading', 'queued'].includes(state.download_status)); + const setIsPausingDownload = useDownloadActionStatesStore(state => state.setIsPausingDownload); + + const stopOngoingDownloads = async () => { + if (ongoingDownloadsCloseable.length > 0) { + for (const state of ongoingDownloadsCloseable) { + setIsPausingDownload(state.download_id, true); + try { + await pauseDownload(state); + } catch (e) { + console.error(e); + } finally { + setIsPausingDownload(state.download_id, false); + } + } + } + } + // Prevent right click context menu in production if (!import.meta.env.DEV) { document.oncontextmenu = (event) => { @@ -105,9 +124,16 @@ export default function App({ children }: { children: React.ReactNode }) { // Prevent app from closing useEffect(() => { - const handleCloseRequested = (event: any) => { + const handleCloseRequested = async (event: any) => { event.preventDefault(); - appWindow.hide(); + if (QUIT_ON_CLOSE) { + if (ongoingDownloads.length > 0) { + await stopOngoingDownloads() + } + await appWindow.destroy(); + } else { + await appWindow.hide(); + } }; appWindow.onCloseRequested(handleCloseRequested); diff --git a/src/components/pages/settings/applicationSettings.tsx b/src/components/pages/settings/applicationSettings.tsx index 5639a09..ba77367 100644 --- a/src/components/pages/settings/applicationSettings.tsx +++ b/src/components/pages/settings/applicationSettings.tsx @@ -130,6 +130,7 @@ function AppGeneralSettings() { const maxRetries = useSettingsPageStatesStore(state => state.settings.max_retries); const preferVideoOverPlaylist = useSettingsPageStatesStore(state => state.settings.prefer_video_over_playlist); const strictDownloadabilityCheck = useSettingsPageStatesStore(state => state.settings.strict_downloadablity_check); + const quitOnClose = useSettingsPageStatesStore(state => state.settings.quit_on_close); const useAria2 = useSettingsPageStatesStore(state => state.settings.use_aria2); const useCustomCommands = useSettingsPageStatesStore(state => state.settings.use_custom_commands); @@ -179,6 +180,15 @@ function AppGeneralSettings() { /> +
Wheather to quit the app when the main window is closed, if disabled the app will keep running in the background and you can open the main window again from the system tray
+Use aria2c as external downloader (recommended only if you are experiancing too slow download speeds with native downloader, you need to install aria2 via homebrew if you are on macos to use this feature)
diff --git a/src/components/titlebar.tsx b/src/components/titlebar.tsx index e0e626f..993fd37 100644 --- a/src/components/titlebar.tsx +++ b/src/components/titlebar.tsx @@ -4,10 +4,35 @@ import { MaximizeIcon } from "@/components/icons/maximize"; import { MinimizeIcon } from "@/components/icons/minimize"; import { CloseIcon } from "@/components/icons/close"; import { UnmaximizeIcon } from "@/components/icons/unmaximize"; +import { useDownloadActionStatesStore, useDownloadStatesStore, useSettingsPageStatesStore } from "@/services/store"; +import { useAppContext } from "@/providers/appContextProvider"; export default function TitleBar() { const [maximized, setMaximized] = useState