import 'package:flutter/material.dart'; import 'package:spotiflac_android/l10n/app_localizations.dart'; /// A control or submenu that can be discovered from the root Settings search. /// /// The catalog contains only presentation metadata. The owning settings page /// remains responsible for reading and changing the actual setting value. class SettingsSearchEntry { const SettingsSearchEntry({ required this.icon, required this.title, this.subtitle, this.keywords = const [], String? targetLabel, }) : targetLabel = targetLabel ?? title; final IconData icon; final String title; final String? subtitle; final List keywords; /// Label of the actual destination widget. Usually the result title, but a /// hidden or toolbar-only action may point at its nearest visible section. final String targetLabel; bool matches(SettingsSearchQuery query) => query.matches([title, ?subtitle, ...keywords]); } /// Normalizes the query once per keystroke, rather than once for every entry. class SettingsSearchQuery { SettingsSearchQuery(String value) : terms = value .trim() .toLowerCase() .split(RegExp(r'\s+')) .where((term) => term.isNotEmpty) .toList(growable: false); final List terms; bool get isEmpty => terms.isEmpty; bool matches(Iterable values) { if (isEmpty) return true; final haystack = values.join(' ').toLowerCase(); return terms.every(haystack.contains); } } /// Localized index of controls found inside every first-level settings page. class SettingsSearchCatalog { SettingsSearchCatalog(AppLocalizations l10n) : extensions = [ SettingsSearchEntry( icon: Icons.low_priority, title: l10n.extensionsDownloadPriority, subtitle: l10n.extensionsDownloadPrioritySubtitle, keywords: const ['provider order', 'service order'], ), SettingsSearchEntry( icon: Icons.alt_route, title: l10n.extensionsFallbackTitle, subtitle: l10n.extensionsFallbackSubtitle, keywords: const ['provider fallback'], ), SettingsSearchEntry( icon: Icons.manage_search, title: l10n.extensionsMetadataPriority, subtitle: l10n.extensionsMetadataPrioritySubtitle, keywords: const ['metadata provider order'], ), SettingsSearchEntry( icon: Icons.search, title: l10n.extensionsSearchProvider, subtitle: l10n.extensionsSearchProviderDescription, keywords: const ['home search source'], ), SettingsSearchEntry( icon: Icons.explore_outlined, title: l10n.extensionsHomeFeedProvider, subtitle: l10n.extensionsHomeFeedDescription, keywords: const ['home provider', 'feed source'], ), SettingsSearchEntry( icon: Icons.add, title: l10n.extensionsInstallButton, keywords: const ['add plugin', 'import extension'], ), ], appearance = [ SettingsSearchEntry( icon: Icons.wallpaper, title: l10n.appearanceDynamicColor, subtitle: l10n.appearanceDynamicColorSubtitle, keywords: const ['material you', 'system color'], ), SettingsSearchEntry( icon: Icons.color_lens_outlined, title: l10n.sectionColor, keywords: const ['palette', 'seed color', 'accent'], ), SettingsSearchEntry( icon: Icons.contrast, title: l10n.sectionTheme, subtitle: '${l10n.appearanceThemeSystem}, ${l10n.appearanceThemeLight}, ' '${l10n.appearanceThemeDark}', keywords: const ['light mode', 'dark mode'], ), SettingsSearchEntry( icon: Icons.brightness_2, title: l10n.appearanceAmoledDark, subtitle: l10n.appearanceAmoledDarkSubtitle, keywords: const ['black theme', 'oled'], ), SettingsSearchEntry( icon: Icons.animation, title: l10n.appearanceHeroAnimations, subtitle: l10n.appearanceHeroAnimationsSubtitle, keywords: const ['transition', 'motion'], ), SettingsSearchEntry( icon: Icons.blur_on, title: l10n.appearanceForceBlur, subtitle: l10n.appearanceForceBlurSubtitle, keywords: const ['backdrop blur', 'performance'], ), SettingsSearchEntry( icon: Icons.language, title: l10n.appearanceLanguage, keywords: const ['locale', 'translation'], ), SettingsSearchEntry( icon: Icons.grid_view_outlined, title: l10n.appearanceHistoryView, subtitle: '${l10n.appearanceHistoryViewList}, ' '${l10n.appearanceHistoryViewGrid}', keywords: const ['layout', 'list', 'grid'], ), ], library = [ SettingsSearchEntry( icon: Icons.grid_view_rounded, title: l10n.libraryDefaultView, keywords: const ['library tab', 'default page'], ), SettingsSearchEntry( icon: Icons.graphic_eq_rounded, title: l10n.trackAudioQuality, keywords: const [ 'quality label', 'bitrate', 'bit depth', 'file format', 'codec', 'flac', 'mp3', 'kbps', ], ), SettingsSearchEntry( icon: Icons.library_music_outlined, title: l10n.libraryEnableLocalLibrary, subtitle: l10n.libraryEnableLocalLibrarySubtitle, keywords: const ['local music'], ), SettingsSearchEntry( icon: Icons.folder_outlined, title: l10n.libraryFolder, keywords: const ['local path', 'scan folder'], ), SettingsSearchEntry( icon: Icons.content_copy_outlined, title: l10n.libraryShowDuplicateIndicator, subtitle: l10n.libraryShowDuplicateIndicatorSubtitle, keywords: const ['duplicate badge'], ), SettingsSearchEntry( icon: Icons.difference_outlined, title: l10n.libraryReviewDuplicates, subtitle: l10n.libraryReviewDuplicatesSubtitle, keywords: const ['duplicate songs'], ), SettingsSearchEntry( icon: Icons.autorenew_rounded, title: l10n.libraryAutoScan, keywords: const ['automatic scan', 'daily', 'weekly'], ), SettingsSearchEntry( icon: Icons.refresh, title: l10n.libraryScan, subtitle: l10n.libraryScanSubtitle, keywords: const ['rescan', 'refresh music'], ), SettingsSearchEntry( icon: Icons.sync, title: l10n.libraryForceFullScan, subtitle: l10n.libraryForceFullScanSubtitle, keywords: const ['rescan all'], ), SettingsSearchEntry( icon: Icons.cleaning_services_outlined, title: l10n.libraryCleanupMissingFiles, subtitle: l10n.libraryCleanupMissingFilesSubtitle, keywords: const ['remove missing'], ), SettingsSearchEntry( icon: Icons.delete_outline, title: l10n.libraryClear, subtitle: l10n.libraryClearSubtitle, keywords: const ['reset local library'], ), SettingsSearchEntry( icon: Icons.open_in_new, title: l10n.libraryExternalPlayer, subtitle: l10n.libraryExternalPlayerSubtitle, keywords: const ['playback app'], ), SettingsSearchEntry( icon: Icons.play_circle_outline, title: l10n.libraryBuiltInPreviewPlayer, subtitle: l10n.libraryBuiltInPreviewPlayerSubtitle, keywords: const ['internal player'], ), SettingsSearchEntry( icon: Icons.graphic_eq, title: l10n.libraryPlaybackNormalization, subtitle: l10n.libraryPlaybackNormalizationSubtitle, keywords: const ['replaygain', 'volume'], ), ], metadata = [ SettingsSearchEntry( icon: Icons.sell_outlined, title: l10n.optionsEmbedMetadata, keywords: const ['tags', 'write metadata'], ), SettingsSearchEntry( icon: Icons.people_alt_outlined, title: l10n.optionsArtistTagMode, keywords: const ['artist separator', 'multiple artists'], ), SettingsSearchEntry( icon: Icons.photo_size_select_large_outlined, title: l10n.optionsEmbeddedCoverSize, subtitle: l10n.optionsEmbeddedCoverSizeDescription, keywords: const ['cover size', 'artwork resolution', 'resize image'], ), SettingsSearchEntry( icon: Icons.graphic_eq, title: l10n.optionsReplayGain, keywords: const ['volume normalization', 'loudness'], ), SettingsSearchEntry( icon: Icons.source_outlined, title: l10n.metadataProvidersTitle, subtitle: l10n.metadataProvidersSubtitle, keywords: const ['metadata priority', 'tag provider'], ), SettingsSearchEntry( icon: Icons.filter_list_outlined, title: l10n.downloadDeduplication, keywords: const ['duplicate download', 'same song'], ), SettingsSearchEntry( icon: Icons.library_music_outlined, title: l10n.downloadQualityVariants, subtitle: l10n.downloadQualityVariantsDescription, keywords: const ['different quality', 'multiple versions'], ), ], lyrics = [ SettingsSearchEntry( icon: Icons.subtitles_outlined, title: l10n.optionsEmbedLyrics, keywords: const ['write lyrics', 'lrc'], ), SettingsSearchEntry( icon: Icons.lyrics_outlined, title: l10n.lyricsMode, keywords: const ['synced', 'plain', 'lyrics type'], ), SettingsSearchEntry( icon: Icons.source_outlined, title: l10n.lyricsProvidersTitle, keywords: const ['lyrics priority', 'lyrics source'], ), SettingsSearchEntry( icon: Icons.translate_outlined, title: l10n.downloadNeteaseIncludeTranslation, keywords: const ['translated lyrics'], ), SettingsSearchEntry( icon: Icons.text_fields_outlined, title: l10n.downloadNeteaseIncludeRomanization, keywords: const ['romanized lyrics', 'latin'], ), SettingsSearchEntry( icon: Icons.record_voice_over_outlined, title: l10n.downloadAppleQqMultiPerson, keywords: const ['duet', 'multi singer'], ), SettingsSearchEntry( icon: Icons.graphic_eq_outlined, title: l10n.downloadAppleElrcWordSync, keywords: const ['word synced', 'elrc'], ), SettingsSearchEntry( icon: Icons.language_outlined, title: l10n.downloadMusixmatchLanguage, keywords: const ['lyrics locale'], ), ], download = [ SettingsSearchEntry( icon: Icons.extension_outlined, title: l10n.sectionService, keywords: const ['download provider', 'default service'], ), SettingsSearchEntry( icon: Icons.tune, title: l10n.downloadAskBeforeDownload, subtitle: l10n.downloadAskQualitySubtitle, keywords: const ['quality picker', 'ask quality'], ), SettingsSearchEntry( icon: Icons.audiotrack, title: l10n.downloadLossyFormat, keywords: const ['mp3', 'aac', 'opus'], ), SettingsSearchEntry( icon: Icons.auto_fix_high_outlined, title: l10n.downloadAutoConvert, subtitle: l10n.downloadAutoConvertSubtitle, keywords: const [ 'automatic conversion', 'mp3', 'm4a', 'aac', 'opus', 'bitrate', ], ), SettingsSearchEntry( icon: Icons.wifi, title: l10n.settingsDownloadNetwork, subtitle: l10n.settingsDownloadNetworkSubtitle, keywords: const ['wifi only', 'mobile data'], ), SettingsSearchEntry( icon: Icons.dynamic_feed_outlined, title: l10n.settingsConcurrentDownloads, subtitle: l10n.settingsConcurrentDownloadsSubtitle, keywords: const ['parallel downloads', 'simultaneous'], ), SettingsSearchEntry( icon: Icons.downloading_outlined, title: l10n.downloadNativeWorker, subtitle: l10n.downloadNativeWorkerSubtitle, keywords: const ['background worker', 'android worker'], ), SettingsSearchEntry( icon: Icons.security_outlined, title: l10n.downloadNetworkCompatibilityMode, keywords: const ['network fallback', 'connection compatibility'], ), SettingsSearchEntry( icon: Icons.lan_outlined, title: l10n.downloadAllowLocalNetwork, keywords: const ['lan', 'private network'], ), SettingsSearchEntry( icon: Icons.manage_search, title: l10n.optionsPrimaryProvider, subtitle: l10n.optionsPrimaryProviderSubtitle, keywords: const ['search source', 'metadata source'], ), SettingsSearchEntry( icon: Icons.tab_outlined, title: l10n.optionsDefaultSearchTab, subtitle: l10n.optionsDefaultSearchTabSubtitle, keywords: const ['track album artist playlist'], ), SettingsSearchEntry( icon: Icons.sync, title: l10n.optionsAutoFallback, subtitle: l10n.optionsAutoFallbackSubtitle, keywords: const ['automatic provider fallback'], ), SettingsSearchEntry( icon: Icons.extension_outlined, title: l10n.downloadFallbackExtensions, subtitle: l10n.downloadFallbackExtensionsSubtitle, keywords: const ['provider order'], ), SettingsSearchEntry( icon: Icons.public, title: l10n.downloadSongLinkRegion, keywords: const ['country', 'region'], ), SettingsSearchEntry( icon: Icons.file_download_outlined, title: l10n.settingsAutoExportFailed, subtitle: l10n.settingsAutoExportFailedSubtitle, keywords: const ['failed downloads', 'export errors'], ), ], files = [ SettingsSearchEntry( icon: Icons.folder_outlined, title: l10n.downloadDirectory, keywords: const ['download folder', 'saf', 'storage path'], ), SettingsSearchEntry( icon: Icons.text_fields, title: l10n.downloadFilenameFormat, keywords: const ['file naming', 'template'], ), SettingsSearchEntry( icon: Icons.music_note_outlined, title: l10n.downloadSingleFilenameFormat, keywords: const ['single naming', 'file template'], ), SettingsSearchEntry( icon: Icons.library_music_outlined, title: l10n.downloadSeparateSinglesFolder, keywords: const ['singles directory'], ), SettingsSearchEntry( icon: Icons.folder_outlined, title: l10n.downloadAlbumFolderStructure, keywords: const ['album directory', 'folder template'], ), SettingsSearchEntry( icon: Icons.create_new_folder_outlined, title: l10n.downloadFolderOrganization, keywords: const ['organize folders', 'directory layout'], ), SettingsSearchEntry( icon: Icons.playlist_play_outlined, title: l10n.downloadCreatePlaylistSourceFolder, keywords: const ['playlist directory'], ), SettingsSearchEntry( icon: Icons.person_search_outlined, title: l10n.downloadUseAlbumArtistForFolders, keywords: const ['album artist directory'], ), SettingsSearchEntry( icon: Icons.filter_alt_outlined, title: l10n.downloadArtistNameFilters, keywords: const ['artist folder filter'], ), SettingsSearchEntry( icon: Icons.person_outline, title: l10n.downloadUsePrimaryArtistOnly, keywords: const ['main artist folder'], ), SettingsSearchEntry( icon: Icons.group_remove_outlined, title: l10n.downloadFilterContributing, keywords: const ['featured artist folder'], ), SettingsSearchEntry( icon: Icons.folder_special_outlined, title: l10n.allFilesAccess, subtitle: l10n.allFilesAccessDescription, keywords: const ['storage permission', 'manage files'], ), ], app = [ SettingsSearchEntry( icon: Icons.extension, title: l10n.optionsExtensionStore, subtitle: l10n.optionsExtensionStoreSubtitle, keywords: const ['repository', 'plugin store'], ), SettingsSearchEntry( icon: Icons.open_in_browser, title: l10n.extensionVerificationBrowserTitle, keywords: const ['captcha', 'turnstile', 'external browser'], ), SettingsSearchEntry( icon: Icons.system_update, title: l10n.optionsCheckUpdates, subtitle: l10n.optionsCheckUpdatesSubtitle, keywords: const ['app update'], ), SettingsSearchEntry( icon: Icons.new_releases, title: l10n.optionsUpdateChannel, keywords: const ['stable', 'preview', 'beta'], ), SettingsSearchEntry( icon: Icons.cleaning_services_outlined, title: l10n.cleanupOrphanedDownloads, subtitle: l10n.cleanupOrphanedDownloadsSubtitle, keywords: const ['stale queue', 'missing download'], ), SettingsSearchEntry( icon: Icons.delete_forever, title: l10n.optionsClearHistory, subtitle: l10n.optionsClearHistorySubtitle, keywords: const ['delete history'], ), SettingsSearchEntry( icon: Icons.history_toggle_off_outlined, title: l10n.settingsSaveDownloadHistory, subtitle: l10n.settingsSaveDownloadHistorySubtitle, keywords: const ['remember downloads'], ), SettingsSearchEntry( icon: Icons.bug_report, title: l10n.optionsDetailedLogging, keywords: const ['debug logs', 'diagnostics'], ), ], cache = [ SettingsSearchEntry( icon: Icons.folder_outlined, title: l10n.cacheAppDirectory, subtitle: l10n.cacheAppDirectoryDesc, keywords: const ['application cache'], ), SettingsSearchEntry( icon: Icons.timer_outlined, title: l10n.cacheTempDirectory, subtitle: l10n.cacheTempDirectoryDesc, keywords: const ['temporary files'], ), SettingsSearchEntry( icon: Icons.image_outlined, title: l10n.cacheCoverImage, subtitle: l10n.cacheCoverImageDesc, keywords: const ['artwork cache'], ), SettingsSearchEntry( icon: Icons.library_music_outlined, title: l10n.cacheLibraryCover, subtitle: l10n.cacheLibraryCoverDesc, keywords: const ['local artwork cache'], ), SettingsSearchEntry( icon: Icons.graphic_eq_outlined, title: l10n.cacheAudioAnalysis, subtitle: l10n.cacheAudioAnalysisDesc, keywords: const ['spectrogram cache'], ), SettingsSearchEntry( icon: Icons.explore_outlined, title: l10n.cacheExploreFeed, subtitle: l10n.cacheExploreFeedDesc, keywords: const ['home feed cache'], ), SettingsSearchEntry( icon: Icons.memory_outlined, title: l10n.cacheTrackLookup, subtitle: l10n.cacheTrackLookupDesc, keywords: const ['search cache'], ), SettingsSearchEntry( icon: Icons.cleaning_services_outlined, title: l10n.cacheCleanupUnused, subtitle: l10n.cacheCleanupUnusedDesc, keywords: const ['clear cache', 'free space'], ), SettingsSearchEntry( icon: Icons.delete_sweep_outlined, title: l10n.cacheClearAll, targetLabel: l10n.cacheSectionMaintenance, keywords: const ['delete all cache'], ), ], backup = [ SettingsSearchEntry( icon: Icons.vpn_key_outlined, title: l10n.backupIncludeSecrets, subtitle: l10n.backupIncludeSecretsDescription, keywords: const ['tokens', 'credentials'], ), SettingsSearchEntry( icon: Icons.ios_share, title: l10n.backupExportButton, subtitle: l10n.backupExportSectionDescription, keywords: const ['create backup', 'save settings'], ), SettingsSearchEntry( icon: Icons.settings_backup_restore, title: l10n.backupImportButton, subtitle: l10n.backupImportSectionDescription, keywords: const ['restore backup', 'load settings'], ), ], logs = [ SettingsSearchEntry( icon: Icons.filter_list, title: l10n.logFilterLevel, subtitle: l10n.logFilterBySeverity, targetLabel: l10n.logFilterSection, keywords: const ['severity', 'error warning debug'], ), SettingsSearchEntry( icon: Icons.search, title: l10n.logSearchHint, targetLabel: l10n.logFilterSection, keywords: const ['find logs'], ), SettingsSearchEntry( icon: Icons.copy, title: l10n.logCopyLogs, targetLabel: l10n.logFilterSection, keywords: const ['clipboard'], ), SettingsSearchEntry( icon: Icons.share, title: l10n.logShareLogs, targetLabel: l10n.logFilterSection, keywords: const ['export logs'], ), SettingsSearchEntry( icon: Icons.delete_outline, title: l10n.logClearLogs, targetLabel: l10n.logFilterSection, keywords: const ['delete logs'], ), ], about = [ SettingsSearchEntry( icon: Icons.info_outline, title: l10n.aboutVersion, keywords: const ['build number', 'app version'], ), SettingsSearchEntry( icon: Icons.people_outline, title: l10n.aboutContributors, keywords: const ['developers', 'credits'], ), SettingsSearchEntry( icon: Icons.translate, title: l10n.aboutTranslators, keywords: const ['translation credits'], ), SettingsSearchEntry( icon: Icons.code, title: l10n.aboutMobileSource, keywords: const ['github', 'source code'], ), SettingsSearchEntry( icon: Icons.bug_report_outlined, title: l10n.aboutReportIssue, subtitle: l10n.aboutReportIssueSubtitle, keywords: const ['bug report'], ), SettingsSearchEntry( icon: Icons.lightbulb_outline, title: l10n.aboutFeatureRequest, subtitle: l10n.aboutFeatureRequestSubtitle, keywords: const ['suggestion', 'idea'], ), SettingsSearchEntry( icon: Icons.telegram, title: l10n.aboutTelegramChannel, subtitle: l10n.aboutTelegramChannelSubtitle, keywords: const ['social'], ), SettingsSearchEntry( icon: Icons.forum_outlined, title: l10n.aboutTelegramChat, subtitle: l10n.aboutTelegramChatSubtitle, keywords: const ['community', 'support chat'], ), ]; final List extensions; final List appearance; final List library; final List metadata; final List lyrics; final List download; final List files; final List app; final List cache; final List backup; final List logs; final List about; }