mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-30 13:19:44 +02:00
refactor: code cleanup and improvements
This commit is contained in:
32 files changed
+13
-453
No files matched your search
@@ -64,7 +64,6 @@ class CollapsingHeader extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// Info card if provided
|
||||
if (infoCard != null)
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
@@ -73,7 +72,6 @@ class CollapsingHeader extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
|
||||
// Content slivers
|
||||
...slivers,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -105,20 +105,17 @@ class _DownloadServicePickerState extends ConsumerState<DownloadServicePicker> {
|
||||
|
||||
/// Get quality options for the selected service
|
||||
List<QualityOption> _getQualityOptions() {
|
||||
// Check if it's a built-in service
|
||||
final builtIn = _builtInServices.where((s) => s.id == _selectedService).firstOrNull;
|
||||
if (builtIn != null) {
|
||||
return builtIn.qualityOptions;
|
||||
}
|
||||
|
||||
// Check if it's an extension
|
||||
final extensionState = ref.read(extensionProvider);
|
||||
final ext = extensionState.extensions.where((e) => e.id == _selectedService).firstOrNull;
|
||||
if (ext != null && ext.qualityOptions.isNotEmpty) {
|
||||
return ext.qualityOptions;
|
||||
}
|
||||
|
||||
// Default quality options if extension doesn't specify any
|
||||
return const [
|
||||
QualityOption(id: 'DEFAULT', label: 'Default Quality', description: 'Best available'),
|
||||
];
|
||||
@@ -129,7 +126,6 @@ class _DownloadServicePickerState extends ConsumerState<DownloadServicePicker> {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final extensionState = ref.watch(extensionProvider);
|
||||
|
||||
// Get enabled download provider extensions
|
||||
final downloadExtensions = extensionState.extensions
|
||||
.where((ext) => ext.enabled && ext.hasDownloadProvider)
|
||||
.toList();
|
||||
@@ -142,7 +138,6 @@ class _DownloadServicePickerState extends ConsumerState<DownloadServicePicker> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Track info header (if provided)
|
||||
if (widget.trackName != null) ...[
|
||||
_TrackInfoHeader(
|
||||
trackName: widget.trackName!,
|
||||
@@ -164,7 +159,6 @@ class _DownloadServicePickerState extends ConsumerState<DownloadServicePicker> {
|
||||
),
|
||||
],
|
||||
|
||||
// Service selector section
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 16, 24, 8),
|
||||
child: Text(
|
||||
@@ -173,21 +167,18 @@ class _DownloadServicePickerState extends ConsumerState<DownloadServicePicker> {
|
||||
),
|
||||
),
|
||||
|
||||
// Built-in services
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
// Built-in services
|
||||
for (final service in _builtInServices)
|
||||
_ServiceChip(
|
||||
label: service.label,
|
||||
isSelected: _selectedService == service.id,
|
||||
onTap: () => setState(() => _selectedService = service.id),
|
||||
),
|
||||
// Extension services
|
||||
for (final ext in downloadExtensions)
|
||||
_ServiceChip(
|
||||
label: ext.displayName,
|
||||
@@ -199,7 +190,6 @@ class _DownloadServicePickerState extends ConsumerState<DownloadServicePicker> {
|
||||
),
|
||||
),
|
||||
|
||||
// Quality selector section
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 16, 24, 8),
|
||||
child: Text(
|
||||
@@ -208,7 +198,6 @@ class _DownloadServicePickerState extends ConsumerState<DownloadServicePicker> {
|
||||
),
|
||||
),
|
||||
|
||||
// Disclaimer for built-in services
|
||||
if (_builtInServices.any((s) => s.id == _selectedService))
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 12),
|
||||
@@ -221,7 +210,6 @@ class _DownloadServicePickerState extends ConsumerState<DownloadServicePicker> {
|
||||
),
|
||||
),
|
||||
|
||||
// Quality options
|
||||
for (final quality in qualityOptions)
|
||||
_QualityOption(
|
||||
title: quality.label,
|
||||
|
||||
@@ -30,7 +30,6 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
Future<void> _downloadAndInstall() async {
|
||||
final apkUrl = widget.updateInfo.apkDownloadUrl;
|
||||
|
||||
// If no direct APK URL, open release page
|
||||
if (apkUrl == null) {
|
||||
final uri = Uri.parse(widget.updateInfo.downloadUrl);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
@@ -60,7 +59,6 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
_statusText = '$receivedMB / $totalMB MB';
|
||||
});
|
||||
}
|
||||
// Update notification
|
||||
notificationService.showUpdateDownloadProgress(
|
||||
version: widget.updateInfo.version,
|
||||
received: received,
|
||||
@@ -70,7 +68,6 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
);
|
||||
|
||||
if (filePath != null) {
|
||||
// Cancel progress notification first
|
||||
await notificationService.cancelUpdateNotification();
|
||||
|
||||
await notificationService.showUpdateDownloadComplete(
|
||||
@@ -81,10 +78,8 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
||||
// Open APK for installation
|
||||
await ApkDownloader.installApk(filePath);
|
||||
} else {
|
||||
// Cancel progress notification first
|
||||
await notificationService.cancelUpdateNotification();
|
||||
|
||||
await notificationService.showUpdateDownloadFailed();
|
||||
@@ -116,7 +111,6 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header with icon
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
@@ -142,7 +136,6 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// Version badge
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
@@ -165,7 +158,6 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// Download progress (when downloading)
|
||||
if (_isDownloading) ...[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
@@ -209,7 +201,6 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
),
|
||||
),
|
||||
] else ...[
|
||||
// Changelog section
|
||||
Text(context.l10n.updateWhatsNew, style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 8),
|
||||
Container(
|
||||
@@ -231,7 +222,6 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
],
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Action buttons
|
||||
if (_isDownloading)
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
@@ -303,19 +293,16 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
String _formatChangelog(String changelog) {
|
||||
var content = changelog;
|
||||
|
||||
// Find content after "What's New" header
|
||||
final whatsNewMatch = RegExp(r"###?\s*What'?s\s*New\s*\n", caseSensitive: false).firstMatch(content);
|
||||
if (whatsNewMatch != null) {
|
||||
content = content.substring(whatsNewMatch.end);
|
||||
}
|
||||
|
||||
// Cut off at "Downloads" section or horizontal rule
|
||||
final cutoffMatch = RegExp(r'\n---|\n###?\s*Downloads', caseSensitive: false).firstMatch(content);
|
||||
if (cutoffMatch != null) {
|
||||
content = content.substring(0, cutoffMatch.start);
|
||||
}
|
||||
|
||||
// Process line by line for better formatting
|
||||
final lines = content.split('\n');
|
||||
final formattedLines = <String>[];
|
||||
|
||||
@@ -323,7 +310,6 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
line = line.trim();
|
||||
if (line.isEmpty) continue;
|
||||
|
||||
// Check if it's a section header
|
||||
final sectionMatch = RegExp(r'^#{1,3}\s*(.+)$').firstMatch(line);
|
||||
if (sectionMatch != null) {
|
||||
final section = sectionMatch.group(1)?.trim();
|
||||
@@ -334,7 +320,6 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if it's a list item
|
||||
final listMatch = RegExp(r'^[-*]\s+(.+)$').firstMatch(line);
|
||||
if (listMatch != null) {
|
||||
var itemText = listMatch.group(1) ?? '';
|
||||
@@ -344,7 +329,6 @@ class _UpdateDialogState extends State<UpdateDialog> {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if it's a sub-item
|
||||
final subListMatch = RegExp(r'^\s+[-*]\s+(.+)$').firstMatch(line);
|
||||
if (subListMatch != null) {
|
||||
var itemText = subListMatch.group(1) ?? '';
|
||||
@@ -401,7 +385,6 @@ class _VersionChip extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// Show update dialog
|
||||
Future<void> showUpdateDialog(
|
||||
BuildContext context, {
|
||||
required UpdateInfo updateInfo,
|
||||
|
||||
Reference in new issue
Block a user