mirror of
https://github.com/neosubhamoy/neodlp.git
synced 2025-12-19 01:32:57 +05:30
feat: added debug mode and optimized logging
This commit is contained in:
16
src/App.tsx
16
src/App.tsx
@@ -88,6 +88,10 @@ export default function App({ children }: { children: React.ReactNode }) {
|
||||
const USE_CUSTOM_COMMANDS = useSettingsPageStatesStore(state => state.settings.use_custom_commands);
|
||||
const CUSTOM_COMMANDS = useSettingsPageStatesStore(state => state.settings.custom_commands);
|
||||
const FILENAME_TEMPLATE = useSettingsPageStatesStore(state => state.settings.filename_template);
|
||||
const DEBUG_MODE = useSettingsPageStatesStore(state => state.settings.debug_mode);
|
||||
const LOG_VERBOSE = useSettingsPageStatesStore(state => state.settings.log_verbose);
|
||||
const LOG_WARNING = useSettingsPageStatesStore(state => state.settings.log_warning);
|
||||
const LOG_PROGRESS = useSettingsPageStatesStore(state => state.settings.log_progress);
|
||||
|
||||
const isErrored = useDownloaderPageStatesStore((state) => state.isErrored);
|
||||
const isErrorExpected = useDownloaderPageStatesStore((state) => state.isErrorExpected);
|
||||
@@ -295,7 +299,6 @@ export default function App({ children }: { children: React.ReactNode }) {
|
||||
'--format',
|
||||
selectedFormat,
|
||||
'--no-mtime',
|
||||
'--no-warnings',
|
||||
'--retries',
|
||||
MAX_RETRIES.toString(),
|
||||
];
|
||||
@@ -304,6 +307,14 @@ export default function App({ children }: { children: React.ReactNode }) {
|
||||
args.push('--ffmpeg-location', '/Applications/NeoDLP.app/Contents/MacOS');
|
||||
}
|
||||
|
||||
if (!DEBUG_MODE || (DEBUG_MODE && !LOG_WARNING)) {
|
||||
args.push('--no-warnings');
|
||||
}
|
||||
|
||||
if (DEBUG_MODE && LOG_VERBOSE) {
|
||||
args.push('--verbose');
|
||||
}
|
||||
|
||||
if (selectedSubtitles) {
|
||||
args.push('--embed-subs', '--sub-lang', selectedSubtitles);
|
||||
}
|
||||
@@ -462,7 +473,7 @@ export default function App({ children }: { children: React.ReactNode }) {
|
||||
command.stdout.on('data', line => {
|
||||
if (line.startsWith('status:') || line.startsWith('[#')) {
|
||||
console.log(line);
|
||||
LOG.info(`YT-DLP Download ${downloadId}`, line);
|
||||
if (DEBUG_MODE && LOG_PROGRESS) LOG.progress(`YT-DLP Download ${downloadId}`, line);
|
||||
const currentProgress = parseProgressLine(line);
|
||||
const state: DownloadState = {
|
||||
download_id: downloadId,
|
||||
@@ -653,6 +664,7 @@ export default function App({ children }: { children: React.ReactNode }) {
|
||||
|
||||
if (!ongoingDownloads || ongoingDownloads && ongoingDownloads?.length < MAX_PARALLEL_DOWNLOADS) {
|
||||
LOG.info('NEODLP', `Starting yt-dlp download with args: ${args.join(' ')}`);
|
||||
if(!DEBUG_MODE || (DEBUG_MODE && !LOG_PROGRESS)) LOG.warning('NEODLP', `Progress logs are hidden. Enable 'Debug Mode > Log Progress' in Settings to unhide.`);
|
||||
const child = await command.spawn();
|
||||
processPid = child.pid;
|
||||
return Promise.resolve();
|
||||
|
||||
@@ -41,7 +41,7 @@ export default function Navbar() {
|
||||
<p className="text-sm text-muted-foreground">NO LOGS TO SHOW!</p>
|
||||
) : (
|
||||
logs.slice().reverse().map((log, index) => (
|
||||
<div key={index} className={`flex flex-col ${log.level === 'error' ? 'text-red-500' : log.level === 'warning' ? 'text-amber-500' : log.level === 'debug' ? 'text-sky-500' : 'text-foreground'}`}>
|
||||
<div key={index} className={`flex flex-col ${log.level === 'error' ? 'text-red-500' : log.level === 'warning' ? 'text-amber-500' : log.level === 'debug' ? 'text-sky-500' : log.level === 'progress' ? 'text-emerald-500' : 'text-foreground'}`}>
|
||||
<p className="text-xs"><strong>{new Date(log.timestamp).toLocaleTimeString()}</strong> [{log.level.toUpperCase()}] <em>{log.context}</em> :</p>
|
||||
<p className="text-xs font-mono break-all">{log.message}</p>
|
||||
</div>
|
||||
|
||||
@@ -18,9 +18,12 @@ export function useLogger() {
|
||||
debug: (context: string, message: string) => {
|
||||
addLog({ timestamp: Date.now(), level: 'debug', context, message });
|
||||
},
|
||||
progress: (context: string, message: string) => {
|
||||
addLog({ timestamp: Date.now(), level: 'progress', context, message });
|
||||
},
|
||||
getLogs: () => logs,
|
||||
clearLogs,
|
||||
};
|
||||
|
||||
return logger;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Progress } from "@/components/ui/progress";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { toast } from "sonner";
|
||||
import { useAppContext } from "@/providers/appContextProvider";
|
||||
import { useCurrentVideoMetadataStore, useDownloadActionStatesStore, useDownloadStatesStore, useLibraryPageStatesStore } from "@/services/store";
|
||||
import { useCurrentVideoMetadataStore, useDownloadActionStatesStore, useDownloadStatesStore, useLibraryPageStatesStore, useSettingsPageStatesStore } from "@/services/store";
|
||||
import { formatBitrate, formatCodec, formatDurationString, formatFileSize, formatSecToTimeString, formatSpeed } from "@/utils";
|
||||
import { AudioLines, Clock, File, FileAudio2, FileQuestion, FileVideo2, FolderInput, ListVideo, Loader2, Music, Pause, Play, Search, Square, Trash2, Video, X } from "lucide-react";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
@@ -34,6 +34,8 @@ export default function LibraryPage() {
|
||||
const setIsCancelingDownload = useDownloadActionStatesStore(state => state.setIsCancelingDownload);
|
||||
const setIsDeleteFileChecked = useDownloadActionStatesStore(state => state.setIsDeleteFileChecked);
|
||||
|
||||
const debugMode = useSettingsPageStatesStore(state => state.settings.debug_mode);
|
||||
|
||||
const { pauseDownload, resumeDownload, cancelDownload } = useAppContext()
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
@@ -379,7 +381,7 @@ export default function LibraryPage() {
|
||||
</div>
|
||||
)}
|
||||
<div className="text-xs text-muted-foreground">{ state.download_status && (
|
||||
`${state.download_status === 'downloading' && state.status === 'finished' ? 'Processing' : state.download_status.charAt(0).toUpperCase() + state.download_status.slice(1)} ${state.download_id ? `• ID: ${state.download_id.toUpperCase()}` : ""} ${state.download_status === 'downloading' && state.status !== 'finished' && state.speed ? `• Speed: ${formatSpeed(state.speed)}` : ""} ${state.download_status === 'downloading' && state.eta ? `• ETA: ${formatSecToTimeString(state.eta)}` : ""}`
|
||||
`${state.download_status === 'downloading' && state.status === 'finished' ? 'Processing' : state.download_status.charAt(0).toUpperCase() + state.download_status.slice(1)} ${debugMode && state.download_id ? `• ID: ${state.download_id.toUpperCase()}` : ""} ${state.download_status === 'downloading' && state.status !== 'finished' && state.speed ? `• Speed: ${formatSpeed(state.speed)}` : ""} ${state.download_status === 'downloading' && state.eta ? `• ETA: ${formatSecToTimeString(state.eta)}` : ""}`
|
||||
)}</div>
|
||||
</div>
|
||||
<div className="w-full flex items-center gap-2 mt-2">
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { toast } from "sonner";
|
||||
import { ArrowDownToLine, ArrowRight, BrushCleaning, Cookie, EthernetPort, ExternalLink, FileVideo, Folder, FolderOpen, Info, Loader2, LucideIcon, Monitor, Moon, Radio, RotateCcw, RotateCw, ShieldMinus, SquareTerminal, Sun, Terminal, Trash, TriangleAlert, WandSparkles, Wifi, Wrench } from "lucide-react";
|
||||
import { ArrowDownToLine, ArrowRight, BrushCleaning, Bug, Cookie, EthernetPort, ExternalLink, FileVideo, Folder, FolderOpen, Info, Loader2, LucideIcon, Monitor, Moon, Radio, RotateCcw, RotateCw, ShieldMinus, SquareTerminal, Sun, Terminal, Trash, TriangleAlert, WandSparkles, Wifi, Wrench } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useEffect } from "react";
|
||||
import { useTheme } from "@/providers/themeProvider";
|
||||
@@ -123,6 +123,10 @@ export default function SettingsPage() {
|
||||
const useCustomCommands = useSettingsPageStatesStore(state => state.settings.use_custom_commands);
|
||||
const customCommands = useSettingsPageStatesStore(state => state.settings.custom_commands);
|
||||
const filenameTemplate = useSettingsPageStatesStore(state => state.settings.filename_template);
|
||||
const debugMode = useSettingsPageStatesStore(state => state.settings.debug_mode);
|
||||
const logVerbose = useSettingsPageStatesStore(state => state.settings.log_verbose);
|
||||
const logWarning = useSettingsPageStatesStore(state => state.settings.log_warning);
|
||||
const logProgress = useSettingsPageStatesStore(state => state.settings.log_progress);
|
||||
|
||||
const websocketPort = useSettingsPageStatesStore(state => state.settings.websocket_port);
|
||||
const isChangingWebSocketPort = useSettingsPageStatesStore(state => state.isChangingWebSocketPort);
|
||||
@@ -525,9 +529,14 @@ export default function SettingsPage() {
|
||||
value="commands"
|
||||
className="data-[state=active]:bg-primary data-[state=active]:text-primary-foreground justify-start px-3 py-1.5 gap-2"
|
||||
><SquareTerminal className="size-4" /> Commands</TabsTrigger>
|
||||
<TabsTrigger
|
||||
key="debug"
|
||||
value="debug"
|
||||
className="data-[state=active]:bg-primary data-[state=active]:text-primary-foreground justify-start px-3 py-1.5 gap-2"
|
||||
><Bug className="size-4" /> Debug</TabsTrigger>
|
||||
</TabsList>
|
||||
<div className="min-h-full flex flex-col max-w-[55%] w-full border-l border-border pl-4">
|
||||
<TabsContent key="general" value="general" className="flex flex-col gap-4 min-h-[350px]">
|
||||
<TabsContent key="general" value="general" className="flex flex-col gap-4 min-h-[385px]">
|
||||
<div className="max-parallel-downloads">
|
||||
<h3 className="font-semibold">Max Parallel Downloads</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Set maximum number of allowed parallel downloads</p>
|
||||
@@ -583,7 +592,7 @@ export default function SettingsPage() {
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent key="appearance" value="appearance" className="flex flex-col gap-4 min-h-[350px]">
|
||||
<TabsContent key="appearance" value="appearance" className="flex flex-col gap-4 min-h-[385px]">
|
||||
<div className="app-theme">
|
||||
<h3 className="font-semibold">Theme</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Choose app interface theme</p>
|
||||
@@ -606,7 +615,7 @@ export default function SettingsPage() {
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent key="folders" value="folders" className="flex flex-col gap-4 min-h-[350px]">
|
||||
<TabsContent key="folders" value="folders" className="flex flex-col gap-4 min-h-[385px]">
|
||||
<div className="download-dir">
|
||||
<h3 className="font-semibold">Download Folder</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Set default download folder (directory)</p>
|
||||
@@ -696,7 +705,7 @@ export default function SettingsPage() {
|
||||
</Form>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent key="formats" value="formats" className="flex flex-col gap-4 min-h-[350px]">
|
||||
<TabsContent key="formats" value="formats" className="flex flex-col gap-4 min-h-[385px]">
|
||||
<div className="video-format">
|
||||
<h3 className="font-semibold">Video Format</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Choose in which format the final video file will be saved</p>
|
||||
@@ -764,7 +773,7 @@ export default function SettingsPage() {
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent key="metadata" value="metadata" className="flex flex-col gap-4 min-h-[350px]">
|
||||
<TabsContent key="metadata" value="metadata" className="flex flex-col gap-4 min-h-[385px]">
|
||||
<div className="embed-video-metadata">
|
||||
<h3 className="font-semibold">Embed Metadata</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Wheather to embed metadata in video/audio files (info, chapters)</p>
|
||||
@@ -798,7 +807,7 @@ export default function SettingsPage() {
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent key="network" value="network" className="flex flex-col gap-4 min-h-[350px]">
|
||||
<TabsContent key="network" value="network" className="flex flex-col gap-4 min-h-[385px]">
|
||||
<div className="proxy">
|
||||
<h3 className="font-semibold">Proxy</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Use proxy for downloads, Unblocks blocked sites in your region (download speed may affect, some sites may not work)</p>
|
||||
@@ -893,7 +902,7 @@ export default function SettingsPage() {
|
||||
onCheckedChange={(checked) => saveSettingsKey('use_force_internet_protocol', checked)}
|
||||
disabled={useCustomCommands}
|
||||
/>
|
||||
<Label htmlFor="use-force-internet-protocol">Force</Label>
|
||||
<Label htmlFor="use-force-internet-protocol">Force IPV</Label>
|
||||
</div>
|
||||
<RadioGroup
|
||||
orientation="horizontal"
|
||||
@@ -914,7 +923,7 @@ export default function SettingsPage() {
|
||||
<Label className="text-xs text-muted-foreground">(Forced: {forceInternetProtocol === "ipv4" ? 'IPv4' : 'IPv6'}, Status: {useForceInternetProtocol && !useCustomCommands ? 'Enabled' : 'Disabled'})</Label>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent key="cookies" value="cookies" className="flex flex-col gap-4 min-h-[350px]">
|
||||
<TabsContent key="cookies" value="cookies" className="flex flex-col gap-4 min-h-[385px]">
|
||||
<div className="cookies">
|
||||
<h3 className="font-semibold">Cookies</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Use cookies to access exclusive/private (login-protected) contents from sites (use wisely, over-use can even block/ban your account)</p>
|
||||
@@ -1003,7 +1012,7 @@ export default function SettingsPage() {
|
||||
<Label className="text-xs text-muted-foreground">(Configured: {importCookiesFrom === "browser" ? 'Yes' : cookiesFile ? 'Yes' : 'No'}, From: {importCookiesFrom === "browser" ? 'Browser' : 'Text'}, Status: {useCookies && !useCustomCommands ? 'Enabled' : 'Disabled'})</Label>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent key="sponsorblock" value="sponsorblock" className="flex flex-col gap-4 min-h-[350px]">
|
||||
<TabsContent key="sponsorblock" value="sponsorblock" className="flex flex-col gap-4 min-h-[385px]">
|
||||
<div className="sponsorblock">
|
||||
<h3 className="font-semibold">Sponsor Block</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Use sponsorblock to remove/mark unwanted segments in videos (sponsorships, intros, outros, etc.)</p>
|
||||
@@ -1127,7 +1136,7 @@ export default function SettingsPage() {
|
||||
<Label className="text-xs text-muted-foreground">(Configured: {sponsorblockMode === "remove" && sponsorblockRemove === "custom" && sponsorblockRemoveCategories.length <= 0 ? 'No' : sponsorblockMode === "mark" && sponsorblockMark === "custom" && sponsorblockMarkCategories.length <= 0 ? 'No' : 'Yes'}, Mode: {sponsorblockMode === "remove" ? 'Remove' : 'Mark'}, Status: {useSponsorblock && !useCustomCommands ? 'Enabled' : 'Disabled'})</Label>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent key="commands" value="commands" className="flex flex-col gap-4 min-h-[350px]">
|
||||
<TabsContent key="commands" value="commands" className="flex flex-col gap-4 min-h-[385px]">
|
||||
<div className="custom-commands">
|
||||
<h3 className="font-semibold">Custom Commands</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3"> Run custom yt-dlp commands for your downloads</p>
|
||||
@@ -1229,6 +1238,50 @@ export default function SettingsPage() {
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent key="debug" value="debug" className="flex flex-col gap-4 min-h-[385px]">
|
||||
<div className="debug-mode">
|
||||
<h3 className="font-semibold">Debug Mode</h3>
|
||||
<p className="text-xs text-muted-foreground mb-3">Enable debug mode for troubleshooting issues (get debug logs, download ids, and more)</p>
|
||||
<div className="flex items-center space-x-2 mb-4">
|
||||
<Switch
|
||||
id="debug-mode"
|
||||
checked={debugMode}
|
||||
onCheckedChange={(checked) => saveSettingsKey('debug_mode', checked)}
|
||||
/>
|
||||
<Label htmlFor="debug-mode">Enable Debug Mode</Label>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 mt-5">
|
||||
<Label className="text-xs mb-1">Logging Options</Label>
|
||||
<div className="flex items-center space-x-2 mb-1">
|
||||
<Switch
|
||||
id="log-verbose"
|
||||
checked={logVerbose}
|
||||
onCheckedChange={(checked) => saveSettingsKey('log_verbose', checked)}
|
||||
disabled={!debugMode}
|
||||
/>
|
||||
<Label htmlFor="log-verbose">Verbose Logging</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 mb-1">
|
||||
<Switch
|
||||
id="log-warning"
|
||||
checked={logWarning}
|
||||
onCheckedChange={(checked) => saveSettingsKey('log_warning', checked)}
|
||||
disabled={!debugMode}
|
||||
/>
|
||||
<Label htmlFor="log-warning">Log Warnings</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 mb-1">
|
||||
<Switch
|
||||
id="log-progress"
|
||||
checked={logProgress}
|
||||
onCheckedChange={(checked) => saveSettingsKey('log_progress', checked)}
|
||||
disabled={!debugMode}
|
||||
/>
|
||||
<Label htmlFor="log-progress">Log Progress</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
</TabsContent>
|
||||
|
||||
@@ -180,6 +180,10 @@ export const useSettingsPageStatesStore = create<SettingsPageStatesStore>((set)
|
||||
use_custom_commands: false,
|
||||
custom_commands: [],
|
||||
filename_template: '%(title)s_%(resolution|unknown)s',
|
||||
debug_mode: false,
|
||||
log_verbose: true,
|
||||
log_warning: true,
|
||||
log_progress: false,
|
||||
// extension settings
|
||||
websocket_port: 53511
|
||||
},
|
||||
@@ -241,6 +245,10 @@ export const useSettingsPageStatesStore = create<SettingsPageStatesStore>((set)
|
||||
use_custom_commands: false,
|
||||
custom_commands: [],
|
||||
filename_template: '%(title)s_%(resolution|unknown)s',
|
||||
debug_mode: false,
|
||||
log_verbose: true,
|
||||
log_warning: true,
|
||||
log_progress: false,
|
||||
// extension settings
|
||||
websocket_port: 53511
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export interface Log {
|
||||
timestamp: number;
|
||||
level: 'info' | 'warning' | 'error' | 'debug';
|
||||
level: 'info' | 'warning' | 'error' | 'debug' | 'progress';
|
||||
context: string;
|
||||
message: string;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@ export interface Settings {
|
||||
use_custom_commands: boolean;
|
||||
custom_commands: CustomCommand[];
|
||||
filename_template: string;
|
||||
debug_mode: boolean;
|
||||
log_verbose: boolean;
|
||||
log_warning: boolean;
|
||||
log_progress: boolean;
|
||||
// extension settings
|
||||
websocket_port: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user