mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-29 15:28:48 +02:00
refactor(screens): unify album header, selection UI, and batch engine
The local/downloaded album screens had drifted copies of the album header, selection bottom bar, disc chip, batch convert/ReplayGain trio, and assorted small helpers. All now delegate to the shared widgets, with the online album screen's design as the reference, and both album screens run batch actions through the queue_tab engine via UnifiedLibraryItem (strict-superset implementation covering both DB writebacks and SAF paths). Also folds the remaining per-screen helper copies (cover URL, error card, byte/clock formatting, readPositiveInt) into their shared homes. Intentional deltas: selection-bar strings follow queue_tab's l10n keys, both providers reload after a conversion, and audio-analysis durations round instead of floor.
This commit is contained in:
@@ -14,6 +14,7 @@ import 'package:spotiflac_android/widgets/settings_group.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:spotiflac_android/l10n/l10n.dart';
|
||||
import 'package:spotiflac_android/services/platform_bridge.dart';
|
||||
import 'package:spotiflac_android/utils/string_utils.dart';
|
||||
|
||||
class AudioAnalysisData {
|
||||
static const cacheVersion = 4;
|
||||
@@ -1378,7 +1379,7 @@ class _AudioInfoCard extends StatelessWidget {
|
||||
_MetricChip(
|
||||
icon: Icons.timer_outlined,
|
||||
label: context.l10n.audioAnalysisDuration,
|
||||
value: _formatDuration(data.duration),
|
||||
value: formatClock(data.duration),
|
||||
cs: cs,
|
||||
),
|
||||
_MetricChip(
|
||||
@@ -1391,7 +1392,7 @@ class _AudioInfoCard extends StatelessWidget {
|
||||
_MetricChip(
|
||||
icon: Icons.storage,
|
||||
label: context.l10n.audioAnalysisFileSize,
|
||||
value: _formatFileSize(data.fileSize),
|
||||
value: formatBytes(data.fileSize),
|
||||
cs: cs,
|
||||
),
|
||||
],
|
||||
@@ -1488,12 +1489,6 @@ class _AudioInfoCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
String _formatDuration(double seconds) {
|
||||
final mins = seconds ~/ 60;
|
||||
final secs = (seconds % 60).floor();
|
||||
return '$mins:${secs.toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
String _formatChannels(BuildContext context, AudioAnalysisData data) {
|
||||
final layout = data.channelLayout.trim();
|
||||
if (layout.isNotEmpty && layout != 'unknown') {
|
||||
@@ -1504,14 +1499,6 @@ class _AudioInfoCard extends StatelessWidget {
|
||||
return data.channels > 0 ? '${data.channels}' : 'N/A';
|
||||
}
|
||||
|
||||
String _formatFileSize(int bytes) {
|
||||
if (bytes == 0) return '0 B';
|
||||
const units = ['B', 'KB', 'MB', 'GB'];
|
||||
final i = (math.log(bytes) / math.log(1024)).floor();
|
||||
final size = bytes / math.pow(1024, i);
|
||||
return '${size.toStringAsFixed(1)} ${units[i]}';
|
||||
}
|
||||
|
||||
String _formatFrequency(double hz) {
|
||||
if (hz >= 1000) return '${(hz / 1000).toStringAsFixed(1)} kHz';
|
||||
return '${hz.round()} Hz';
|
||||
@@ -1766,7 +1753,7 @@ class _SpectrogramPainter extends CustomPainter {
|
||||
canvas.drawLine(Offset(x, plot.top), Offset(x, plot.bottom), gridPaint);
|
||||
_drawText(
|
||||
canvas,
|
||||
_fmtTime(ts),
|
||||
formatClock(ts),
|
||||
Offset(x, plot.bottom + 3),
|
||||
align: _TextAlignV.topCenter,
|
||||
);
|
||||
@@ -1818,13 +1805,6 @@ class _SpectrogramPainter extends CustomPainter {
|
||||
return 1200.0;
|
||||
}
|
||||
|
||||
static String _fmtTime(double sec) {
|
||||
final s = sec.round();
|
||||
final m = s ~/ 60;
|
||||
final r = s % 60;
|
||||
return '$m:${r.toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant _SpectrogramPainter old) =>
|
||||
old.image != image ||
|
||||
|
||||
Reference in New Issue
Block a user