feat: Update version to 1.7.16 and add CollapsibleSection

This commit is contained in:
Peifan Li
2025-12-29 19:46:11 -05:00
parent 7b10b56cbf
commit e56db6d1cf
14 changed files with 124 additions and 110 deletions

View File

@@ -3,7 +3,7 @@
*/
export const VERSION = {
number: "1.7.15",
number: "1.7.16",
buildDate: new Date().toISOString().split("T")[0],
name: "MyTube Backend Server",
displayVersion: function () {

View File

@@ -0,0 +1,28 @@
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { Accordion, AccordionDetails, AccordionSummary, Typography } from '@mui/material';
import React, { ReactNode } from 'react';
interface CollapsibleSectionProps {
title: string;
children: ReactNode;
defaultExpanded?: boolean;
}
const CollapsibleSection: React.FC<CollapsibleSectionProps> = ({ title, children, defaultExpanded = true }) => {
return (
<Accordion defaultExpanded={defaultExpanded} sx={{ width: '100%', mb: 2 }}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls={`panel-${title.replace(/\s+/g, '-').toLowerCase()}-content`}
id={`panel-${title.replace(/\s+/g, '-').toLowerCase()}-header`}
>
<Typography variant="h6">{title}</Typography>
</AccordionSummary>
<AccordionDetails>
{children}
</AccordionDetails>
</Accordion>
);
};
export default CollapsibleSection;

View File

@@ -19,7 +19,6 @@ const AdvancedSettings: React.FC<AdvancedSettingsProps> = ({ debugMode, onDebugM
return (
<Box>
<Typography variant="h6" gutterBottom>{t('debugMode')}</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
{t('debugModeDescription')}
</Typography>

View File

@@ -288,7 +288,6 @@ const CloudDriveSettings: React.FC<CloudDriveSettingsProps> = ({ settings, onCha
return (
<Box>
<Typography variant="h6" gutterBottom>{t('cloudDriveSettings')} (beta)</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
{t('cloudDriveDescription')}
</Typography>

View File

@@ -57,9 +57,6 @@ const CloudflareSettings: React.FC<CloudflareSettingsProps> = ({ enabled, token,
return (
<Box>
<Typography variant="h6" >
{t('cloudflaredTunnel')}
</Typography>
<FormControlLabel
control={
<Switch

View File

@@ -83,7 +83,6 @@ const CookieSettings: React.FC<CookieSettingsProps> = ({ onSuccess, onError }) =
return (
<Box>
<Typography variant="h6" gutterBottom>{t('cookieSettings') || 'Cookie Settings'}</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
{t('cookieUploadDescription') || 'Upload cookies.txt to pass YouTube bot checks and enable Bilibili subtitle downloads. The file will be renamed to cookies.txt automatically. (Example: use "Get cookies.txt LOCALLY" extension to export cookies)'}
</Typography>

View File

@@ -129,7 +129,6 @@ const DatabaseSettings: React.FC<DatabaseSettingsProps> = ({
return (
<Box>
<Typography variant="h6" gutterBottom>{t('database')}</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
{t('migrateDataDescription')}
</Typography>

View File

@@ -22,7 +22,6 @@ const DownloadSettings: React.FC<DownloadSettingsProps> = ({
return (
<Box>
<Typography variant="h6" gutterBottom>{t('downloadSettings')}</Typography>
<Typography gutterBottom>
{t('maxConcurrent')}: {settings.maxConcurrentDownloads}
</Typography>

View File

@@ -135,7 +135,6 @@ const GeneralSettings: React.FC<GeneralSettingsProps> = (props) => {
return (
<Box>
<Typography variant="h6" gutterBottom>{t('general')}</Typography>
<Box sx={{ maxWidth: 400, display: 'flex', flexDirection: 'column', gap: 3 }}>
{!isVisitorMode && (
<>

View File

@@ -1,4 +1,4 @@
import { Box, FormControlLabel, Switch, TextField, Typography } from '@mui/material';
import { Box, FormControlLabel, Switch, TextField } from '@mui/material';
import React from 'react';
import { useLanguage } from '../../contexts/LanguageContext';
import { Settings } from '../../types';
@@ -13,7 +13,6 @@ const SecuritySettings: React.FC<SecuritySettingsProps> = ({ settings, onChange
return (
<Box>
<Typography variant="h6" gutterBottom>{t('security')}</Typography>
<FormControlLabel
control={
<Switch

View File

@@ -1,4 +1,4 @@
import { Box, Button, Chip, TextField, Typography } from '@mui/material';
import { Box, Button, Chip, TextField } from '@mui/material';
import React, { useState } from 'react';
import { useLanguage } from '../../contexts/LanguageContext';
@@ -27,7 +27,6 @@ const TagsSettings: React.FC<TagsSettingsProps> = ({ tags, onTagsChange }) => {
return (
<Box>
<Typography variant="h6" gutterBottom>{t('tagsManagement') || 'Tags Management'}</Typography>
<Box sx={{ display: 'flex', gap: 1, mb: 2, flexWrap: 'wrap' }}>
{tagsArray.length > 0 && tagsArray.map((tag) => (
<Chip

View File

@@ -1,4 +1,4 @@
import { Box, FormControlLabel, Switch, Typography } from '@mui/material';
import { Box, FormControlLabel, Switch } from '@mui/material';
import React from 'react';
import { useLanguage } from '../../contexts/LanguageContext';
import { Settings } from '../../types';
@@ -13,7 +13,6 @@ const VideoDefaultSettings: React.FC<VideoDefaultSettingsProps> = ({ settings, o
return (
<Box>
<Typography variant="h6" gutterBottom>{t('videoDefaults')}</Typography>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<FormControlLabel
control={

View File

@@ -242,9 +242,6 @@ const YtDlpSettings: React.FC<YtDlpSettingsProps> = ({ config, proxyOnlyYoutube
<Box>
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 2, mb: 2 }}>
<Box>
<Typography variant="h6" gutterBottom>
{t('ytDlpConfiguration') || 'yt-dlp Configuration'}
</Typography>
<Typography variant="body2" color="text.secondary">
{t('ytDlpConfigurationDescription') || 'Configure yt-dlp options. See '}
<Link

View File

@@ -6,7 +6,6 @@ import {
Card,
CardContent,
Container,
Divider,
Grid,
Snackbar,
Typography
@@ -14,6 +13,7 @@ import {
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
import React, { useEffect, useRef, useState } from 'react';
import CollapsibleSection from '../components/CollapsibleSection';
import ConfirmationModal from '../components/ConfirmationModal';
import AdvancedSettings from '../components/Settings/AdvancedSettings';
import CloudDriveSettings from '../components/Settings/CloudDriveSettings';
@@ -169,142 +169,143 @@ const SettingsPage: React.FC = () => {
<Grid container spacing={4}>
{/* General Settings - Only show visitor mode toggle when visitor mode is enabled */}
<Grid size={12}>
<GeneralSettings
language={settings.language}
websiteName={settings.websiteName}
itemsPerPage={settings.itemsPerPage}
showYoutubeSearch={settings.showYoutubeSearch}
visitorMode={settings.visitorMode}
savedVisitorMode={settingsData?.visitorMode}
infiniteScroll={settings.infiniteScroll}
videoColumns={settings.videoColumns}
<CollapsibleSection title={t('general')} defaultExpanded={true}>
<GeneralSettings
language={settings.language}
websiteName={settings.websiteName}
itemsPerPage={settings.itemsPerPage}
showYoutubeSearch={settings.showYoutubeSearch}
visitorMode={settings.visitorMode}
savedVisitorMode={settingsData?.visitorMode}
infiniteScroll={settings.infiniteScroll}
videoColumns={settings.videoColumns}
onChange={(field, value) => handleChange(field as keyof Settings, value)}
/>
onChange={(field, value) => handleChange(field as keyof Settings, value)}
/>
</CollapsibleSection>
</Grid>
<Grid size={12}><Divider /></Grid>
{/* Cloudflare Settings */}
<Grid size={12}>
<CloudflareSettings
enabled={settings.cloudflaredTunnelEnabled}
token={settings.cloudflaredToken}
visitorMode={visitorMode}
onChange={(field, value) => handleChange(field as keyof Settings, value)}
/>
<CollapsibleSection title={t('cloudflaredTunnel')} defaultExpanded={false}>
<CloudflareSettings
enabled={settings.cloudflaredTunnelEnabled}
token={settings.cloudflaredToken}
visitorMode={visitorMode}
onChange={(field, value) => handleChange(field as keyof Settings, value)}
/>
</CollapsibleSection>
</Grid>
{!visitorMode && (
<>
<Grid size={12}><Divider /></Grid>
{/* Cookie Upload Settings */}
<Grid size={12}>
<CookieSettings
onSuccess={(msg) => setMessage({ text: msg, type: 'success' })}
onError={(msg) => setMessage({ text: msg, type: 'error' })}
/>
<CollapsibleSection title={t('cookieSettings') || 'Cookie Settings'} defaultExpanded={false}>
<CookieSettings
onSuccess={(msg) => setMessage({ text: msg, type: 'success' })}
onError={(msg) => setMessage({ text: msg, type: 'error' })}
/>
</CollapsibleSection>
</Grid>
<Grid size={12}><Divider /></Grid>
{/* Security Settings */}
<Grid size={12}>
<SecuritySettings
settings={settings}
onChange={handleChange}
/>
<CollapsibleSection title={t('security')} defaultExpanded={false}>
<SecuritySettings
settings={settings}
onChange={handleChange}
/>
</CollapsibleSection>
</Grid>
<Grid size={12}><Divider /></Grid>
{/* Video Defaults */}
<Grid size={12}>
<VideoDefaultSettings
settings={settings}
onChange={handleChange}
/>
<CollapsibleSection title={t('videoDefaults')} defaultExpanded={false}>
<VideoDefaultSettings
settings={settings}
onChange={handleChange}
/>
</CollapsibleSection>
</Grid>
<Grid size={12}><Divider /></Grid>
{/* Tags Management */}
<Grid size={12}>
<TagsSettings
tags={Array.isArray(settings.tags) ? settings.tags : []}
onTagsChange={handleTagsChange}
/>
<CollapsibleSection title={t('tagsManagement') || 'Tags Management'} defaultExpanded={false}>
<TagsSettings
tags={Array.isArray(settings.tags) ? settings.tags : []}
onTagsChange={handleTagsChange}
/>
</CollapsibleSection>
</Grid>
<Grid size={12}><Divider /></Grid>
{/* Download Settings */}
<Grid size={12}>
<DownloadSettings
settings={settings}
onChange={handleChange}
activeDownloadsCount={activeDownloads.length}
onCleanup={() => setShowCleanupTempFilesModal(true)}
isSaving={isSaving}
/>
<CollapsibleSection title={t('downloadSettings')} defaultExpanded={false}>
<DownloadSettings
settings={settings}
onChange={handleChange}
activeDownloadsCount={activeDownloads.length}
onCleanup={() => setShowCleanupTempFilesModal(true)}
isSaving={isSaving}
/>
</CollapsibleSection>
</Grid>
<Grid size={12}><Divider /></Grid>
{/* Cloud Drive Settings */}
<Grid size={12}>
<CloudDriveSettings
settings={settings}
onChange={handleChange}
/>
<CollapsibleSection title={t('cloudDriveSettings')} defaultExpanded={false}>
<CloudDriveSettings
settings={settings}
onChange={handleChange}
/>
</CollapsibleSection>
</Grid>
<Grid size={12}><Divider /></Grid>
{/* Database Settings */}
<Grid size={12}>
<DatabaseSettings
onMigrate={() => setShowMigrateConfirmModal(true)}
onDeleteLegacy={() => setShowDeleteLegacyModal(true)}
onFormatFilenames={() => setShowFormatConfirmModal(true)}
onExportDatabase={handleExportDatabase}
onImportDatabase={handleImportDatabase}
onCleanupBackupDatabases={handleCleanupBackupDatabases}
onRestoreFromLastBackup={handleRestoreFromLastBackup}
isSaving={isSaving}
lastBackupInfo={lastBackupInfo}
moveSubtitlesToVideoFolder={settings.moveSubtitlesToVideoFolder || false}
onMoveSubtitlesToVideoFolderChange={(checked) => handleChange('moveSubtitlesToVideoFolder', checked)}
moveThumbnailsToVideoFolder={settings.moveThumbnailsToVideoFolder || false}
onMoveThumbnailsToVideoFolderChange={(checked) => handleChange('moveThumbnailsToVideoFolder', checked)}
/>
<CollapsibleSection title={t('database')} defaultExpanded={false}>
<DatabaseSettings
onMigrate={() => setShowMigrateConfirmModal(true)}
onDeleteLegacy={() => setShowDeleteLegacyModal(true)}
onFormatFilenames={() => setShowFormatConfirmModal(true)}
onExportDatabase={handleExportDatabase}
onImportDatabase={handleImportDatabase}
onCleanupBackupDatabases={handleCleanupBackupDatabases}
onRestoreFromLastBackup={handleRestoreFromLastBackup}
isSaving={isSaving}
lastBackupInfo={lastBackupInfo}
moveSubtitlesToVideoFolder={settings.moveSubtitlesToVideoFolder || false}
onMoveSubtitlesToVideoFolderChange={(checked) => handleChange('moveSubtitlesToVideoFolder', checked)}
moveThumbnailsToVideoFolder={settings.moveThumbnailsToVideoFolder || false}
onMoveThumbnailsToVideoFolderChange={(checked) => handleChange('moveThumbnailsToVideoFolder', checked)}
/>
</CollapsibleSection>
</Grid>
<Grid size={12}><Divider /></Grid>
{/* yt-dlp Configuration */}
<Grid size={12}>
<YtDlpSettings
config={settings.ytDlpConfig || ''}
proxyOnlyYoutube={settings.proxyOnlyYoutube || false}
onChange={(config) => handleChange('ytDlpConfig', config)}
onProxyOnlyYoutubeChange={(checked) => handleChange('proxyOnlyYoutube', checked)}
/>
<CollapsibleSection title={t('ytDlpConfiguration') || 'yt-dlp Configuration'} defaultExpanded={false}>
<YtDlpSettings
config={settings.ytDlpConfig || ''}
proxyOnlyYoutube={settings.proxyOnlyYoutube || false}
onChange={(config) => handleChange('ytDlpConfig', config)}
onProxyOnlyYoutubeChange={(checked) => handleChange('proxyOnlyYoutube', checked)}
/>
</CollapsibleSection>
</Grid>
<Grid size={12}><Divider /></Grid>
{/* Advanced Settings */}
<Grid size={12}>
<AdvancedSettings
debugMode={debugMode}
onDebugModeChange={setDebugMode}
/>
<CollapsibleSection title={t('debugMode') || 'Advanced Settings'} defaultExpanded={false}>
<AdvancedSettings
debugMode={debugMode}
onDebugModeChange={setDebugMode}
/>
</CollapsibleSection>
</Grid>
</>
)}
</Grid>
</CardContent>
</Card>