mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-09 14:18:11 +02:00
chore: remove redundant comments and boilerplate across codebase
Strip doc comments, section dividers, HTML comments, and Flutter template boilerplate that add no informational value. No logic or behavior changes.
This commit is contained in:
@@ -1,13 +1,10 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// App version and info constants
|
||||
/// Update version here only - all other files will reference this
|
||||
class AppInfo {
|
||||
static const String version = '4.5.0';
|
||||
static const String buildNumber = '127';
|
||||
static const String fullVersion = '$version+$buildNumber';
|
||||
|
||||
/// Shows "Internal" in debug builds, actual version in release.
|
||||
static String get displayVersion => kDebugMode ? 'Internal' : version;
|
||||
|
||||
static const String appName = 'SpotiFLAC Mobile';
|
||||
|
||||
@@ -3,9 +3,6 @@ import 'package:spotiflac_android/l10n/app_localizations.dart';
|
||||
|
||||
export 'package:spotiflac_android/l10n/app_localizations.dart';
|
||||
|
||||
/// Extension to easily access AppLocalizations from BuildContext
|
||||
extension AppLocalizationsX on BuildContext {
|
||||
/// Get the AppLocalizations instance
|
||||
/// Usage: context.l10n.navHome
|
||||
AppLocalizations get l10n => AppLocalizations.of(this);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Storage keys for theme settings persistence
|
||||
const String kThemeModeKey = 'theme_mode';
|
||||
const String kUseDynamicColorKey = 'use_dynamic_color';
|
||||
const String kSeedColorKey = 'seed_color';
|
||||
@@ -13,7 +12,7 @@ class ThemeSettings {
|
||||
final ThemeMode themeMode;
|
||||
final bool useDynamicColor;
|
||||
final int seedColorValue;
|
||||
final bool useAmoled; // Pure black background for OLED screens
|
||||
final bool useAmoled;
|
||||
|
||||
const ThemeSettings({
|
||||
this.themeMode = ThemeMode.system,
|
||||
|
||||
@@ -3598,11 +3598,6 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Album ReplayGain: accumulate per-track data, compute & write album gain
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Build a stable key for grouping tracks by album.
|
||||
String _albumRgKey(Track track) {
|
||||
if (track.albumId != null && track.albumId!.isNotEmpty) {
|
||||
return 'id:${track.albumId}';
|
||||
@@ -3773,7 +3768,6 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
_log.w('SAF write-back failed for album RG: $filePath');
|
||||
}
|
||||
} finally {
|
||||
// Clean up temp file regardless of SAF result.
|
||||
try {
|
||||
final tmp = File(tempPath!);
|
||||
if (await tmp.exists()) await tmp.delete();
|
||||
@@ -4017,7 +4011,6 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
final isM4a = format == 'm4a';
|
||||
final isMp3 = format == 'mp3';
|
||||
|
||||
// ── Cover download ──────────────────────────────────────────────
|
||||
String? coverPath;
|
||||
var coverUrl = normalizeRemoteHttpUrl(track.coverUrl);
|
||||
if (coverUrl != null && coverUrl.isNotEmpty) {
|
||||
@@ -4055,7 +4048,6 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
}
|
||||
|
||||
try {
|
||||
// ── Metadata map ────────────────────────────────────────────────
|
||||
final metadata = <String, String>{
|
||||
'TITLE': track.name,
|
||||
'ARTIST': track.artistName,
|
||||
@@ -4099,7 +4091,6 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
metadata['COMPOSER'] = track.composer!;
|
||||
}
|
||||
|
||||
// ── Lyrics ──────────────────────────────────────────────────────
|
||||
final lyricsMode = settings.lyricsMode;
|
||||
final extensionState = ref.read(extensionProvider);
|
||||
final skipLyrics = _shouldSkipLyrics(
|
||||
@@ -4160,7 +4151,6 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
|
||||
ReplayGainResult? scannedReplayGain;
|
||||
|
||||
// ── ReplayGain (MP3/Opus/M4A: scan before FFmpeg, add to metadata) ─
|
||||
if (settings.embedReplayGain && !isFlac) {
|
||||
try {
|
||||
final rgResult = await FFmpegService.scanReplayGain(filePath);
|
||||
@@ -4178,7 +4168,6 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
}
|
||||
}
|
||||
|
||||
// ── FFmpeg embed (format-specific) ──────────────────────────────
|
||||
final validCover = coverPath != null && await File(coverPath).exists()
|
||||
? coverPath
|
||||
: null;
|
||||
@@ -4232,7 +4221,6 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
}
|
||||
}
|
||||
|
||||
// ── FLAC post-processing ────────────────────────────────────────
|
||||
if (isFlac) {
|
||||
if (settings.artistTagMode == artistTagModeSplitVorbis) {
|
||||
try {
|
||||
@@ -7991,10 +7979,6 @@ final downloadQueueLookupProvider = Provider<DownloadQueueLookup>((ref) {
|
||||
return ref.watch(downloadQueueProvider.select((s) => s.lookup));
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Album ReplayGain helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class _AlbumRgTrackEntry {
|
||||
String filePath;
|
||||
final String trackId;
|
||||
|
||||
@@ -1753,7 +1753,6 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
);
|
||||
}
|
||||
|
||||
/// Build YT Music "Quick picks" style swipeable pages section
|
||||
Widget _buildYTMusicQuickPicksSection(
|
||||
ExploreSection section,
|
||||
ColorScheme colorScheme,
|
||||
|
||||
@@ -125,7 +125,6 @@ class _LibraryTracksFolderScreenState
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns true if [url] is a local file path rather than a network URL.
|
||||
bool _isCoverLocalPath(String url) {
|
||||
return !url.startsWith('http://') && !url.startsWith('https://');
|
||||
}
|
||||
@@ -1301,7 +1300,6 @@ class _CollectionTrackTile extends ConsumerWidget {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Builds a cover image widget that handles both network URLs and local file paths.
|
||||
Widget _buildTrackCover(BuildContext context, String coverUrl, double size) {
|
||||
final isLocal =
|
||||
!coverUrl.startsWith('http://') && !coverUrl.startsWith('https://');
|
||||
|
||||
@@ -2162,7 +2162,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
|
||||
.createPlaylist(playlistName);
|
||||
}
|
||||
|
||||
/// Build a playlist cover thumbnail (custom cover > first track cover > icon fallback).
|
||||
/// Pass a finite [size] (e.g. 56) for list view, or `null` for grid view
|
||||
/// where the widget should expand to fill its parent.
|
||||
Widget _buildPlaylistCover(
|
||||
@@ -2987,7 +2986,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the visible collection entries, hiding Wishlist/Loved when empty.
|
||||
List<_CollectionEntry> _getVisibleCollectionEntries(
|
||||
LibraryCollectionsState collectionState,
|
||||
) {
|
||||
@@ -4483,7 +4481,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Show batch convert bottom sheet for selected tracks
|
||||
Future<void> _showBatchConvertSheet(
|
||||
BuildContext context,
|
||||
List<UnifiedLibraryItem> allItems,
|
||||
@@ -5629,7 +5626,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
|
||||
);
|
||||
}
|
||||
|
||||
/// Build cover image widget for unified library item.
|
||||
/// When [size] is provided, renders at fixed dimensions (list mode).
|
||||
/// When [size] is null, fills the parent container (grid mode).
|
||||
Widget _buildUnifiedCoverImage(
|
||||
|
||||
@@ -60,7 +60,6 @@ class AppSettingsPage extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Updates ────────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionApp),
|
||||
),
|
||||
@@ -97,7 +96,6 @@ class AppSettingsPage extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Data ───────────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionData),
|
||||
),
|
||||
@@ -122,7 +120,6 @@ class AppSettingsPage extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Debug ──────────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionDebug),
|
||||
),
|
||||
|
||||
@@ -741,7 +741,6 @@ class _LanguageSelector extends StatelessWidget {
|
||||
('zh_TW', '繁體中文', Icons.language),
|
||||
];
|
||||
|
||||
/// Get only languages that meet the translation threshold.
|
||||
/// Uses filteredLocaleCodes from supported_locales.dart (generated file).
|
||||
List<(String, String, IconData)> get _languages {
|
||||
return _allLanguages.where((lang) {
|
||||
|
||||
@@ -166,7 +166,6 @@ class _RecentDonorsCard extends StatelessWidget {
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
const donorNames = <String>[];
|
||||
|
||||
// Match SettingsGroup color logic
|
||||
final cardColor = isDark
|
||||
? Color.alphaBlend(
|
||||
Colors.white.withValues(alpha: 0.08),
|
||||
|
||||
@@ -74,7 +74,6 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Service ────────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionService),
|
||||
),
|
||||
@@ -91,7 +90,6 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Audio Quality ──────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: context.l10n.sectionAudioQuality,
|
||||
@@ -117,7 +115,6 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Network & Performance ──────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: context.l10n.sectionPerformance,
|
||||
@@ -176,7 +173,6 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Fallback & Search ──────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: context.l10n.sectionSearchSource,
|
||||
@@ -211,7 +207,6 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Misc ───────────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionDownload),
|
||||
),
|
||||
@@ -611,8 +606,6 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Private widgets (reused from original) ─────────────────────────────────
|
||||
|
||||
class _BetaBadge extends StatelessWidget {
|
||||
const _BetaBadge();
|
||||
|
||||
@@ -896,7 +889,6 @@ class _ConcurrentChip extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
// Imported from options_settings_page — search source selectors
|
||||
class _MetadataSourceSelector extends ConsumerWidget {
|
||||
const _MetadataSourceSelector();
|
||||
|
||||
|
||||
@@ -347,7 +347,6 @@ class _ExtensionsPageState extends ConsumerState<ExtensionsPage> {
|
||||
return _getFriendlyErrorMessage(firstError);
|
||||
}
|
||||
|
||||
/// Parse error message to be more user-friendly
|
||||
String _getFriendlyErrorMessage(String? error) {
|
||||
if (error == null) return context.l10n.snackbarFailedToInstall;
|
||||
|
||||
|
||||
@@ -135,7 +135,6 @@ class _FilesSettingsPageState extends ConsumerState<FilesSettingsPage> {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Download Location ──────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: context.l10n.setupDownloadLocationTitle,
|
||||
@@ -159,7 +158,6 @@ class _FilesSettingsPageState extends ConsumerState<FilesSettingsPage> {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Filename Formats ───────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: context.l10n.sectionFileSettings,
|
||||
@@ -199,7 +197,6 @@ class _FilesSettingsPageState extends ConsumerState<FilesSettingsPage> {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Folder Structure ───────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: context.l10n.downloadFolderOrganization,
|
||||
@@ -318,7 +315,6 @@ class _FilesSettingsPageState extends ConsumerState<FilesSettingsPage> {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Storage Access (Android 13+) ───────────────────────────
|
||||
if (Platform.isAndroid && _androidSdkVersion >= 33) ...[
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
@@ -379,8 +375,6 @@ class _FilesSettingsPageState extends ConsumerState<FilesSettingsPage> {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Helpers ──────────────────────────────────────────────────────────────
|
||||
|
||||
String _getAlbumFolderStructureLabel(String structure) {
|
||||
switch (structure) {
|
||||
case 'album_only':
|
||||
|
||||
@@ -556,7 +556,6 @@ class _LogEntryTile extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// Summary card showing detected issues in logs
|
||||
class _LogSummaryCard extends StatelessWidget {
|
||||
final List<LogEntry> logs;
|
||||
|
||||
|
||||
@@ -358,7 +358,6 @@ class _DisabledProviderItem extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
// Empty space aligned with numbered badge
|
||||
const SizedBox(width: 28),
|
||||
const SizedBox(width: 16),
|
||||
Icon(info.icon, color: colorScheme.outline),
|
||||
|
||||
@@ -60,7 +60,6 @@ class LyricsSettingsPage extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Lyrics Embedding ───────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionLyrics),
|
||||
),
|
||||
@@ -112,7 +111,6 @@ class LyricsSettingsPage extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Provider Options ───────────────────────────────────────
|
||||
if (settings.embedMetadata && settings.embedLyrics) ...[
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
|
||||
@@ -61,7 +61,6 @@ class MetadataSettingsPage extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Embedding ──────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(title: context.l10n.sectionDownload),
|
||||
),
|
||||
@@ -116,7 +115,6 @@ class MetadataSettingsPage extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Providers ─────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: context.l10n.sectionMetadataProviders,
|
||||
@@ -141,7 +139,6 @@ class MetadataSettingsPage extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Deduplication ──────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: SettingsSectionHeader(
|
||||
title: context.l10n.sectionDuplicates,
|
||||
|
||||
@@ -61,7 +61,6 @@ class SettingsTab extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Group 1: Appearance & Content ──────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
@@ -96,7 +95,6 @@ class SettingsTab extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Group 2: Download ──────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
@@ -139,7 +137,6 @@ class SettingsTab extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// ── Group 3: App ───────────────────────────────────────────────
|
||||
SliverToBoxAdapter(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
|
||||
@@ -717,7 +717,6 @@ class _SetupScreenState extends ConsumerState<SetupScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
// --- Language data (native names, always readable regardless of current locale) ---
|
||||
static const _allLanguages = [
|
||||
('system', 'System Default', Icons.phone_android),
|
||||
('en', 'English', Icons.language),
|
||||
@@ -757,7 +756,6 @@ class _SetupScreenState extends ConsumerState<SetupScreen> {
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final shortestSide = MediaQuery.sizeOf(context).shortestSide;
|
||||
// Match _StepLayout sizing exactly
|
||||
final iconPadding = (shortestSide * 0.06).clamp(16.0, 24.0);
|
||||
final iconSize = (shortestSide * 0.12).clamp(32.0, 48.0);
|
||||
final titleGap = (shortestSide * 0.06).clamp(16.0, 32.0);
|
||||
@@ -766,7 +764,6 @@ class _SetupScreenState extends ConsumerState<SetupScreen> {
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
// Header: identical to _StepLayout (same padding, spacing, styles)
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 0),
|
||||
child: Column(
|
||||
@@ -805,7 +802,6 @@ class _SetupScreenState extends ConsumerState<SetupScreen> {
|
||||
],
|
||||
),
|
||||
),
|
||||
// Language list (scrollable action area)
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 80),
|
||||
|
||||
@@ -1060,7 +1060,6 @@ class FFmpegService {
|
||||
/// Uses the FFmpeg `ebur128` audio filter to measure integrated loudness (LUFS)
|
||||
/// and true peak. ReplayGain reference level is -18 LUFS (≈ 89 dB SPL).
|
||||
///
|
||||
/// Returns a [ReplayGainResult] on success, or null if the scan fails.
|
||||
static Future<ReplayGainResult?> scanReplayGain(String filePath) async {
|
||||
// -nostats suppresses the interactive progress line.
|
||||
// ebur128=peak=true prints integrated loudness + true peak.
|
||||
@@ -1079,7 +1078,6 @@ class FFmpegService {
|
||||
// because -f null always "fails" on some FFmpeg builds.
|
||||
final output = result.output;
|
||||
|
||||
// Parse integrated loudness: "I: -14.0 LUFS"
|
||||
final integratedMatch = RegExp(
|
||||
r'I:\s+(-?\d+\.?\d*)\s+LUFS',
|
||||
).allMatches(output);
|
||||
@@ -1205,7 +1203,6 @@ class FFmpegService {
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup temp file on failure
|
||||
try {
|
||||
final tempFile = File(tempOutput);
|
||||
if (await tempFile.exists()) await tempFile.delete();
|
||||
@@ -1332,7 +1329,6 @@ class FFmpegService {
|
||||
output.contains('incorrect codec parameters')) {
|
||||
_log.w('MP3 copy failed (codec mismatch), re-encoding with libmp3lame');
|
||||
|
||||
// Clean up failed temp file
|
||||
try {
|
||||
final tempFile = File(tempOutput);
|
||||
if (await tempFile.exists()) await tempFile.delete();
|
||||
@@ -1353,7 +1349,6 @@ class FFmpegService {
|
||||
return await _finalizeMp3Embed(mp3Path, reencodeOutput);
|
||||
}
|
||||
|
||||
// Clean up re-encode temp file
|
||||
try {
|
||||
final tempFile = File(reencodeOutput);
|
||||
if (await tempFile.exists()) await tempFile.delete();
|
||||
@@ -1363,7 +1358,6 @@ class FFmpegService {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Clean up temp file for other failures
|
||||
try {
|
||||
final tempFile = File(tempOutput);
|
||||
if (await tempFile.exists()) await tempFile.delete();
|
||||
@@ -1375,7 +1369,6 @@ class FFmpegService {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Build and execute FFmpeg arguments for MP3 metadata embedding.
|
||||
static Future<FFmpegResult> _runMp3Embed({
|
||||
required String mp3Path,
|
||||
required String tempOutput,
|
||||
@@ -1775,7 +1768,6 @@ class FFmpegService {
|
||||
/// Unified audio format conversion with full metadata + cover preservation.
|
||||
/// Supports: FLAC/M4A/MP3/Opus -> MP3/Opus/ALAC/FLAC.
|
||||
/// ALAC and FLAC targets are lossless (bitrate parameter is ignored).
|
||||
/// Returns the new file path on success, null on failure.
|
||||
static Future<String?> convertAudioFormat({
|
||||
required String inputPath,
|
||||
required String targetFormat,
|
||||
@@ -1881,7 +1873,6 @@ class FFmpegService {
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
/// Convert any audio format to ALAC (Apple Lossless) in an M4A container.
|
||||
/// Metadata and cover art are embedded in a single FFmpeg pass.
|
||||
static Future<String?> _convertToAlac({
|
||||
required String inputPath,
|
||||
@@ -1954,7 +1945,6 @@ class FFmpegService {
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
/// Convert any audio format to FLAC with metadata and cover art preservation.
|
||||
static Future<String?> _convertToFlac({
|
||||
required String inputPath,
|
||||
required Map<String, String> metadata,
|
||||
@@ -2359,7 +2349,6 @@ class FFmpegService {
|
||||
/// [outputDir] is where individual track files will be saved
|
||||
/// [tracks] is the list of track split info from the Go CUE parser
|
||||
/// [albumMetadata] contains album-level metadata (artist, album, genre, date)
|
||||
/// Returns list of output file paths on success, null on failure.
|
||||
static Future<List<String>?> splitCueToTracks({
|
||||
required String audioPath,
|
||||
required String outputDir,
|
||||
|
||||
@@ -45,8 +45,6 @@ class UpdateChecker {
|
||||
static const String _allReleasesApiUrl =
|
||||
'https://api.github.com/repos/${AppInfo.githubRepo}/releases';
|
||||
|
||||
/// Check for updates based on channel preference
|
||||
/// [channel] can be 'stable' or 'preview'
|
||||
static Future<UpdateInfo?> checkForUpdate({String channel = 'stable'}) async {
|
||||
if (!Platform.isAndroid) {
|
||||
return null;
|
||||
|
||||
@@ -10,7 +10,7 @@ class DownloadServicePicker extends ConsumerStatefulWidget {
|
||||
final String? artistName;
|
||||
final String? coverUrl;
|
||||
final void Function(String quality, String service) onSelect;
|
||||
final String? recommendedService; // Service to show as "(Recommended)"
|
||||
final String? recommendedService;
|
||||
|
||||
const DownloadServicePicker({
|
||||
super.key,
|
||||
|
||||
Reference in New Issue
Block a user