From d387295ae7aca6b7bbde011560ee8db2aa4c75e2 Mon Sep 17 00:00:00 2001 From: MSOB7YY Date: Wed, 20 Nov 2024 03:25:28 +0200 Subject: [PATCH] perf: migrate video details to db - this also includes rewrite for cache checking parts and other functions making it more efficient --- lib/controller/backup_controller.dart | 6 +- lib/controller/settings_controller.dart | 6 +- lib/controller/video_controller.dart | 419 ++++++++---------- lib/core/constants.dart | 13 +- .../widgets/settings/advanced_settings.dart | 2 +- .../settings/backup_restore_settings.dart | 16 +- lib/ui/widgets/settings/indexer_settings.dart | 2 +- pubspec.yaml | 2 +- 8 files changed, 217 insertions(+), 249 deletions(-) diff --git a/lib/controller/backup_controller.dart b/lib/controller/backup_controller.dart index 270263a7..987b10dd 100644 --- a/lib/controller/backup_controller.dart +++ b/lib/controller/backup_controller.dart @@ -50,8 +50,10 @@ class BackupController { AppPaths.TRACKS_STATS_OLD, AppPaths.TRACKS_STATS_DB_INFO.file.path, AppPaths.TOTAL_LISTEN_TIME, - AppPaths.VIDEOS_CACHE, - AppPaths.VIDEOS_LOCAL, + AppPaths.VIDEOS_CACHE_OLD, + AppPaths.VIDEOS_CACHE_DB_INFO.file.path, + AppPaths.VIDEOS_LOCAL_OLD, + AppPaths.VIDEOS_LOCAL_DB_INFO.file.path, AppPaths.FAVOURITES_PLAYLIST, AppPaths.SETTINGS, AppPaths.SETTINGS_EQUALIZER, diff --git a/lib/controller/settings_controller.dart b/lib/controller/settings_controller.dart index e27d1ca4..10f7fbb6 100644 --- a/lib/controller/settings_controller.dart +++ b/lib/controller/settings_controller.dart @@ -120,8 +120,10 @@ class _SettingsController with SettingsFileWriter { AppPaths.TRACKS_STATS_OLD, AppPaths.TRACKS_STATS_DB_INFO.file.path, AppPaths.TOTAL_LISTEN_TIME, - AppPaths.VIDEOS_CACHE, - AppPaths.VIDEOS_LOCAL, + AppPaths.VIDEOS_CACHE_OLD, + AppPaths.VIDEOS_CACHE_DB_INFO.file.path, + AppPaths.VIDEOS_LOCAL_OLD, + AppPaths.VIDEOS_LOCAL_DB_INFO.file.path, AppPaths.SETTINGS, AppPaths.SETTINGS_EQUALIZER, AppDirs.PALETTES, diff --git a/lib/controller/video_controller.dart b/lib/controller/video_controller.dart index 5630d126..1e0a62ce 100644 --- a/lib/controller/video_controller.dart +++ b/lib/controller/video_controller.dart @@ -4,10 +4,10 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:just_audio/just_audio.dart'; +import 'package:namico_db_wrapper/namico_db_wrapper.dart'; import 'package:youtipie/class/streams/video_stream.dart'; import 'package:youtipie/class/streams/video_streams_result.dart'; -import 'package:namida/base/settings_file_writer.dart'; import 'package:namida/class/media_info.dart'; import 'package:namida/class/track.dart'; import 'package:namida/class/video.dart'; @@ -186,12 +186,15 @@ class VideoController { final isNoVideosAvailable = false.obs; /// `path`: `NamidaVideo` - final _videoPathsMap = {}; + var _videoPathsInfoMap = {}; var _allVideoPaths = {}; /// `id`: `[]` - final _videoCacheIDMap = >{}; + var _videoCacheIDMap = >{}; + + late final _videoCacheIDMapDB = DBWrapper.openFromInfo(fileInfo: AppPaths.VIDEOS_CACHE_DB_INFO, createIfNotExist: true); + late final _videoLocalMapDB = DBWrapper.openFromInfo(fileInfo: AppPaths.VIDEOS_LOCAL_DB_INFO, createIfNotExist: true); Iterable get videosInCache sync* { for (final vids in _videoCacheIDMap.values) { @@ -204,6 +207,7 @@ class VideoController { _videoCacheIDMap.addNoDuplicatesForce(id, nv); // well, no matter what happens, sometimes the info coming has extra info _videoCacheIDMap[id]?.removeDuplicates((element) => "${element.height}_${element.resolution}_${element.path}"); + _saveCachedVideos(id); } NamidaVideo addLocalVideoFileInfoToCacheMap(String path, MediaInfo info, FileStat fileStats, {String? ytID}) { @@ -213,8 +217,8 @@ class VideoController { path: path, stats: fileStats, ); - _videoPathsMap[path] = nv; - _saveLocalVideosFile(); + _videoPathsInfoMap[path] = nv; + _videoLocalMapDB.putAsync(path, nv.toJson()); return nv; } @@ -260,16 +264,21 @@ class VideoController { void removeNVFromCacheMap(String youtubeId, String path) { _videoCacheIDMap[youtubeId]?.removeWhere((element) => element.path == path); + _saveCachedVideos(youtubeId); } void deleteAllVideosForVideoId(String youtubeId) { final videos = _videoCacheIDMap[youtubeId]; videos?.loop((item) => File(item.path).deleteSync()); _videoCacheIDMap.remove(youtubeId); + _saveCachedVideos(youtubeId); } void clearCachedVideosMap() { _videoCacheIDMap.clear(); + _videoCacheIDMapDB + ..deleteEverything() + ..claimFreeSpaceAsync(); } Future updateCurrentVideo(Track? track, {bool returnEarly = false, bool handleVideoPlayback = true}) async { @@ -281,7 +290,7 @@ class VideoController { if (track == null || track == kDummyTrack) return null; if (!settings.enableVideoPlayback.value) return null; if (track is Video) { - final info = _videoPathsMap[track.path]; + final info = _videoPathsInfoMap[track.path]; final nv = info ?? NamidaVideo( path: track.path, @@ -511,8 +520,11 @@ class VideoController { updateCurrentBytes(); if (downloadedVideo != null) { - _videoCacheIDMap.addNoDuplicatesForce(downloadedVideo.ytID ?? '', downloadedVideo); - await _saveCachedVideosFile(); + final ytId = downloadedVideo.ytID; + if (ytId != null) { + _videoCacheIDMap.addNoDuplicatesForce(ytId, downloadedVideo); + await _saveCachedVideos(ytId); + } } if (_canExecuteForCurrentTrackOnly(initialTrack)) { currentDownloadedBytes.value = null; @@ -587,7 +599,7 @@ class VideoController { final possibleLocal = []; for (int i = 0; i < local.length; i++) { var l = local[i]; - NamidaVideo? nv = _videoPathsMap[l]; + NamidaVideo? nv = _videoPathsInfoMap[l]; if (nv == null) { try { final v = await NamidaFFMPEG.inst.extractMetadata(l); @@ -616,106 +628,75 @@ class VideoController { } Future initialize() async { - // -- Fetching Cached Videos Info. - final file = File(AppPaths.VIDEOS_CACHE); - final cacheVideosInfoFile = await file.readAsJson() as List?; - final vl = cacheVideosInfoFile?.mapped((e) => NamidaVideo.fromJson(e)); - _videoCacheIDMap.clear(); - vl?.loop((e) => _videoCacheIDMap.addForce(e.ytID ?? '', e)); - Future fetchCachedVideos() async { - final cachedVideos = await _checkIfVideosInMapValid(_videoCacheIDMap); + final cachedVideosAndToDelete = await _fetchAndCheckIfVideosInMapValid(); + final cachedVideos = cachedVideosAndToDelete.validMap; printy('videos cached: ${cachedVideos.length}'); - _videoCacheIDMap.clear(); - cachedVideos.entries.toList().loop((videoEntry) { - videoEntry.value.loop((e) { - _videoCacheIDMap.addForce(videoEntry.key, e); - }); - }); + _videoCacheIDMap = cachedVideos; + + for (final idKey in cachedVideosAndToDelete.shouldBeReSaved) { + _saveCachedVideos(idKey); // will write the map value and delete if required + } final newCachedVideos = await _checkForNewVideosInCache(cachedVideos); printy('videos cached new: ${newCachedVideos.length}'); - newCachedVideos.entries.toList().loop((videoEntry) { - videoEntry.value.loop((e) { - _videoCacheIDMap.addForce(videoEntry.key, e); + for (final newv in newCachedVideos.entries) { + newv.value.loop((e) { + _videoCacheIDMap.addForce(newv.key, e); }); - }); + _saveCachedVideos(newv.key); + } + } - // -- saving files - await _saveCachedVideosFile(); + Future fetchLocalVideos() async { + await rescanLocalVideosPaths(); + + final localVideos = await _VideoControllerIsolateFunctions._readLocalVideosDb.thready([AppPaths.VIDEOS_LOCAL_OLD, _videoLocalMapDB.fileInfo]); + printy('videos local: ${localVideos.length}'); + _videoPathsInfoMap = localVideos; } await Future.wait([ fetchCachedVideos(), // --> should think about a way to flank around scanning lots of cache videos if info not found (ex: after backup) - scanLocalVideos( - fillPathsOnly: true, extractIfFileNotFound: false, readCachedLocalFile: true), // this will get paths only and disables extracting whole local videos on startup + fetchLocalVideos(), // this will get paths only and disables extracting whole local videos on startup ]); if (Player.inst.videoPlayerInfo.value?.isInitialized != true) await updateCurrentVideo(Player.inst.currentTrack?.track); } - Future scanLocalVideos({ - bool strictNoMedia = true, - bool forceReScan = false, - bool extractIfFileNotFound = false, - required bool fillPathsOnly, - bool readCachedLocalFile = false, - }) async { - if (fillPathsOnly) { - localVideoExtractCurrent.value = 0; - final videos = await _fetchVideoPathsFromStorage(strictNoMedia: strictNoMedia, forceReCheckDir: forceReScan); - _allVideoPaths = videos; - localVideoExtractCurrent.value = null; - - if (readCachedLocalFile) { - final videosJson = await _videoLocalMapFileSaver._readFile(); - videosJson?.loop((e) { - final nv = NamidaVideo.fromJson(e); - _videoPathsMap[nv.path] = nv; - }); - } + Future rescanLocalVideosPaths({bool strictNoMedia = true}) async { + localVideoExtractCurrent.value = 0; + final videos = await _fetchVideoPathsFromStorage(strictNoMedia: strictNoMedia, forceReCheckDir: true); + _allVideoPaths = videos; + localVideoExtractCurrent.value = null; + } - return; + Future _saveCachedVideos(String id) { + final videos = _videoCacheIDMap[id]; + if (videos == null || videos.isEmpty) { + return _videoCacheIDMapDB.deleteAsync(id); } - - void resetCounters() { - localVideoExtractCurrent.value = 0; - localVideoExtractTotal.value = 0; + final map = >{}; + for (int i = 0; i < videos.length; i++) { + var item = videos[i]; + map['$i'] = item.toJson(); } - - resetCounters(); - final localVideos = await _getLocalVideos( - strictNoMedia: strictNoMedia, - forceReScan: forceReScan, - extractIfFileNotFound: extractIfFileNotFound, - onProgress: (didExtract, total) { - if (didExtract) localVideoExtractCurrent.value = (localVideoExtractCurrent.value ?? 0) + 1; - localVideoExtractTotal.value = total; - }, - ); - printy('videos local: ${localVideos.length}'); - localVideos.loop((e) { - _videoPathsMap[e.path] = e; - }); - resetCounters(); - localVideoExtractCurrent.value = null; + return _videoCacheIDMapDB.putAsync(id, map); } - final _videoCacheIDMapFileSaver = _VideoControllerCacheVideosFileSaver._(); - Future _saveCachedVideosFile() => _videoCacheIDMapFileSaver._writeToStorage(); - - final _videoLocalMapFileSaver = _VideoControllerLocalVideosFileSaver._(); - Future _saveLocalVideosFile() => _videoLocalMapFileSaver._writeToStorage(); - /// - Loops the map sent, makes sure that everything exists & valid. /// - Detects: `deleted` & `needs-to-be-updated` files /// - DOES NOT handle: `new files`. /// - Returns a copy of the map but with valid videos only. - Future>> _checkIfVideosInMapValid(Map> idsMap) async { - final res = await _checkIfVideosInMapValidIsolate.thready(idsMap); + Future<({Map> validMap, Set shouldBeReSaved})> _fetchAndCheckIfVideosInMapValid() async { + final res = await _VideoControllerIsolateFunctions._fetchAndCheckIfVideosInMapValidIsolate.thready([AppPaths.VIDEOS_CACHE_OLD, _videoCacheIDMapDB.fileInfo]); final validMap = res['validMap'] as Map>; final shouldBeReExtracted = res['newIdsMap'] as Map>; + final shouldBeRemoved = res['shouldBeRemoved'] as Map>; + + final videoKeysToReSave = {}; + videoKeysToReSave.addAll(shouldBeRemoved.keys); for (final newId in shouldBeReExtracted.entries) { for (final statAndPath in newId.value) { @@ -725,45 +706,11 @@ class VideoController { path: statAndPath.$2, ); validMap.addForce(newId.key, nv); + videoKeysToReSave.add(newId.key); } } - return validMap; - } - - static Future _checkIfVideosInMapValidIsolate(Map> idsMap) async { - final validMap = >{}; - final newIdsMap = >{}; - - final videosInMap = idsMap.entries.toList(); - - videosInMap.loop((ve) { - final id = ve.key; - final vl = ve.value; - vl.loop((v) { - final file = File(v.path); - // --- File Exists, will be added either instantly, or by fetching new metadata. - if (file.existsSync()) { - final stats = file.statSync(); - // -- Video Exists, and already updated. - if (v.sizeInBytes == stats.size) { - validMap.addForce(id, v); - } - // -- Video exists but needs to be updated. - else { - newIdsMap.addForce(id, (stats, v.path)); - } - } - - // else { - // -- File doesnt exist, ie. has been removed - // } - }); - }); - return { - "validMap": validMap, - "newIdsMap": newIdsMap, - }; + return (validMap: validMap, shouldBeReSaved: videoKeysToReSave); } /// - Loops the currently existing files @@ -772,7 +719,7 @@ class VideoController { /// - Returns a map with **new videos only**. /// - **New**: excludes files ending with `.part` Future>> _checkForNewVideosInCache(Map> idsMap) async { - final newIds = await _checkForNewVideosInCacheIsolate.thready({ + final newIds = await _VideoControllerIsolateFunctions._checkForNewVideosInCacheIsolate.thready({ 'dirPath': AppDirs.VIDEOS_CACHE, 'idsMap': idsMap, }); @@ -793,90 +740,6 @@ class VideoController { return newIdsMap; } - static Future>> _checkForNewVideosInCacheIsolate(Map params) async { - final dirPath = params['dirPath'] as String; - final idsMap = params['idsMap'] as Map>; - final dir = Directory(dirPath); - final newIdsMap = >{}; - - final dirFiles = dir.listSyncSafe(); - for (int i = 0; i < dirFiles.length; i++) { - var df = dirFiles[i]; - if (df is File) { - final filename = df.path.getFilename; - if (filename.endsWith('.part')) continue; // first thing first - if (filename.endsWith('.mime')) continue; // second thing second - - final id = filename.substring(0, 11); - final videosInMap = idsMap[id]; - final stats = df.statSync(); - final sizeInBytes = stats.size; - if (videosInMap != null) { - // if file exists in map and is valid - if (videosInMap.firstWhereEff((element) => element.sizeInBytes == sizeInBytes) != null) { - continue; // skipping since the map will contain only new entries - } - } - // -- hmmm looks like a new video, needs extraction - try { - newIdsMap.addForce(id, (stats, df.path)); - } catch (e) { - continue; - } - } - } - return newIdsMap; - } - - Future> _getLocalVideos({ - bool strictNoMedia = true, - bool forceReScan = false, - bool extractIfFileNotFound = true, - required void Function(bool didExtract, int total) onProgress, - }) async { - final videosFile = File(AppPaths.VIDEOS_LOCAL); - final namidaVideos = []; - - if (await videosFile.existsAndValid() && !forceReScan) { - final videosJson = await videosFile.readAsJson() as List?; - final vl = videosJson?.map((e) => NamidaVideo.fromJson(e)) ?? []; - namidaVideos.addAll(vl); - } else { - if (!extractIfFileNotFound) return []; - final videos = await _fetchVideoPathsFromStorage(strictNoMedia: strictNoMedia, forceReCheckDir: forceReScan); - - for (final path in videos) { - try { - final v = await NamidaFFMPEG.inst.extractMetadata(path); - if (v != null) { - ThumbnailManager.inst.extractVideoThumbnailAndSave( - videoPath: path, - isLocal: true, - idOrFileNameWithExt: path.getFilename, - isExtracted: true, - ); - final stats = await File(path).stat(); - final nv = _getNVFromFFMPEGMap( - path: path, - mediaInfo: v, - stats: stats, - ytID: null, - ); - namidaVideos.add(nv); - } - } catch (e) { - printy(e, isError: true); - continue; - } - - onProgress(true, videos.length); - } - await videosFile.writeAsJson(namidaVideos.mapped((e) => e.toJson())); - } - - return namidaVideos; - } - Future _extractNVFromFFMPEG({ required FileStat stats, required String? id, @@ -952,42 +815,134 @@ extension _GlobalPaintBounds on BuildContext { } } -class _VideoControllerCacheVideosFileSaver with SettingsFileWriter { - _VideoControllerCacheVideosFileSaver._(); - - @override - void applyKuruSettings() {} - - @override - Object get jsonToWrite { - final mapValuesTotal = >[]; - for (final e in VideoController.inst._videoCacheIDMap.values) { - mapValuesTotal.addAll(e.map((e) => e.toJson())); +class _VideoControllerIsolateFunctions { + const _VideoControllerIsolateFunctions(); + + static Map _readLocalVideosDb(List params) { + final oldJsonFilePath = params[0] as String; + final dbFileInfo = params[1] as DbWrapperFileInfo; + final oldJsonFile = File(oldJsonFilePath); + final db = DBWrapper.openFromInfo(fileInfo: dbFileInfo, createIfNotExist: true); + + // -- migrating old json file + if (oldJsonFile.existsSync()) { + try { + final localVideosInfoFile = oldJsonFile.readAsJsonSync() as List?; + if (localVideosInfoFile != null) { + for (final map in localVideosInfoFile) { + final path = map['path'] as String?; + if (path != null) db.put(path, map); + } + } + oldJsonFile.deleteSync(); + } catch (_) {} } - return mapValuesTotal; - } - Future _writeToStorage() async => await writeToStorage(); - - @override - String get filePath => AppPaths.VIDEOS_CACHE; -} - -class _VideoControllerLocalVideosFileSaver with SettingsFileWriter { - _VideoControllerLocalVideosFileSaver._(); + final localVids = {}; + db.loadEverything( + (e) { + final nv = NamidaVideo.fromJson(e); + localVids[nv.path] = nv; + }, + ); + return localVids; + } + + static Future _fetchAndCheckIfVideosInMapValidIsolate(List params) async { + final oldJsonFilePath = params[0] as String; + final dbFileInfo = params[1] as DbWrapperFileInfo; + final oldJsonFile = File(oldJsonFilePath); + final db = DBWrapper.openFromInfo(fileInfo: dbFileInfo, createIfNotExist: true); + + // -- migrating old json file + if (oldJsonFile.existsSync()) { + try { + final cacheVideosInfoFile = oldJsonFile.readAsJsonSync() as List?; + if (cacheVideosInfoFile != null) { + final videosInMap = >>{}; + for (final map in cacheVideosInfoFile) { + final youtubeId = map['ytID'] as String?; + if (youtubeId != null) { + videosInMap[youtubeId] ??= {}; + final indexString = '${videosInMap[youtubeId]!.length}'; + videosInMap[youtubeId]![indexString] = map; + } + } + for (final e in videosInMap.entries) { + db.put(e.key, e.value); + } + } + oldJsonFile.deleteSync(); + } catch (_) {} + } - @override - void applyKuruSettings() {} + final validMap = >{}; + final newIdsMap = >{}; + final shouldBeRemoved = >{}; + + db.loadEverythingKeyed( + (id, value) { + for (final videoJson in value.values) { + final v = NamidaVideo.fromJson(videoJson); + final file = File(v.path); + // --- File Exists, will be added either instantly, or by fetching new metadata. + if (file.existsSync()) { + final stats = file.statSync(); + // -- Video Exists, and already updated. + if (v.sizeInBytes == stats.size) { + validMap.addForce(id, v); + } + // -- Video exists but needs to be updated. + else { + newIdsMap.addForce(id, (stats, v.path)); + } + } else { + // -- File doesnt exist, ie. has been removed + shouldBeRemoved.addForce(id, v); + } + } + }, + ); - @override - Object get jsonToWrite { - return VideoController.inst._videoPathsMap.values.map((e) => e.toJson()).toList(); + return { + "validMap": validMap, + "newIdsMap": newIdsMap, + "shouldBeRemoved": shouldBeRemoved, + }; } - Future _readFile() async => await prepareSettingsFile_() as List?; + static Future>> _checkForNewVideosInCacheIsolate(Map params) async { + final dirPath = params['dirPath'] as String; + final idsMap = params['idsMap'] as Map>; + final dir = Directory(dirPath); + final newIdsMap = >{}; - Future _writeToStorage() => writeToStorage(); + final dirFiles = dir.listSyncSafe(); + for (int i = 0; i < dirFiles.length; i++) { + var df = dirFiles[i]; + if (df is File) { + final filename = df.path.getFilename; + if (filename.endsWith('.part')) continue; // first thing first + if (filename.endsWith('.mime')) continue; // second thing second - @override - String get filePath => AppPaths.VIDEOS_LOCAL; + final id = filename.substring(0, 11); + final videosInMap = idsMap[id]; + final stats = df.statSync(); + final sizeInBytes = stats.size; + if (videosInMap != null) { + // if file exists in map and is valid + if (videosInMap.firstWhereEff((element) => element.sizeInBytes == sizeInBytes) != null) { + continue; // skipping since the map will contain only new entries + } + } + // -- hmmm looks like a new video, needs extraction + try { + newIdsMap.addForce(id, (stats, df.path)); + } catch (e) { + continue; + } + } + } + return newIdsMap; + } } diff --git a/lib/core/constants.dart b/lib/core/constants.dart index c4a175d7..34add0fc 100644 --- a/lib/core/constants.dart +++ b/lib/core/constants.dart @@ -227,14 +227,19 @@ class AppPaths { static final SETTINGS_PLAYER = _join(_USER_DATA, 'namida_settings_player.json'); static final SETTINGS_YOUTUBE = _join(_USER_DATA, 'namida_settings_youtube.json'); static final SETTINGS_EXTRA = _join(_USER_DATA, 'namida_settings_extra.json'); - static final TRACKS_OLD = _join(_USER_DATA, 'tracks.json'); static final TRACKS_DB_INFO = DbWrapperFileInfo(directory: _USER_DATA, dbName: 'tracks'); - static final TRACKS_STATS_OLD = _join(_USER_DATA, 'tracks_stats.json'); static final TRACKS_STATS_DB_INFO = DbWrapperFileInfo(directory: _USER_DATA, dbName: 'tracks_stats'); - static final VIDEOS_LOCAL = _join(_USER_DATA, 'local_videos.json'); - static final VIDEOS_CACHE = _join(_USER_DATA, 'cache_videos.json'); + static final VIDEOS_LOCAL_DB_INFO = DbWrapperFileInfo(directory: _USER_DATA, dbName: 'local_videos'); + static final VIDEOS_CACHE_DB_INFO = DbWrapperFileInfo(directory: _USER_DATA, dbName: 'cache_videos'); static final LATEST_QUEUE = _join(_USER_DATA, 'latest_queue.json'); + // -- obsolete + static final TRACKS_OLD = _join(_USER_DATA, 'tracks.json'); + static final TRACKS_STATS_OLD = _join(_USER_DATA, 'tracks_stats.json'); + static final VIDEOS_LOCAL_OLD = _join(_USER_DATA, 'local_videos.json'); + static final VIDEOS_CACHE_OLD = _join(_USER_DATA, 'cache_videos.json'); + // --------- + static String get LOGS => _getLogsFile(''); static String get LOGS_TAGGER => _getLogsFile('_tagger'); diff --git a/lib/ui/widgets/settings/advanced_settings.dart b/lib/ui/widgets/settings/advanced_settings.dart index be286861..088eebea 100644 --- a/lib/ui/widgets/settings/advanced_settings.dart +++ b/lib/ui/widgets/settings/advanced_settings.dart @@ -298,7 +298,7 @@ class AdvancedSettings extends SettingSubpageProvider { ), title: lang.RESCAN_VIDEOS, onTap: () async { - await VideoController.inst.scanLocalVideos(forceReScan: true, fillPathsOnly: true); + await VideoController.inst.rescanLocalVideosPaths(); snackyy(title: lang.DONE, message: lang.FINISHED_UPDATING_LIBRARY); }, ), diff --git a/lib/ui/widgets/settings/backup_restore_settings.dart b/lib/ui/widgets/settings/backup_restore_settings.dart index b28b425f..62498dd7 100644 --- a/lib/ui/widgets/settings/backup_restore_settings.dart +++ b/lib/ui/widgets/settings/backup_restore_settings.dart @@ -182,7 +182,7 @@ class BackupAndRestore extends SettingSubpageProvider { } } - final totalFiles = [ + final totalFiles = [ AppPaths.SETTINGS, AppPaths.SETTINGS_EQUALIZER, AppPaths.SETTINGS_PLAYER, @@ -192,8 +192,10 @@ class BackupAndRestore extends SettingSubpageProvider { AppPaths.TRACKS_DB_INFO.file.path, AppPaths.TRACKS_STATS_OLD, AppPaths.TRACKS_STATS_DB_INFO.file.path, - AppPaths.VIDEOS_LOCAL, - AppPaths.VIDEOS_CACHE, + AppPaths.VIDEOS_LOCAL_OLD, + AppPaths.VIDEOS_LOCAL_DB_INFO.file.path, + AppPaths.VIDEOS_CACHE_OLD, + AppPaths.VIDEOS_CACHE_DB_INFO.file.path, AppPaths.LATEST_QUEUE, AppPaths.TOTAL_LISTEN_TIME, AppPaths.FAVOURITES_PLAYLIST, @@ -202,7 +204,7 @@ class BackupAndRestore extends SettingSubpageProvider { AppPaths.YT_SUBSCRIPTIONS_GROUPS_ALL, ]; - final totalDirs = [ + final totalDirs = [ AppDirs.PLAYLISTS, AppDirs.HISTORY_PLAYLIST, AppDirs.LYRICS, @@ -377,8 +379,10 @@ class BackupAndRestore extends SettingSubpageProvider { AppPaths.TRACKS_STATS_OLD, AppPaths.TRACKS_STATS_DB_INFO.file.path, AppPaths.TOTAL_LISTEN_TIME, - AppPaths.VIDEOS_CACHE, - AppPaths.VIDEOS_LOCAL, + AppPaths.VIDEOS_CACHE_OLD, + AppPaths.VIDEOS_CACHE_DB_INFO.file.path, + AppPaths.VIDEOS_LOCAL_OLD, + AppPaths.VIDEOS_LOCAL_DB_INFO.file.path, AppDirs.YT_DOWNLOAD_TASKS, ], youtubeAvailable: true, diff --git a/lib/ui/widgets/settings/indexer_settings.dart b/lib/ui/widgets/settings/indexer_settings.dart index b642778a..d24580f8 100644 --- a/lib/ui/widgets/settings/indexer_settings.dart +++ b/lib/ui/widgets/settings/indexer_settings.dart @@ -897,7 +897,7 @@ Future showRefreshPromptDialog(bool didModifyFolder) async { onPressed: () async { NamidaNavigator.inst.closeDialog(); await Future.delayed(const Duration(milliseconds: 300)); - VideoController.inst.scanLocalVideos(forceReScan: true, fillPathsOnly: true); + VideoController.inst.rescanLocalVideosPaths(); await Indexer.inst.refreshLibraryAndCheckForDiff(currentFiles: currentFiles); }, ), diff --git a/pubspec.yaml b/pubspec.yaml index a022ac44..4603843d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: namida description: A Beautiful and Feature-rich Music Player, With YouTube & Video Support Built in Flutter publish_to: "none" -version: 4.7.05-beta+241120013 +version: 4.7.1-beta+241120014 environment: sdk: ">=3.4.0 <4.0.0"