mirror of
https://github.com/neosubhamoy/neodlp.git
synced 2026-06-21 03:33:44 +05:30
Compare commits
10 Commits
1ad9c9797b
...
v0.4.5
@@ -45,13 +45,13 @@ jobs:
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- name: 🚚 Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: 🛠️ Install dependencies
|
||||
if: matrix.platform == 'ubuntu-22.04' || matrix.platform == 'ubuntu-22.04-arm'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
||||
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf xdg-utils
|
||||
|
||||
- name: 📦 Setup node
|
||||
uses: actions/setup-node@v6
|
||||
|
||||
+16
-17
@@ -1,45 +1,44 @@
|
||||
### ✨ Changelog
|
||||
### Changelog
|
||||
|
||||
- Added filename sanitization settings
|
||||
- Fixed po-token server process not terminating on app update
|
||||
- Fixed yt-dlp auto-update on linux flatpak
|
||||
- Fixed potoken server on linux flatpak
|
||||
- Improved linux package dependencies
|
||||
- Added native windows arm64 builds by @talynone
|
||||
- Discontinued linux appimage builds
|
||||
- Added quit-on-close settings toggle
|
||||
- Added option to remove download id from filename
|
||||
- Fixed inconsistent download progress on high-speed networks by @talynone
|
||||
- Disabled self-updater on flatpak
|
||||
- Other minor fixes and improvements
|
||||
|
||||
### 📝 Notes
|
||||
### Notes
|
||||
|
||||
> [!CAUTION]
|
||||
> Users are always adviced to complete/cancel all paused downloads before updating to a newer version, otherwise paused downloads may not resume properly and re-start from the begining.
|
||||
|
||||
> [!WARNING]
|
||||
> Linux users make sure `yt-dlp` and `deno` is not installed in your distro (otherwise you will get package installation conflict). Don't worry, You can still use yt-dlp cli as before (the only difference is that now it will be installed and auto-updated by neodlp, which You can also disable from neodlp settings if you don't want to auto-update yt-dlp) (ignore this if you are installing AppImage/Flatpak)
|
||||
> Linux users make sure `yt-dlp` and `deno` is not installed in your distro (otherwise you will get package installation conflict). Don't worry, You can still use yt-dlp cli as before (the only difference is that now it will be installed and auto-updated by neodlp, which You can also disable from neodlp settings if you don't want to auto-update yt-dlp) (ignore this if you are installing the Flatpak)
|
||||
|
||||
> This is an Un-Signed Build (Windows doesn't trust this Certificate so, it may flag this as malicious software, in that case, disable Windows SmartScreen and Defender, install it, and then re-enable them)
|
||||
|
||||
> This is an Un-Signed Build (MacOS doesn't trust this Certificate so, it may flag this as from 'unverified developer' and prevent it from opening, in that case, open Settings and allow it from 'Settings > Privacy and Security' section to get started)
|
||||
|
||||
### 📦 Shipped Binaries
|
||||
### Shipped Binaries
|
||||
|
||||
| yt-dlp (updateable) | ffmpeg | aria2c | deno | bgutil-pot-rs |
|
||||
| :---- | :---- | :---- | :---- | :---- |
|
||||
| v2026.03.21.233500 (nightly) | v8.0.1 | v1.37.0 | v2.7.8 | v0.8.1 |
|
||||
| v2026.05.24.234402 (nightly) | v8.0.1 | v1.37.0 | v2.8.0 | v0.8.1 |
|
||||
|
||||
> ‼️ Linux builds (deb, rpm) does not ships with `ffmpeg` and `aria2c` (though it will be auto installed as a dependency by your package manager, if you are on fedora make sure to [enable rpmfusion free+nonfree repos](https://docs.fedoraproject.org/en-US/quick-docs/rpmfusion-setup/#_enabling_the_rpm_fusion_repositories_using_command_line_utilities) before installing the rpm package)
|
||||
|
||||
> ‼️ MacOS builds (dmg, app) does not ships with `aria2c`, If you want to use [aria2](https://formulae.brew.sh/formula/aria2) install it via [Homebrew](https://brew.sh) (though it will be auto installed as a dependency if you install neodlp via Homebrew)
|
||||
|
||||
### ⬇️ Download Section
|
||||
### Download Section
|
||||
|
||||
| Architecture | Windows (msi) ⬆️ | Windows (exe) ⬆️ | Linux (deb) | Linux (rpm) | Linux (AppImage) ⬆️ | MacOS (dmg) ⬆️ | MacOS (app) ⬆️ |
|
||||
| :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- |
|
||||
| x86_64 | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_x64_en-US.msi) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_x64-setup.exe) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_amd64.deb) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP-<version>-1.x86_64.rpm) | 🚫 [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_amd64.AppImage) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_x64.dmg) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_x64.app.tar.gz) |
|
||||
| ARM64 | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_arm64_en-US.msi) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_arm64-setup.exe) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_arm64.deb) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP-<version>-1.aarch64.rpm) | N/A | ⚠️ [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_aarch64.dmg) | ⚠️ [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_aarch64.app.tar.gz) |
|
||||
| Architecture | Windows (msi) ⬆️ | Windows (exe) ⬆️ | Linux (deb) | Linux (rpm) | MacOS (dmg) ⬆️ | MacOS (app) ⬆️ |
|
||||
| :---- | :---- | :---- | :---- | :---- | :---- | :---- |
|
||||
| x86_64 | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_x64_en-US.msi) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_x64-setup.exe) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_amd64.deb) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP-<version>-1.x86_64.rpm) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_x64.dmg) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_x64.app.tar.gz) |
|
||||
| ARM64 | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_arm64_en-US.msi) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_arm64-setup.exe) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_arm64.deb) | [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP-<version>-1.aarch64.rpm) | ⚠️ [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_<version>_aarch64.dmg) | ⚠️ [Download](https://github.com/neosubhamoy/neodlp/releases/download/<release_tag>/NeoDLP_aarch64.app.tar.gz) |
|
||||
|
||||
> ⬆️ icon indicates this packaging format supports in-built app-updater
|
||||
|
||||
> 🚫 Linux AppImage builds are experimental and does not support neodlp's browser intergration features and yt-dlp updates due to it's limitations. Also, don't run the AppImage with portable (.home, .config) folders, it will break things (it is highly recommended to use native [DEB, RPM, AUR] builds if possible for the full experiance, otherwise AppImages are good for trying out NeoDLP without installing)
|
||||
|
||||
> ⚠️ MacOS ARM64 binary downloads are experimental and may not open on Apple Silicon Macs if downloaded from browser (You will get 'Damaged File' error) it's because the binaries are not signed (signing MacOS binaries requires 99$/year Apple Developer Account subscription, which I can't afford RN!) and Apple Silicon Macs don't allow unsigned apps (downloaded from browser) to be installed on the system. If you want to use NeoDLP on your Apple Silicon Macs, There are few ways you can bypass these restrictions:
|
||||
> 1. Using [Homebrew](https://neodlp.neosubhamoy.com/download) (Recommended)
|
||||
> 2. Using our automated [Curl-Bash Installer](https://neodlp.neosubhamoy.com/download)
|
||||
|
||||
@@ -75,20 +75,17 @@ After installing the extension you can do the following directly from the browse
|
||||
|
||||
| Architecture | Windows | Linux | MacOS |
|
||||
| :---- | :---- | :---- | :---- |
|
||||
| x86_64 | ✅ [Download](https://github.com/neosubhamoy/neodlp/releases/latest) | ✅ [Download](https://github.com/neosubhamoy/neodlp/releases/latest) | ✅ [Download](https://github.com/neosubhamoy/neodlp/releases/latest) |
|
||||
| ARM64 | ✅ Emulation | ✅ [Download](https://github.com/neosubhamoy/neodlp/releases/latest) | ✅ [Download](https://github.com/neosubhamoy/neodlp/releases/latest) |
|
||||
| x86_64 | ✅ [Native](https://github.com/neosubhamoy/neodlp/releases/latest) | ✅ [Native](https://github.com/neosubhamoy/neodlp/releases/latest) | ✅ [Native](https://github.com/neosubhamoy/neodlp/releases/latest) |
|
||||
| ARM64 | ✅ [Native](https://github.com/neosubhamoy/neodlp/releases/latest) | ✅ [Native](https://github.com/neosubhamoy/neodlp/releases/latest) | ✅ [Native](https://github.com/neosubhamoy/neodlp/releases/latest) |
|
||||
|
||||
> [!NOTE]
|
||||
> x86_64 Windows binary also works on ARM64 (Windows on ARM) devices with emulation (Not planning to release native Windows ARM64 build anytime soon as, x86_64 one works fine on ARM64 without noticeable performance impact)
|
||||
|
||||
| Platform (OS) | Distribution Channel | Installation Command / Instruction |
|
||||
| Platform (Architecture) [Type] | Distribution Channel | Installation Command / Instruction |
|
||||
| :---- | :---- | :---- |
|
||||
| Windows x86_64 / ARM64 | WinGet | `winget install neosubhamoy.neodlp` |
|
||||
| MacOS x86_64 / ARM64 | Homebrew | `brew install neosubhamoy/tap/neodlp` |
|
||||
| MacOS x86_64 / ARM64 | Curl-Bash Installer | `curl -sSL https://neodlp.neosubhamoy.com/macos_installer.sh \| bash` |
|
||||
| Linux x86_64 / ARM64 (Flatpak) | Flathub | `flatpak install flathub com.neosubhamoy.neodlp` |
|
||||
| Linux x86_64 / ARM64 (Native) | Curl-Bash Installer | `curl -sSL https://neodlp.neosubhamoy.com/linux_installer.sh \| bash` |
|
||||
| Arch Linux x86_64 / ARM64 (Native) | AUR | `yay -S neodlp` or `paru -S neodlp` |
|
||||
| Windows (x86_64 / ARM64) | WinGet | `winget install neosubhamoy.neodlp --source winget` |
|
||||
| MacOS (x86_64 / ARM64) | Homebrew | `brew install neosubhamoy/tap/neodlp` |
|
||||
| MacOS (x86_64 / ARM64) | Curl-Bash Installer | `curl -sSL https://neodlp.neosubhamoy.com/macos_installer.sh \| bash` |
|
||||
| Linux (x86_64 / ARM64) [Flatpak] | Flathub | `flatpak install flathub com.neosubhamoy.neodlp` |
|
||||
| Linux (x86_64 / ARM64) [Native] | Curl-Bash Installer | `curl -sSL https://neodlp.neosubhamoy.com/linux_installer.sh \| bash` |
|
||||
| Arch Linux (x86_64 / ARM64) [Native] | AUR | `yay -S neodlp` or `paru -S neodlp` |
|
||||
|
||||
## Package Testing Status
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@
|
||||
</branding>
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release version="0.4.5" date="2026-05-27">
|
||||
<url type="details">https://github.com/neosubhamoy/neodlp/releases/tag/v0.4.5</url>
|
||||
</release>
|
||||
<release version="0.4.4" date="2026-03-27">
|
||||
<url type="details">https://github.com/neosubhamoy/neodlp/releases/tag/v0.4.4</url>
|
||||
</release>
|
||||
|
||||
Generated
+865
-868
File diff suppressed because it is too large
Load Diff
+33
-31
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "neodlp",
|
||||
"private": true,
|
||||
"version": "0.4.4",
|
||||
"version": "0.4.5",
|
||||
"description": "Cross-platform Video/Audio Downloader Desktop App based on YT-DLP with Modern UI and Browser Integration",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
@@ -24,51 +24,53 @@
|
||||
"download": "node ./scripts/download-bins.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@tanstack/devtools-vite": "^0.6.0",
|
||||
"@tanstack/react-devtools": "^0.10.0",
|
||||
"@tanstack/react-pacer": "^0.20.0",
|
||||
"@tanstack/react-pacer-devtools": "^0.5.5",
|
||||
"@tanstack/react-query": "^5.91.2",
|
||||
"@tanstack/react-query-devtools": "^5.91.3",
|
||||
"@tauri-apps/api": "^2.10.1",
|
||||
"@hookform/resolvers": "^5.4.0",
|
||||
"@hugeicons/core-free-icons": "^4.1.4",
|
||||
"@hugeicons/react": "^1.1.6",
|
||||
"@tanstack/devtools-vite": "^0.7.0",
|
||||
"@tanstack/react-devtools": "^0.10.5",
|
||||
"@tanstack/react-pacer": "^0.22.1",
|
||||
"@tanstack/react-pacer-devtools": "^0.7.1",
|
||||
"@tanstack/react-query": "^5.100.14",
|
||||
"@tanstack/react-query-devtools": "^5.100.14",
|
||||
"@tauri-apps/api": "^2.11.0",
|
||||
"@tauri-apps/plugin-clipboard-manager": "^2.3.2",
|
||||
"@tauri-apps/plugin-dialog": "^2.6.0",
|
||||
"@tauri-apps/plugin-fs": "^2.4.5",
|
||||
"@tauri-apps/plugin-dialog": "^2.7.1",
|
||||
"@tauri-apps/plugin-fs": "^2.5.1",
|
||||
"@tauri-apps/plugin-log": "^2.8.0",
|
||||
"@tauri-apps/plugin-notification": "^2.3.3",
|
||||
"@tauri-apps/plugin-opener": "^2.5.3",
|
||||
"@tauri-apps/plugin-opener": "^2.5.4",
|
||||
"@tauri-apps/plugin-os": "^2.3.2",
|
||||
"@tauri-apps/plugin-process": "^2.3.1",
|
||||
"@tauri-apps/plugin-shell": "^2.3.5",
|
||||
"@tauri-apps/plugin-sql": "^2.3.2",
|
||||
"@tauri-apps/plugin-updater": "^2.10.0",
|
||||
"@tauri-apps/plugin-sql": "^2.4.0",
|
||||
"@tauri-apps/plugin-updater": "^2.10.1",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.577.0",
|
||||
"lucide-react": "^1.16.0",
|
||||
"next-themes": "^0.4.6",
|
||||
"radix-ui": "^1.4.3",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-hook-form": "^7.71.2",
|
||||
"react-resizable-panels": "^4.7.3",
|
||||
"react-router-dom": "^7.13.1",
|
||||
"react": "^19.2.6",
|
||||
"react-dom": "^19.2.6",
|
||||
"react-hook-form": "^7.76.1",
|
||||
"react-resizable-panels": "^4.11.2",
|
||||
"react-router-dom": "^7.15.1",
|
||||
"sonner": "^2.0.7",
|
||||
"tailwind-merge": "^3.5.0",
|
||||
"tailwind-merge": "^3.6.0",
|
||||
"ulid": "^3.0.2",
|
||||
"zod": "^4.3.6",
|
||||
"zustand": "^5.0.12"
|
||||
"zod": "^4.4.3",
|
||||
"zustand": "^5.0.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/vite": "^4.2.2",
|
||||
"@tauri-apps/cli": "^2.10.1",
|
||||
"@types/node": "^25.5.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@tailwindcss/vite": "^4.3.0",
|
||||
"@tauri-apps/cli": "^2.11.2",
|
||||
"@types/node": "^25.9.1",
|
||||
"@types/react": "^19.2.15",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
"tailwindcss": "^4.2.2",
|
||||
"@vitejs/plugin-react": "^6.0.2",
|
||||
"tailwindcss": "^4.3.0",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
"typescript": "~5.9.3",
|
||||
"vite": "^8.0.1"
|
||||
"typescript": "~6.0.3",
|
||||
"vite": "^8.0.14"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ function getArchesForBin(bin) {
|
||||
}
|
||||
|
||||
const versions = {
|
||||
'yt-dlp': '2026.03.21.233500',
|
||||
'yt-dlp': '2026.05.24.234402',
|
||||
'ffmpeg-ffprobe': 'latest',
|
||||
'deno': '2.7.8',
|
||||
'deno': '2.8.0',
|
||||
'aria2c': '1.37.0',
|
||||
'neodlp-pot': '0.8.1'
|
||||
};
|
||||
|
||||
Generated
+536
-847
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "neodlp"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
description = "Cross-platform Video/Audio Downloader Desktop App based on YT-DLP with Modern UI and Browser Integration"
|
||||
authors = ["neosubhamoy <hey@neosubhamoy.com>"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "NeoDLP",
|
||||
"mainBinaryName": "neodlp",
|
||||
"version": "0.4.4",
|
||||
"version": "0.4.5",
|
||||
"identifier": "com.neosubhamoy.neodlp",
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": ["deb", "rpm", "appimage"],
|
||||
"targets": ["deb", "rpm"],
|
||||
"createUpdaterArtifacts": true,
|
||||
"licenseFile": "../LICENSE",
|
||||
"category": "Utility",
|
||||
@@ -71,13 +71,6 @@
|
||||
"/usr/bin/neodlp-msghost": "./target/x86_64-unknown-linux-gnu/release/neodlp-msghost",
|
||||
"/etc/xdg/autostart/neodlp-autostart.desktop": "./resources/autostart/linux/autostart.desktop"
|
||||
}
|
||||
},
|
||||
"appimage": {
|
||||
"files": {
|
||||
"/usr/bin/ffmpeg": "./binaries/ffmpeg-x86_64-unknown-linux-gnu",
|
||||
"/usr/bin/ffprobe": "./binaries/ffprobe-x86_64-unknown-linux-gnu",
|
||||
"/usr/bin/aria2c": "./binaries/aria2c-x86_64-unknown-linux-gnu"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+44
-6
@@ -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);
|
||||
@@ -281,6 +307,7 @@ export default function App({ children }: { children: React.ReactNode }) {
|
||||
|
||||
// Check for app update
|
||||
useEffect(() => {
|
||||
const handleAppUpdateCheck = async () => {
|
||||
// Only run once when both settings and KV pairs are loaded
|
||||
if (!isSettingsStatePropagated || !isKvPairsStatePropagated) {
|
||||
console.log("Skipping app update check, waiting for configs to load...");
|
||||
@@ -291,10 +318,21 @@ export default function App({ children }: { children: React.ReactNode }) {
|
||||
console.log("App update check already performed in this session, skipping");
|
||||
return;
|
||||
}
|
||||
const isFlatpak = await invoke<boolean>('is_flatpak');
|
||||
// Skip self-update check on Flatpak, as updates should be handled by Flatpak cli itself
|
||||
if (isFlatpak) {
|
||||
console.log("Flatpak detected! Skipping app update check");
|
||||
return;
|
||||
}
|
||||
|
||||
hasRunAppUpdateCheckRef.current = true;
|
||||
checkForAppUpdate().catch((error) => {
|
||||
console.error("Error checking for app update:", error);
|
||||
});
|
||||
try {
|
||||
await checkForAppUpdate();
|
||||
} catch (e) {
|
||||
console.error("Error checking for app update:", e);
|
||||
}
|
||||
}
|
||||
handleAppUpdateCheck();
|
||||
}, [isSettingsStatePropagated, isKvPairsStatePropagated]);
|
||||
|
||||
// Check for yt-dlp auto-update
|
||||
|
||||
@@ -2,7 +2,9 @@ import { useLocation } from "react-router-dom";
|
||||
import { isActive } from "@/utils";
|
||||
import { config } from "@/config";
|
||||
import { useSettingsPageStatesStore } from "@/services/store";
|
||||
import { Github, Globe, Heart } from "lucide-react";
|
||||
import { Globe, Heart } from "lucide-react";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import { GithubIcon } from "@hugeicons/core-free-icons";
|
||||
import { IndianFlagLogo } from "@/components/icons/india";
|
||||
|
||||
export default function Footer() {
|
||||
@@ -20,10 +22,10 @@ export default function Footer() {
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<a href={config.appHomepage} target="_blank" className="text-sm text-muted-foreground hover:text-foreground" title="Homepage">
|
||||
<Globe className="w-4 h-4" />
|
||||
<Globe className="size-4" />
|
||||
</a>
|
||||
<a href={'https://github.com/' + config.appRepo} target="_blank" className="text-sm text-muted-foreground hover:text-foreground" title="GitHub">
|
||||
<Github className="w-4 h-4" />
|
||||
<HugeiconsIcon icon={GithubIcon} className="size-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,9 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { toast } from "sonner";
|
||||
import { BadgeCheck, BellRing, BrushCleaning, Bug, CircleCheck, Cookie, ExternalLink, FilePen, FileVideo, Folder, FolderOpen, Github, Globe, Heart, Info, KeyRound, Loader2, LucideIcon, Mail, Monitor, Moon, Package, Scale, ShieldMinus, SquareTerminal, Sun, Terminal, Timer, Trash, TriangleAlert, WandSparkles, Wifi, Wrench } from "lucide-react";
|
||||
import { BadgeCheck, BellRing, BrushCleaning, Bug, CircleCheck, Cookie, ExternalLink, FilePen, FileVideo, Folder, FolderOpen, Globe, Heart, Info, KeyRound, Loader2, LucideIcon, Mail, Monitor, Moon, Package, Scale, ShieldMinus, SquareTerminal, Sun, Terminal, Timer, Trash, TriangleAlert, WandSparkles, Wifi, Wrench } from "lucide-react";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import { GithubIcon } from "@hugeicons/core-free-icons";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Slider } from "@/components/ui/slider";
|
||||
import { Input } from "@/components/ui/input";
|
||||
@@ -128,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);
|
||||
|
||||
@@ -177,6 +180,15 @@ function AppGeneralSettings() {
|
||||
/>
|
||||
<Label htmlFor="max-retries" className="text-xs text-muted-foreground">(Current: {maxRetries}) (Default: 5, Maximum: 100)</Label>
|
||||
</div>
|
||||
<div className="quit-on-close">
|
||||
<h3 className="font-semibold">Quit on Close</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">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</p>
|
||||
<Switch
|
||||
id="quit-on-close"
|
||||
checked={quitOnClose}
|
||||
onCheckedChange={(checked) => saveSettingsKey('quit_on_close', checked)}
|
||||
/>
|
||||
</div>
|
||||
<div className="aria2">
|
||||
<h3 className="font-semibold">Aria2</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">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)</p>
|
||||
@@ -297,6 +309,7 @@ function AppFilesystemSettings() {
|
||||
const filenameTemplate = useSettingsPageStatesStore(state => state.settings.filename_template);
|
||||
const windowsFilenames = useSettingsPageStatesStore(state => state.settings.windows_filenames);
|
||||
const restrictFilenames = useSettingsPageStatesStore(state => state.settings.restrict_filenames);
|
||||
const uniqueFilenames = useSettingsPageStatesStore(state => state.settings.unique_filenames);
|
||||
|
||||
const downloadStates = useDownloadStatesStore(state => state.downloadStates);
|
||||
const ongoingDownloads = downloadStates.filter(state =>
|
||||
@@ -450,6 +463,15 @@ function AppFilesystemSettings() {
|
||||
</form>
|
||||
</Form>
|
||||
</div>
|
||||
<div className="unique-filenames">
|
||||
<h3 className="font-semibold">Unique Filenames</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Make filenames unique by appending download ID, playlist index at the end of the filename (recommended, disabling it may cause issue with some downloads, also it may cause paused downloads to re-start from begining)</p>
|
||||
<Switch
|
||||
id="unique-filenames"
|
||||
checked={uniqueFilenames}
|
||||
onCheckedChange={(checked) => saveSettingsKey('unique_filenames', checked)}
|
||||
/>
|
||||
</div>
|
||||
<div className="sanitize-filenames">
|
||||
<h3 className="font-semibold">Sanitize Filenames</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Make filenames windows-compatible, allow only ASCII characters and replace spaces with underscore (recommended, disabling it may cause issue with some downloads, also it may cause paused downloads to re-start from begining)</p>
|
||||
@@ -1793,7 +1815,7 @@ function AppInfoSettings() {
|
||||
<Globe className="size-3.5" />
|
||||
</a>
|
||||
<a href={'https://github.com/' + config.appRepo} target="_blank" className="text-sm text-foreground" title="GitHub">
|
||||
<Github className="size-3.5" />
|
||||
<HugeiconsIcon icon={GithubIcon} className="size-3.5" />
|
||||
</a>
|
||||
<p className="text-muted-foreground">•</p>
|
||||
<a href={config.appHomepage + '/privacy-policy'} target="_blank" className="text-xs hover:underline">Privacy Policy</a>
|
||||
@@ -1805,7 +1827,7 @@ function AppInfoSettings() {
|
||||
</div>
|
||||
<div className="about-developer">
|
||||
<h3 className="font-semibold">Developer</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Meet the Creator & Lead-Developer of NeoDLP</p>
|
||||
<p className="text-xs text-muted-foreground mb-3">Meet the Creator of NeoDLP</p>
|
||||
<Card className="p-4 space-y-4 flex items-center gap-4">
|
||||
<div className="relative w-fit m-0">
|
||||
<Avatar className="size-11">
|
||||
|
||||
@@ -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<boolean>(false);
|
||||
const appWindow = getCurrentWebviewWindow();
|
||||
const quitOnClose = useSettingsPageStatesStore(state => state.settings.quit_on_close);
|
||||
|
||||
const downloadStates = useDownloadStatesStore(state => state.downloadStates);
|
||||
const ongoingDownloads = downloadStates.filter(state =>
|
||||
['starting', 'downloading', 'queued'].includes(state.download_status)
|
||||
);
|
||||
const setIsPausingDownload = useDownloadActionStatesStore(state => state.setIsPausingDownload);
|
||||
const { pauseDownload } = useAppContext();
|
||||
|
||||
const stopOngoingDownloads = async () => {
|
||||
if (ongoingDownloads.length > 0) {
|
||||
for (const state of ongoingDownloads) {
|
||||
setIsPausingDownload(state.download_id, true);
|
||||
try {
|
||||
await pauseDownload(state);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
setIsPausingDownload(state.download_id, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="titlebar flex items-center justify-between border-b bg-background">
|
||||
@@ -48,7 +73,16 @@ export default function TitleBar() {
|
||||
className="px-4 py-3 hover:bg-destructive"
|
||||
id="titlebar-close"
|
||||
title="Close"
|
||||
onClick={() => appWindow.hide()}
|
||||
onClick={async () => {
|
||||
if (quitOnClose) {
|
||||
if (ongoingDownloads.length > 0) {
|
||||
await stopOngoingDownloads();
|
||||
}
|
||||
await appWindow.destroy();
|
||||
} else {
|
||||
await appWindow.hide()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
|
||||
+1
-1
@@ -6,5 +6,5 @@ export const config = {
|
||||
appSupportEmail: "support@neodlp.neosubhamoy.com",
|
||||
appAuthor: "Subhamoy Biswas",
|
||||
appAuthorUrl: "https://neosubhamoy.com",
|
||||
appAuthorSponsorUrl: "https://buymeacoffee.com/neosubhamoy",
|
||||
appAuthorSponsorUrl: "https://github.com/sponsors/neosubhamoy",
|
||||
}
|
||||
|
||||
@@ -74,7 +74,8 @@ export default function useDownloader() {
|
||||
disable_innertube: DISABLE_INNERTUBE,
|
||||
pot_server_port: POT_SERVER_PORT,
|
||||
windows_filenames: WINDOWS_FILENAMES,
|
||||
restrict_filenames: RESTRICT_FILENAMES
|
||||
restrict_filenames: RESTRICT_FILENAMES,
|
||||
unique_filenames: UNIQUE_FILENAMES,
|
||||
} = useSettingsPageStatesStore(state => state.settings);
|
||||
const isRunningPotServer = useSettingsPageStatesStore(state => state.isRunningPotServer);
|
||||
|
||||
@@ -349,9 +350,17 @@ export default function useDownloader() {
|
||||
}
|
||||
|
||||
if (isMultiplePlaylistItems) {
|
||||
args.push('--output', `%(playlist_title|Unknown)s[${downloadId}]/[%(playlist_index|0)d]_${FILENAME_TEMPLATE}.%(ext)s`);
|
||||
if (UNIQUE_FILENAMES) {
|
||||
args.push('--output', `%(playlist_title|Untitled)s[${downloadId}]/[%(playlist_index|0)d]_${FILENAME_TEMPLATE}.%(ext)s`);
|
||||
} else {
|
||||
args.push('--output', `%(playlist_title|Untitled)s/${FILENAME_TEMPLATE}.%(ext)s`);
|
||||
}
|
||||
} else {
|
||||
if (UNIQUE_FILENAMES) {
|
||||
args.push('--output', `${FILENAME_TEMPLATE}[${downloadId}].%(ext)s`);
|
||||
} else {
|
||||
args.push('--output', `${FILENAME_TEMPLATE}.%(ext)s`);
|
||||
}
|
||||
}
|
||||
|
||||
if (WINDOWS_FILENAMES) {
|
||||
|
||||
@@ -32,7 +32,6 @@ const TanstackProvider = ({children}: {children: React.ReactNode}) => {
|
||||
{
|
||||
name: 'TanStack Pacer',
|
||||
render: <PacerDevtoolsPanel />,
|
||||
defaultOpen: false
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -204,7 +204,7 @@ export const useSettingsPageStatesStore = create<SettingsPageStatesStore>((set)
|
||||
force_internet_protocol: 'ipv4',
|
||||
use_custom_commands: false,
|
||||
custom_commands: [],
|
||||
filename_template: '%(title|Unknown)s_%(resolution|unknown)s',
|
||||
filename_template: '%(title|Untitled)s_%(resolution|unknown)s',
|
||||
debug_mode: false,
|
||||
log_verbose: true,
|
||||
log_progress: false,
|
||||
@@ -223,6 +223,8 @@ export const useSettingsPageStatesStore = create<SettingsPageStatesStore>((set)
|
||||
pot_server_port: 4416,
|
||||
windows_filenames: true,
|
||||
restrict_filenames: true,
|
||||
unique_filenames: true,
|
||||
quit_on_close: false,
|
||||
// extension settings
|
||||
websocket_port: 53511
|
||||
},
|
||||
@@ -291,7 +293,7 @@ export const useSettingsPageStatesStore = create<SettingsPageStatesStore>((set)
|
||||
force_internet_protocol: 'ipv4',
|
||||
use_custom_commands: false,
|
||||
custom_commands: [],
|
||||
filename_template: '%(title|Unknown)s_%(resolution|unknown)s',
|
||||
filename_template: '%(title|Untitled)s_%(resolution|unknown)s',
|
||||
debug_mode: false,
|
||||
log_verbose: true,
|
||||
log_progress: false,
|
||||
@@ -310,6 +312,8 @@ export const useSettingsPageStatesStore = create<SettingsPageStatesStore>((set)
|
||||
pot_server_port: 4416,
|
||||
windows_filenames: true,
|
||||
restrict_filenames: true,
|
||||
unique_filenames: true,
|
||||
quit_on_close: false,
|
||||
// extension settings
|
||||
websocket_port: 53511
|
||||
},
|
||||
|
||||
@@ -66,6 +66,8 @@ export interface Settings {
|
||||
pot_server_port: number;
|
||||
windows_filenames: boolean;
|
||||
restrict_filenames: boolean;
|
||||
unique_filenames: boolean;
|
||||
quit_on_close: boolean;
|
||||
// extension settings
|
||||
websocket_port: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user