feat: add recent access history, artist screen redesign, and extension improvements

Recent Access History:
- Quick access to recently visited artists, albums, playlists, and tracks
- Tap search bar to show recent access list
- Stays visible after keyboard dismiss, exit with back button
- Persists across app restarts (SharedPreferences)
- X button to remove items, Clear All button for all

Artist Screen Redesign:
- Full-width header image with gradient overlay
- Monthly listeners display with compact notation
- Popular section with top 5 tracks and download status
- Extension artists skip Spotify/Deezer fetch (no rate limit errors)

Go Backend:
- GetArtistWithExtensionJSON now returns top_tracks, header_image, listeners

Bug Fixes:
- Search bar unfocus when tapping outside
- Keyboard not appearing on Settings navigation return
- Recent access artist navigation uses correct screen for extensions
- Extension artist screen correctly parses and forwards top tracks

Localization:
- Added recentPlaylistInfo, errorGeneric strings
- Multi-language support via Crowdin

Extensions:
- YT Music: v1.5.0 (top_tracks in getArtist)
- Spotify Web: v1.6.0
This commit is contained in:
zarzet
2026-01-17 04:29:39 +07:00
parent 9eac6e6e56
commit fc8cfb05d0
29 changed files with 2014 additions and 240 deletions
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotiflac_android/l10n/l10n.dart';
import 'package:spotiflac_android/l10n/supported_locales.dart';
import 'package:spotiflac_android/providers/settings_provider.dart';
import 'package:spotiflac_android/providers/theme_provider.dart';
import 'package:spotiflac_android/widgets/settings_group.dart';
@@ -709,7 +710,8 @@ class _LanguageSelector extends StatelessWidget {
required this.onChanged,
});
static const _languages = [
// All available languages (code, displayName, icon)
static const _allLanguages = [
('system', 'System Default', Icons.phone_android),
('en', 'English', Icons.language),
('id', 'Bahasa Indonesia', Icons.language),
@@ -726,8 +728,20 @@ 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) {
// Always include 'system' option
if (lang.$1 == 'system') return true;
// Only include languages in the filtered set
return filteredLocaleCodes.contains(lang.$1);
}).toList();
}
String _getLanguageName(String code) {
for (final lang in _languages) {
// Search in all languages (not just filtered) for display name fallback
for (final lang in _allLanguages) {
if (lang.$1 == code) return lang.$2;
}
return code;
+3
View File
@@ -127,6 +127,9 @@ class SettingsTab extends ConsumerWidget {
}
void _navigateTo(BuildContext context, Widget page) {
// Unfocus any focused widget before navigating to prevent keyboard from appearing on return
FocusManager.instance.primaryFocus?.unfocus();
Navigator.of(context).push(
// Use PageRouteBuilder for better predictive back gesture support
// MaterialPageRoute can cause freeze on some devices with gesture navigation