mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-08-02 09:08:35 +02:00
refactor: remove orphaned bridge, database, and queue helpers
This commit is contained in:
@@ -2386,14 +2386,6 @@ class MainActivity: FlutterFragmentActivity() {
|
||||
}
|
||||
result.success(tempPath)
|
||||
}
|
||||
"safReplaceFromPath" -> {
|
||||
val uriStr = call.argument<String>("uri") ?: ""
|
||||
val srcPath = call.argument<String>("src_path") ?: ""
|
||||
val ok = withContext(Dispatchers.IO) {
|
||||
writeUriFromPath(Uri.parse(uriStr), srcPath)
|
||||
}
|
||||
result.success(ok)
|
||||
}
|
||||
"safCreateFromPath" -> {
|
||||
val treeUriStr = call.argument<String>("tree_uri") ?: ""
|
||||
val relativeDir = call.argument<String>("relative_dir") ?: ""
|
||||
@@ -3064,12 +3056,6 @@ class MainActivity: FlutterFragmentActivity() {
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"getLogs" -> {
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.getLogs()
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"getLogsSince" -> {
|
||||
val index = call.argument<Int>("index") ?: 0
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
@@ -3108,12 +3094,6 @@ class MainActivity: FlutterFragmentActivity() {
|
||||
}
|
||||
result.success(null)
|
||||
}
|
||||
"getLogCount" -> {
|
||||
val count = withContext(Dispatchers.IO) {
|
||||
Gobackend.getLogCount()
|
||||
}
|
||||
result.success(count.toInt())
|
||||
}
|
||||
"setLoggingEnabled" -> {
|
||||
val enabled = call.argument<Boolean>("enabled") ?: false
|
||||
withContext(Dispatchers.IO) {
|
||||
|
||||
@@ -17,8 +17,8 @@ func TestLogBufferExportedHelpersAndRedaction(t *testing.T) {
|
||||
SetLoggingEnabled(false)
|
||||
LogInfo("test", "ignored access_token=secret")
|
||||
LogError("test", "Authorization: Bearer secret-token api_key=value")
|
||||
if GetLogCount() != 1 {
|
||||
t.Fatalf("disabled logging should keep errors only, got %d", GetLogCount())
|
||||
if GetLogBuffer().Count() != 1 {
|
||||
t.Fatalf("disabled logging should keep errors only, got %d", GetLogBuffer().Count())
|
||||
}
|
||||
|
||||
SetLoggingEnabled(true)
|
||||
@@ -28,8 +28,8 @@ func TestLogBufferExportedHelpersAndRedaction(t *testing.T) {
|
||||
GoLog("[GoTag] success token=abc")
|
||||
|
||||
var entries []LogEntry
|
||||
if err := json.Unmarshal([]byte(GetLogs()), &entries); err != nil {
|
||||
t.Fatalf("GetLogs JSON: %v", err)
|
||||
if err := json.Unmarshal([]byte(GetLogBuffer().GetAll()), &entries); err != nil {
|
||||
t.Fatalf("GetAll JSON: %v", err)
|
||||
}
|
||||
if len(entries) < 4 {
|
||||
t.Fatalf("expected log entries, got %#v", entries)
|
||||
@@ -52,8 +52,8 @@ func TestLogBufferExportedHelpersAndRedaction(t *testing.T) {
|
||||
}
|
||||
|
||||
ClearLogs()
|
||||
if GetLogCount() != 0 || GetLogs() != "[]" {
|
||||
t.Fatalf("logs were not cleared: count=%d logs=%s", GetLogCount(), GetLogs())
|
||||
if GetLogBuffer().Count() != 0 || GetLogBuffer().GetAll() != "[]" {
|
||||
t.Fatalf("logs were not cleared: count=%d logs=%s", GetLogBuffer().Count(), GetLogBuffer().GetAll())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -207,10 +207,6 @@ func GoLog(format string, args ...any) {
|
||||
GetLogBuffer().Add(level, tag, message)
|
||||
}
|
||||
|
||||
func GetLogs() string {
|
||||
return GetLogBuffer().GetAll()
|
||||
}
|
||||
|
||||
func GetLogsSince(index int) string {
|
||||
entries, nextIndex := GetLogBuffer().getSince(index)
|
||||
logsJson, _ := json.Marshal(entries)
|
||||
@@ -222,10 +218,6 @@ func ClearLogs() {
|
||||
GetLogBuffer().Clear()
|
||||
}
|
||||
|
||||
func GetLogCount() int {
|
||||
return GetLogBuffer().Count()
|
||||
}
|
||||
|
||||
func SetLoggingEnabled(enabled bool) {
|
||||
GetLogBuffer().SetLoggingEnabled(enabled)
|
||||
}
|
||||
|
||||
@@ -665,10 +665,6 @@ import Gobackend
|
||||
GobackendClearTrackIDCache()
|
||||
return nil
|
||||
|
||||
case "getLogs":
|
||||
let response = GobackendGetLogs()
|
||||
return response
|
||||
|
||||
case "getLogsSince":
|
||||
let args = call.arguments as! [String: Any]
|
||||
let index = args["index"] as? Int ?? 0
|
||||
@@ -690,10 +686,6 @@ import Gobackend
|
||||
case "getGoRuntimeMetrics":
|
||||
return GobackendGetRuntimeMetricsJSON()
|
||||
|
||||
case "getLogCount":
|
||||
let response = GobackendGetLogCount()
|
||||
return response
|
||||
|
||||
case "setLoggingEnabled":
|
||||
let args = call.arguments as! [String: Any]
|
||||
let enabled = args["enabled"] as? Bool ?? false
|
||||
|
||||
@@ -1033,9 +1033,6 @@
|
||||
"@libraryFilterMetadataMissingLabel": {
|
||||
"description": "Filter option - items missing record label"
|
||||
},
|
||||
"@badgeBeta": {
|
||||
"description": "Badge label for beta features"
|
||||
},
|
||||
"@audioAnalysisLufs": {
|
||||
"description": "Integrated loudness metric label"
|
||||
},
|
||||
@@ -2881,7 +2878,6 @@
|
||||
"@collectionPlaylistEmptySubtitle": {
|
||||
"description": "Playlist empty state subtitle"
|
||||
},
|
||||
"badgeBeta": "BETA",
|
||||
"@tutorialSearchHint": {
|
||||
"description": "Placeholder shown in the tutorial search demo"
|
||||
},
|
||||
|
||||
@@ -5226,10 +5226,6 @@
|
||||
"@downloadNativeWorkerSubtitle": {
|
||||
"description": "Setting subtitle for Android native download worker"
|
||||
},
|
||||
"badgeBeta": "BETA",
|
||||
"@badgeBeta": {
|
||||
"description": "Badge label for beta features"
|
||||
},
|
||||
"extensionServiceStatus": "Estado del servicio",
|
||||
"@extensionServiceStatus": {
|
||||
"description": "Extension detail section header for service status"
|
||||
|
||||
@@ -1033,9 +1033,6 @@
|
||||
"@libraryFilterMetadataMissingLabel": {
|
||||
"description": "Filter option - items missing record label"
|
||||
},
|
||||
"@badgeBeta": {
|
||||
"description": "Badge label for beta features"
|
||||
},
|
||||
"@audioAnalysisLufs": {
|
||||
"description": "Integrated loudness metric label"
|
||||
},
|
||||
@@ -2881,7 +2878,6 @@
|
||||
"@collectionPlaylistEmptySubtitle": {
|
||||
"description": "Playlist empty state subtitle"
|
||||
},
|
||||
"badgeBeta": "BÊTA",
|
||||
"@tutorialSearchHint": {
|
||||
"description": "Placeholder shown in the tutorial search demo"
|
||||
},
|
||||
|
||||
@@ -1033,9 +1033,6 @@
|
||||
"@libraryFilterMetadataMissingLabel": {
|
||||
"description": "Filter option - items missing record label"
|
||||
},
|
||||
"@badgeBeta": {
|
||||
"description": "Badge label for beta features"
|
||||
},
|
||||
"@audioAnalysisLufs": {
|
||||
"description": "Integrated loudness metric label"
|
||||
},
|
||||
@@ -2881,7 +2878,6 @@
|
||||
"@collectionPlaylistEmptySubtitle": {
|
||||
"description": "Playlist empty state subtitle"
|
||||
},
|
||||
"badgeBeta": "BETA",
|
||||
"@tutorialSearchHint": {
|
||||
"description": "Placeholder shown in the tutorial search demo"
|
||||
},
|
||||
|
||||
@@ -1033,9 +1033,6 @@
|
||||
"@libraryFilterMetadataMissingLabel": {
|
||||
"description": "Filter option - items missing record label"
|
||||
},
|
||||
"@badgeBeta": {
|
||||
"description": "Badge label for beta features"
|
||||
},
|
||||
"@audioAnalysisLufs": {
|
||||
"description": "Integrated loudness metric label"
|
||||
},
|
||||
@@ -2881,7 +2878,6 @@
|
||||
"@collectionPlaylistEmptySubtitle": {
|
||||
"description": "Playlist empty state subtitle"
|
||||
},
|
||||
"badgeBeta": "BETA",
|
||||
"@tutorialSearchHint": {
|
||||
"description": "Placeholder shown in the tutorial search demo"
|
||||
},
|
||||
|
||||
@@ -5365,10 +5365,6 @@
|
||||
"@downloadNativeWorkerSubtitle": {
|
||||
"description": "Setting subtitle for Android native download worker"
|
||||
},
|
||||
"badgeBeta": "베타",
|
||||
"@badgeBeta": {
|
||||
"description": "Badge label for beta features"
|
||||
},
|
||||
"extensionServiceStatus": "서비스 상태",
|
||||
"@extensionServiceStatus": {
|
||||
"description": "Extension detail section header for service status"
|
||||
|
||||
@@ -1033,9 +1033,6 @@
|
||||
"@libraryFilterMetadataMissingLabel": {
|
||||
"description": "Filter option - items missing record label"
|
||||
},
|
||||
"@badgeBeta": {
|
||||
"description": "Badge label for beta features"
|
||||
},
|
||||
"@audioAnalysisLufs": {
|
||||
"description": "Integrated loudness metric label"
|
||||
},
|
||||
@@ -2881,7 +2878,6 @@
|
||||
"@collectionPlaylistEmptySubtitle": {
|
||||
"description": "Playlist empty state subtitle"
|
||||
},
|
||||
"badgeBeta": "BETA",
|
||||
"@tutorialSearchHint": {
|
||||
"description": "Placeholder shown in the tutorial search demo"
|
||||
},
|
||||
|
||||
@@ -1033,9 +1033,6 @@
|
||||
"@libraryFilterMetadataMissingLabel": {
|
||||
"description": "Filter option - items missing record label"
|
||||
},
|
||||
"@badgeBeta": {
|
||||
"description": "Badge label for beta features"
|
||||
},
|
||||
"@audioAnalysisLufs": {
|
||||
"description": "Integrated loudness metric label"
|
||||
},
|
||||
@@ -2881,7 +2878,6 @@
|
||||
"@collectionPlaylistEmptySubtitle": {
|
||||
"description": "Playlist empty state subtitle"
|
||||
},
|
||||
"badgeBeta": "BETA",
|
||||
"@tutorialSearchHint": {
|
||||
"description": "Placeholder shown in the tutorial search demo"
|
||||
},
|
||||
|
||||
@@ -1033,9 +1033,6 @@
|
||||
"@libraryFilterMetadataMissingLabel": {
|
||||
"description": "Filter option - items missing record label"
|
||||
},
|
||||
"@badgeBeta": {
|
||||
"description": "Badge label for beta features"
|
||||
},
|
||||
"@audioAnalysisLufs": {
|
||||
"description": "Integrated loudness metric label"
|
||||
},
|
||||
@@ -2881,7 +2878,6 @@
|
||||
"@collectionPlaylistEmptySubtitle": {
|
||||
"description": "Playlist empty state subtitle"
|
||||
},
|
||||
"badgeBeta": "BETA",
|
||||
"@tutorialSearchHint": {
|
||||
"description": "Placeholder shown in the tutorial search demo"
|
||||
},
|
||||
|
||||
@@ -1033,9 +1033,6 @@
|
||||
"@libraryFilterMetadataMissingLabel": {
|
||||
"description": "Filter option - items missing record label"
|
||||
},
|
||||
"@badgeBeta": {
|
||||
"description": "Badge label for beta features"
|
||||
},
|
||||
"@audioAnalysisLufs": {
|
||||
"description": "Integrated loudness metric label"
|
||||
},
|
||||
@@ -2881,7 +2878,6 @@
|
||||
"@collectionPlaylistEmptySubtitle": {
|
||||
"description": "Playlist empty state subtitle"
|
||||
},
|
||||
"badgeBeta": "BETA",
|
||||
"@tutorialSearchHint": {
|
||||
"description": "Placeholder shown in the tutorial search demo"
|
||||
},
|
||||
|
||||
@@ -983,10 +983,6 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
_lastNotifQueueCount = -1;
|
||||
}
|
||||
|
||||
void setOutputDir(String dir) {
|
||||
state = state.copyWith(outputDir: dir);
|
||||
}
|
||||
|
||||
bool _isSafMode(AppSettings settings) {
|
||||
return Platform.isAndroid &&
|
||||
settings.storageMode == 'saf' &&
|
||||
@@ -1452,39 +1448,6 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
}
|
||||
}
|
||||
|
||||
void clearCompleted() {
|
||||
final removedItems = state.items.where(
|
||||
(item) =>
|
||||
item.status == DownloadStatus.completed ||
|
||||
item.status == DownloadStatus.failed ||
|
||||
item.status == DownloadStatus.skipped,
|
||||
);
|
||||
bool hadFailedOrSkipped = false;
|
||||
for (final item in removedItems) {
|
||||
if (item.status == DownloadStatus.failed ||
|
||||
item.status == DownloadStatus.skipped) {
|
||||
hadFailedOrSkipped = true;
|
||||
_purgeAlbumRgEntry(item.track);
|
||||
}
|
||||
}
|
||||
|
||||
final items = state.items
|
||||
.where(
|
||||
(item) =>
|
||||
item.status != DownloadStatus.completed &&
|
||||
item.status != DownloadStatus.failed &&
|
||||
item.status != DownloadStatus.skipped,
|
||||
)
|
||||
.toList();
|
||||
|
||||
state = state.copyWith(items: items);
|
||||
_saveQueueToStorage();
|
||||
|
||||
if (hadFailedOrSkipped) {
|
||||
_retriggerAlbumRgChecks();
|
||||
}
|
||||
}
|
||||
|
||||
void clearAll() {
|
||||
final wasProcessing = state.isProcessing;
|
||||
final activeIds = state.items
|
||||
@@ -1780,27 +1743,6 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
}
|
||||
}
|
||||
|
||||
void clearFailedDownloads() {
|
||||
final failedItems = state.items
|
||||
.where((item) => item.status == DownloadStatus.failed)
|
||||
.toList();
|
||||
for (final item in failedItems) {
|
||||
_purgeAlbumRgEntry(item.track);
|
||||
}
|
||||
|
||||
final items = state.items
|
||||
.where((item) => item.status != DownloadStatus.failed)
|
||||
.toList();
|
||||
state = state.copyWith(items: items);
|
||||
_saveQueueToStorage();
|
||||
_log.d('Cleared failed downloads from queue');
|
||||
|
||||
// Removing failed items may unblock album RG for affected albums.
|
||||
if (failedItems.isNotEmpty) {
|
||||
_retriggerAlbumRgChecks();
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> _runPostProcessingHooks(String filePath, Track track) async {
|
||||
try {
|
||||
final settings = ref.read(settingsProvider);
|
||||
|
||||
@@ -273,11 +273,6 @@ class AppRemoteConfigService {
|
||||
this.endpoint = AppInfo.remoteConfigApiUrl,
|
||||
}) : _client = client ?? http.Client();
|
||||
|
||||
Future<AppRemoteConfig?> fetchConfig({String? locale}) async {
|
||||
final snapshot = await fetchConfigSnapshot(locale: locale);
|
||||
return snapshot?.config;
|
||||
}
|
||||
|
||||
Future<RemoteConfigSnapshot?> readCachedConfig() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final cachedJson = prefs.getString(_cachedConfigJsonKey);
|
||||
|
||||
@@ -694,11 +694,6 @@ class HistoryDatabase {
|
||||
return _dbRowToJson(rows.first);
|
||||
}
|
||||
|
||||
Future<bool> existsTrack(HistoryLookupRequest request) async {
|
||||
final row = await findExistingTrack(request, columns: ['id']);
|
||||
return row != null;
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>?> findExistingTrack(
|
||||
HistoryLookupRequest request, {
|
||||
List<String>? columns,
|
||||
@@ -830,80 +825,6 @@ class HistoryDatabase {
|
||||
.toList(growable: false);
|
||||
}
|
||||
|
||||
Future<Set<String>> existingTrackKeys(
|
||||
List<HistoryLookupRequest> requests,
|
||||
) async {
|
||||
if (requests.isEmpty) return const <String>{};
|
||||
final db = await database;
|
||||
final found = <String>{};
|
||||
final rawSpotifyToKeys = <String, Set<String>>{};
|
||||
final normSpotifyToKeys = <String, Set<String>>{};
|
||||
final isrcToKeys = <String, Set<String>>{};
|
||||
final matchToKeys = <String, Set<String>>{};
|
||||
|
||||
void add(Map<String, Set<String>> map, String value, String key) {
|
||||
if (value.isEmpty) return;
|
||||
map.putIfAbsent(value, () => <String>{}).add(key);
|
||||
}
|
||||
|
||||
for (final request in requests) {
|
||||
final key = request.lookupKey;
|
||||
for (final candidate in spotifyLookupCandidates(request.spotifyId)) {
|
||||
add(rawSpotifyToKeys, candidate, key);
|
||||
add(normSpotifyToKeys, normalizeSpotifyId(candidate), key);
|
||||
}
|
||||
add(isrcToKeys, normalizeIsrc(request.isrc), key);
|
||||
add(matchToKeys, matchKeyFor(request.trackName, request.artistName), key);
|
||||
}
|
||||
|
||||
Future<void> queryColumn(
|
||||
String column,
|
||||
Map<String, Set<String>> keyMap,
|
||||
) async {
|
||||
final values = keyMap.keys.toList(growable: false);
|
||||
const chunkSize = 450;
|
||||
for (var i = 0; i < values.length; i += chunkSize) {
|
||||
final end = (i + chunkSize < values.length)
|
||||
? i + chunkSize
|
||||
: values.length;
|
||||
final chunk = values.sublist(i, end);
|
||||
final placeholders = List.filled(chunk.length, '?').join(',');
|
||||
final rows = await db.rawQuery(
|
||||
'SELECT DISTINCT $column AS lookup_value FROM history WHERE $column IN ($placeholders)',
|
||||
chunk,
|
||||
);
|
||||
for (final row in rows) {
|
||||
final value = row['lookup_value'] as String?;
|
||||
if (value == null) continue;
|
||||
found.addAll(keyMap[value] ?? const <String>{});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await queryColumn('spotify_id', rawSpotifyToKeys);
|
||||
await queryColumn('spotify_id_norm', normSpotifyToKeys);
|
||||
await queryColumn('isrc_norm', isrcToKeys);
|
||||
await queryColumn('match_key', matchToKeys);
|
||||
return found;
|
||||
}
|
||||
|
||||
Future<bool> existsBySpotifyId(String spotifyId) async {
|
||||
final db = await database;
|
||||
final result = await db.rawQuery(
|
||||
'SELECT 1 FROM history WHERE spotify_id = ? LIMIT 1',
|
||||
[spotifyId],
|
||||
);
|
||||
return result.isNotEmpty;
|
||||
}
|
||||
|
||||
Future<Set<String>> getAllSpotifyIds() async {
|
||||
final db = await database;
|
||||
final rows = await db.rawQuery(
|
||||
'SELECT spotify_id FROM history WHERE spotify_id IS NOT NULL AND spotify_id != ""',
|
||||
);
|
||||
return rows.map((r) => r['spotify_id'] as String).toSet();
|
||||
}
|
||||
|
||||
Future<void> deleteById(String id) async {
|
||||
final db = await database;
|
||||
await db.transaction((txn) async {
|
||||
@@ -1071,16 +992,6 @@ class HistoryDatabase {
|
||||
return rows.map((r) => r['file_path'] as String).toSet();
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> getAllEntriesWithPaths() async {
|
||||
final db = await database;
|
||||
final rows = await db.rawQuery('''
|
||||
SELECT id, file_path, storage_mode, download_tree_uri, saf_relative_dir, saf_file_name
|
||||
FROM history
|
||||
WHERE file_path IS NOT NULL AND file_path != ""
|
||||
''');
|
||||
return rows.map((r) => Map<String, dynamic>.from(r)).toList();
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> getEntriesWithPathsPage({
|
||||
required int limit,
|
||||
int offset = 0,
|
||||
|
||||
@@ -436,10 +436,6 @@ class NotificationService {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> cancelLibraryScanNotification() async {
|
||||
await _notifications.cancel(id: libraryScanId);
|
||||
}
|
||||
|
||||
Future<void> showUpdateDownloadProgress({
|
||||
required String version,
|
||||
required int received,
|
||||
|
||||
@@ -642,17 +642,6 @@ class PlatformBridge {
|
||||
return result as String?;
|
||||
}
|
||||
|
||||
static Future<bool> replaceContentUriFromPath(
|
||||
String uri,
|
||||
String srcPath,
|
||||
) async {
|
||||
final result = await _channel.invokeMethod('safReplaceFromPath', {
|
||||
'uri': uri,
|
||||
'src_path': srcPath,
|
||||
});
|
||||
return result as bool;
|
||||
}
|
||||
|
||||
static Future<String?> createSafFileFromPath({
|
||||
required String treeUri,
|
||||
required String relativeDir,
|
||||
@@ -1188,11 +1177,6 @@ class PlatformBridge {
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
static Future<int> getGoLogCount() async {
|
||||
final result = await _channel.invokeMethod('getLogCount');
|
||||
return result as int;
|
||||
}
|
||||
|
||||
static Future<void> setGoLoggingEnabled(bool enabled) async {
|
||||
await _channel.invokeMethod('setLoggingEnabled', {'enabled': enabled});
|
||||
}
|
||||
|
||||
@@ -297,30 +297,3 @@ class SettingsSectionHeader extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Small "BETA" pill, used as a [SettingsItem.titleTrailing] /
|
||||
/// [SettingsSwitchItem.titleTrailing] marker for experimental features.
|
||||
class BetaBadge extends StatelessWidget {
|
||||
final String label;
|
||||
|
||||
const BetaBadge({super.key, required this.label});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.tertiaryContainer,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: colorScheme.onTertiaryContainer,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user