From 49869792cf70a6c278d6cb302a08b42cf1fe84db Mon Sep 17 00:00:00 2001 From: zarzet Date: Sat, 13 Jun 2026 15:37:00 +0700 Subject: [PATCH] chore: trim redundant comments --- go_backend/extension_manager.go | 8 +++----- ios/Runner/AppDelegate.swift | 17 ++-------------- lib/app.dart | 8 ++------ lib/main.dart | 6 ++---- lib/providers/download_queue_provider.dart | 4 +--- lib/providers/store_provider.dart | 5 +---- lib/screens/queue_tab.dart | 20 +++++++------------ lib/screens/settings/files_settings_page.dart | 12 ++--------- lib/screens/track_metadata_edit_sheet.dart | 15 ++++---------- lib/screens/track_metadata_screen.dart | 2 -- lib/services/platform_bridge.dart | 8 ++------ lib/widgets/animation_utils.dart | 9 +++------ lib/widgets/batch_convert_sheet.dart | 12 +---------- 13 files changed, 30 insertions(+), 96 deletions(-) diff --git a/go_backend/extension_manager.go b/go_backend/extension_manager.go index 3f2a21d4..091e3d32 100644 --- a/go_backend/extension_manager.go +++ b/go_backend/extension_manager.go @@ -119,11 +119,9 @@ func (ext *loadedExtension) lockReadyVM() (*goja.Runtime, error) { type extensionManager struct { mu sync.RWMutex - // mutationMu serializes heavy mutating operations (install / upgrade / - // remove). These tear down and re-extract files and rebuild goja VMs; - // running two at once (e.g. updating two extensions simultaneously) races - // the non-thread-safe goja runtime and can hard-crash the process. Always - // acquired before m.mu; internal "*Locked" helpers assume it is held. + // mutationMu serializes install/upgrade/remove (heavy FS + goja VM + // teardown/reload), which are not safe to run concurrently. Acquired before + // m.mu; "*Locked" helpers assume it is held. mutationMu sync.Mutex extensions map[string]*loadedExtension extensionsDir string diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 2aa7fe9f..09a0ba72 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -21,11 +21,8 @@ import Gobackend // Import Go framework /// Currently accessed security-scoped URL for library folder private var activeSecurityScopedURL: URL? - /// Whether a download queue is currently active. When true, the app begins a - /// fresh background task each time it enters the background so an in-flight - /// download keeps running for the limited window iOS allows. iOS has no - /// foreground-service equivalent, so this is best-effort. Only touched on the - /// main thread. + /// Whether a download queue is active; while true a background task is + /// started on each background entry to extend execution time. Main-thread only. private var downloadsActive = false private var downloadBackgroundTask: UIBackgroundTaskIdentifier = .invalid @@ -241,17 +238,12 @@ import Gobackend // Import Go framework } private func handleMethodCall(call: FlutterMethodCall, result: @escaping FlutterResult) { - // Background-task management must run on the main thread and does not - // touch the Go backend, so handle it directly without dispatching. switch call.method { case "beginBackgroundDownloadTask": - // Queue started: remember it so we extend background time whenever - // the app is backgrounded while downloads run. downloadsActive = true result(nil) return case "endBackgroundDownloadTask": - // Queue finished/paused: stop extending background time. downloadsActive = false endBackgroundDownloadTask() result(nil) @@ -283,14 +275,9 @@ import Gobackend // Import Go framework override func applicationWillEnterForeground(_ application: UIApplication) { super.applicationWillEnterForeground(application) - // No background-time countdown while in the foreground. endBackgroundDownloadTask() } - /// Begins a background task (if one is not already active) so an in-flight - /// download keeps running for the limited window iOS allows after the app is - /// backgrounded. The expiration handler ends the task to avoid the app being - /// force-terminated by the watchdog. Must run on the main thread. private func beginBackgroundDownloadTask() { if downloadBackgroundTask != .invalid { return } downloadBackgroundTask = UIApplication.shared.beginBackgroundTask( diff --git a/lib/app.dart b/lib/app.dart index fde40a5a..41c9d0fe 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -114,12 +114,8 @@ class SpotiFLACApp extends ConsumerWidget { scrollBehavior: scrollBehavior, themeAnimationDuration: const Duration(milliseconds: 300), themeAnimationCurve: Curves.easeInOut, - // Treat the display as one continuous surface. Some large/foldable - // devices report a full-height display feature (hinge/cutout) which - // makes Flutter split modal routes into a sub-screen, leaving bottom - // sheets and dialogs visibly off-center instead of centered on the - // full screen. Clearing displayFeatures keeps them centered for every - // modal/dialog generically, without per-sheet workarounds. + // Treat the display as one continuous surface so bottom sheets and + // dialogs stay centered on large/foldable devices. builder: (context, child) { final mediaQuery = MediaQuery.of(context); return MediaQuery( diff --git a/lib/main.dart b/lib/main.dart index 76410a1b..e00ebd1b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -20,10 +20,8 @@ import 'package:spotiflac_android/utils/logger.dart'; final _log = AppLogger('Main'); void main() { - // Catch uncaught errors so a failure in a provider/async path (e.g. a - // misbehaving extension request) is logged instead of taking the whole app - // down. Native (Go) fatal crashes can't be caught here, but Dart-side ones - // can. + // Catch uncaught Dart errors so a failing async path is logged, not fatal. + // Native (Go) crashes still can't be caught here. runZonedGuarded( () async { WidgetsFlutterBinding.ensureInitialized(); diff --git a/lib/providers/download_queue_provider.dart b/lib/providers/download_queue_provider.dart index 52b4b45e..fc6d5b24 100644 --- a/lib/providers/download_queue_provider.dart +++ b/lib/providers/download_queue_provider.dart @@ -6676,9 +6676,7 @@ class DownloadQueueNotifier extends Notifier { } } - // iOS has no foreground service; request a background execution window so - // an in-flight download can keep running for a short time after the app is - // backgrounded instead of being suspended immediately. + // iOS: request a background execution window (no foreground service). if (Platform.isIOS && _totalQueuedAtStart > 0) { await PlatformBridge.beginBackgroundDownloadTask(); } diff --git a/lib/providers/store_provider.dart b/lib/providers/store_provider.dart index 4d9ed74b..4691bb05 100644 --- a/lib/providers/store_provider.dart +++ b/lib/providers/store_provider.dart @@ -206,10 +206,7 @@ class StoreState { } class StoreNotifier extends Notifier { - /// Serializes extension install/upgrade operations. Running two of these at - /// once (e.g. updating two extensions simultaneously) races the native - /// extension manager's goja VM teardown/reload and can hard-crash the app, so - /// they must run strictly one at a time. + /// Serializes install/upgrade so two never race the native VM teardown/reload. Future _mutationChain = Future.value(); Future _runSerialized(Future Function() action) { diff --git a/lib/screens/queue_tab.dart b/lib/screens/queue_tab.dart index 9870c874..abcb47ae 100644 --- a/lib/screens/queue_tab.dart +++ b/lib/screens/queue_tab.dart @@ -123,10 +123,8 @@ class _QueueTabState extends ConsumerState { List _selectionOverlayItems = const []; double _selectionOverlayBottomPadding = 0; - /// When true, the floating selection overlays are kept hidden even though - /// selection mode is still active. Used while a modal sheet/dialog launched - /// from the selection toolbar is open, so the overlay does not reappear on - /// top of (or behind) the modal's open/close animation. + /// Keeps the selection overlays hidden while a modal launched from the + /// selection toolbar is open, so they don't reappear over its animation. bool _suppressSelectionOverlay = false; bool _isPlaylistSelectionMode = false; @@ -4849,9 +4847,8 @@ class _QueueTabState extends ConsumerState { var didStartConversion = false; - // Resolve localized strings up front: the builder closure must not look up - // Localizations via the outer (State) context, which may be deactivated by - // the time the root-navigator sheet rebuilds. + // Resolve localized strings up front; the builder must not look up + // Localizations via the (possibly deactivated) State context. final sheetTitle = context.l10n.selectionBatchConvertConfirmTitle; final sheetConfirmLabel = context.l10n.selectionConvertCount( _selectedIds.length, @@ -4883,10 +4880,8 @@ class _QueueTabState extends ConsumerState { ), ); - // The showModalBottomSheet future completes when the sheet begins closing, - // not when its exit animation finishes. Wait out the exit transition - // (~200ms) before restoring the selection toolbar so it does not pop in - // front of the still-animating sheet. + // Wait out the sheet's exit animation before restoring the toolbar so it + // doesn't pop in front of the still-closing sheet. await Future.delayed(const Duration(milliseconds: 260)); if (!mounted) { _suppressSelectionOverlay = false; @@ -5321,8 +5316,7 @@ class _QueueTabState extends ConsumerState { return; } if (confirmed != true) { - // Restore after the dialog's exit animation so the toolbar does not - // appear in front of the closing dialog. + // Restore after the dialog's exit animation. await Future.delayed(const Duration(milliseconds: 220)); _suppressSelectionOverlay = false; if (!mounted) return; diff --git a/lib/screens/settings/files_settings_page.dart b/lib/screens/settings/files_settings_page.dart index 84fa6111..4cf17568 100644 --- a/lib/screens/settings/files_settings_page.dart +++ b/lib/screens/settings/files_settings_page.dart @@ -712,10 +712,6 @@ class _FilesSettingsPageState extends ConsumerState { final save = onSave ?? ref.read(settingsProvider.notifier).setFilenameFormat; - // The controller is owned by a StatefulWidget so it is disposed in its - // State.dispose() (after the subtree is removed), instead of in - // whenComplete which fires while the closing/keyboard-hide animations can - // still rebuild the TextField and touch a disposed controller. showModalBottomSheet( context: context, isScrollControlled: true, @@ -938,12 +934,8 @@ class _FolderOption extends StatelessWidget { } -/// Bottom sheet body for editing a filename format. Owns its -/// [TextEditingController] and disposes it in [dispose], which runs only after -/// the sheet's subtree has been removed from the tree. This avoids the -/// "TextEditingController used after being disposed" crash that happens when -/// the controller is torn down in `whenComplete` while the closing and -/// keyboard-hide animations are still rebuilding the field. +/// Bottom sheet for editing a filename format. Owns its controller and disposes +/// it in [dispose] to avoid use-after-dispose during the close animation. class _FilenameFormatEditorSheet extends StatefulWidget { final String initialText; final void Function(String) onSave; diff --git a/lib/screens/track_metadata_edit_sheet.dart b/lib/screens/track_metadata_edit_sheet.dart index b9840864..26ffb351 100644 --- a/lib/screens/track_metadata_edit_sheet.dart +++ b/lib/screens/track_metadata_edit_sheet.dart @@ -1699,9 +1699,8 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> { ); } - /// Fill for the modern input fields. Sits one elevation step apart from the - /// section card so each field reads as a distinct, recessed surface in both - /// light and dark (including AMOLED) themes. + /// Fill for input fields, one step apart from the card so each field reads as + /// a distinct surface in light/dark/AMOLED. Color _fieldFill(ColorScheme cs) { final isDark = Theme.of(context).brightness == Brightness.dark; return isDark @@ -1745,8 +1744,6 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> { filled: true, fillColor: _fieldFill(cs), isDense: true, - // Borderless by default; definition comes from the fill contrast. - // A soft primary ring appears only on focus for a clean look. border: OutlineInputBorder( borderRadius: radius, borderSide: BorderSide.none, @@ -1770,8 +1767,6 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> { ); } - /// Shared shape for the edit sections, mirroring the bounded cards used on the - /// track metadata screen (rounded with a subtle outline). RoundedRectangleBorder _sectionCardShape(ColorScheme cs) { return RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), @@ -1779,10 +1774,8 @@ class _EditMetadataSheetState extends State<_EditMetadataSheet> { ); } - /// A titled section card matching the track metadata screen layout. When - /// [onHeaderTap] is provided the header becomes a full-width tappable row so - /// the ink ripple follows the card's rounded shape (clipped to the card), - /// and a chevron is rendered automatically based on [expanded]. + /// Titled section card. When [onHeaderTap] is set the header is a full-width + /// tappable row (ripple clipped to the card) with an auto chevron. Widget _sectionCard({ required IconData icon, required String title, diff --git a/lib/screens/track_metadata_screen.dart b/lib/screens/track_metadata_screen.dart index c270137a..1df9403a 100644 --- a/lib/screens/track_metadata_screen.dart +++ b/lib/screens/track_metadata_screen.dart @@ -1468,8 +1468,6 @@ class _TrackMetadataScreenState extends ConsumerState { ); } - /// Shared shape for the main section cards: rounded with a subtle outline so - /// each section (Metadata, File Info, Lyrics, Audio Analysis) is bounded. RoundedRectangleBorder _sectionCardShape(ColorScheme colorScheme) { return RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), diff --git a/lib/services/platform_bridge.dart b/lib/services/platform_bridge.dart index 3f78beef..1add3860 100644 --- a/lib/services/platform_bridge.dart +++ b/lib/services/platform_bridge.dart @@ -865,10 +865,7 @@ class PlatformBridge { return result as bool; } - /// iOS only: mark that a download queue is active so the app keeps in-flight - /// downloads running for a short window whenever it is backgrounded. iOS - /// grants a limited budget (roughly 30s on modern versions) per background - /// entry; there is no foreground-service equivalent, so this is best-effort. + /// iOS only: keep in-flight downloads running briefly after backgrounding. static Future beginBackgroundDownloadTask() async { if (!Platform.isIOS) return; try { @@ -876,8 +873,7 @@ class PlatformBridge { } catch (_) {} } - /// iOS only: mark that the download queue is no longer active (queue finished - /// or paused), stopping background-time extension. + /// iOS only: stop the background-time extension (queue finished or paused). static Future endBackgroundDownloadTask() async { if (!Platform.isIOS) return; try { diff --git a/lib/widgets/animation_utils.dart b/lib/widgets/animation_utils.dart index ca8cd635..f61884f0 100644 --- a/lib/widgets/animation_utils.dart +++ b/lib/widgets/animation_utils.dart @@ -474,12 +474,9 @@ class GridSkeleton extends StatelessWidget { } } -/// Artist screen skeleton – shown *below* the SliverAppBar header while the -/// discography loads. Renders a cover placeholder (only when the header image -/// isn't available yet), the "Popular" section (rank + cover 48x48 + title + -/// badge + trailing), and the horizontal album sections. The artist name and -/// listeners are intentionally omitted here since the header already shows them -/// overlaid on the cover. +/// Artist screen skeleton shown below the SliverAppBar header while the +/// discography loads: optional cover placeholder, "Popular" section, and the +/// horizontal album sections. class ArtistScreenSkeleton extends StatelessWidget { final int popularCount; final int albumCount; diff --git a/lib/widgets/batch_convert_sheet.dart b/lib/widgets/batch_convert_sheet.dart index 31edb500..bba723c4 100644 --- a/lib/widgets/batch_convert_sheet.dart +++ b/lib/widgets/batch_convert_sheet.dart @@ -4,22 +4,12 @@ import 'package:spotiflac_android/utils/audio_conversion_utils.dart'; import 'package:spotiflac_android/widgets/settings_group.dart'; /// Modern, card-based batch convert sheet shared by the queue and album -/// screens. It mirrors the single-track convert sheet styling so format and -/// bitrate selection look consistent across the app. +/// screens, matching the single-track convert sheet styling. class BatchConvertSheet extends StatefulWidget { - /// Available target formats. final List formats; - - /// Sheet title. final String title; - - /// Optional subtitle shown under the title (e.g. number of tracks). final String? subtitle; - - /// Label for the primary action button. final String confirmLabel; - - /// Called with the selected format and bitrate when the user confirms. final void Function(String format, String bitrate) onConvert; const BatchConvertSheet({