source: disable analysis for widget, screen saver; disabling analysis also disables entry discovery
This commit is contained in:
parent
618b63bfc0
commit
211f803afe
17 changed files with 64 additions and 86 deletions
|
@ -296,14 +296,11 @@ open class MainActivity : FlutterFragmentActivity() {
|
|||
open fun extractIntentData(intent: Intent?): FieldMap {
|
||||
when (val action = intent?.action) {
|
||||
Intent.ACTION_MAIN -> {
|
||||
val fields = HashMap<String, Any?>()
|
||||
if (intent.getBooleanExtra(EXTRA_KEY_SAFE_MODE, false)) {
|
||||
fields[INTENT_DATA_KEY_SAFE_MODE] = true
|
||||
}
|
||||
fields[INTENT_DATA_KEY_PAGE] = intent.getStringExtra(EXTRA_KEY_PAGE)
|
||||
fields[INTENT_DATA_KEY_FILTERS] = extractFiltersFromIntent(intent)
|
||||
fields[INTENT_DATA_KEY_EXPLORER_PATH] = intent.getStringExtra(EXTRA_KEY_EXPLORER_PATH)
|
||||
return fields
|
||||
return hashMapOf(
|
||||
INTENT_DATA_KEY_PAGE to intent.getStringExtra(EXTRA_KEY_PAGE),
|
||||
INTENT_DATA_KEY_FILTERS to extractFiltersFromIntent(intent),
|
||||
INTENT_DATA_KEY_EXPLORER_PATH to intent.getStringExtra(EXTRA_KEY_EXPLORER_PATH),
|
||||
)
|
||||
}
|
||||
|
||||
Intent.ACTION_VIEW,
|
||||
|
@ -557,7 +554,6 @@ open class MainActivity : FlutterFragmentActivity() {
|
|||
const val INTENT_DATA_KEY_MIME_TYPE = "mimeType"
|
||||
const val INTENT_DATA_KEY_PAGE = "page"
|
||||
const val INTENT_DATA_KEY_QUERY = "query"
|
||||
const val INTENT_DATA_KEY_SAFE_MODE = "safeMode"
|
||||
const val INTENT_DATA_KEY_SECURE_URIS = "secureUris"
|
||||
const val INTENT_DATA_KEY_URI = "uri"
|
||||
const val INTENT_DATA_KEY_WIDGET_ID = "widgetId"
|
||||
|
@ -566,7 +562,6 @@ open class MainActivity : FlutterFragmentActivity() {
|
|||
const val EXTRA_KEY_EXPLORER_PATH = "explorerPath"
|
||||
const val EXTRA_KEY_FILTERS_ARRAY = "filters"
|
||||
const val EXTRA_KEY_FILTERS_STRING = "filtersString"
|
||||
const val EXTRA_KEY_SAFE_MODE = "safeMode"
|
||||
const val EXTRA_KEY_WIDGET_ID = "widgetId"
|
||||
|
||||
// dart page routes
|
||||
|
|
|
@ -21,15 +21,11 @@ class MediaStoreStreamHandler(private val context: Context, arguments: Any?) : E
|
|||
|
||||
private var knownEntries: Map<Long?, Int?>? = null
|
||||
private var directory: String? = null
|
||||
private var safe: Boolean = false
|
||||
|
||||
init {
|
||||
if (arguments is Map<*, *>) {
|
||||
knownEntries = (arguments["knownEntries"] as? Map<*, *>?)?.map { (it.key as Number?)?.toLong() to it.value as Int? }?.toMap()
|
||||
directory = arguments["directory"] as String?
|
||||
// do not use kotlin.collections `getOrDefault` as it crashes on API <24
|
||||
// and there is no warning from Android Studio
|
||||
safe = arguments["safe"] as Boolean? ?: false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +59,7 @@ class MediaStoreStreamHandler(private val context: Context, arguments: Any?) : E
|
|||
}
|
||||
|
||||
private fun fetchAll() {
|
||||
MediaStoreImageProvider().fetchAll(context, knownEntries ?: emptyMap(), directory, safe) { success(it) }
|
||||
MediaStoreImageProvider().fetchAll(context, knownEntries ?: emptyMap(), directory) { success(it) }
|
||||
endOfStream()
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.content.Context
|
|||
import android.graphics.BitmapFactory
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.net.Uri
|
||||
import androidx.exifinterface.media.ExifInterfaceFork as ExifInterface
|
||||
import com.drew.metadata.avi.AviDirectory
|
||||
import com.drew.metadata.exif.ExifIFD0Directory
|
||||
import com.drew.metadata.jpeg.JpegDirectory
|
||||
|
@ -29,6 +28,7 @@ import deckers.thibault.aves.utils.StorageUtils
|
|||
import deckers.thibault.aves.utils.UriUtils.tryParseId
|
||||
import org.beyka.tiffbitmapfactory.TiffBitmapFactory
|
||||
import java.io.IOException
|
||||
import androidx.exifinterface.media.ExifInterfaceFork as ExifInterface
|
||||
|
||||
class SourceEntry {
|
||||
private val origin: Int
|
||||
|
@ -116,8 +116,8 @@ class SourceEntry {
|
|||
// metadata retrieval
|
||||
// expects entry with: uri, mimeType
|
||||
// finds: width, height, orientation/rotation, date, title, duration
|
||||
fun fillPreCatalogMetadata(context: Context, safe: Boolean): SourceEntry {
|
||||
if (isSvg || safe) return this
|
||||
fun fillPreCatalogMetadata(context: Context): SourceEntry {
|
||||
if (isSvg) return this
|
||||
if (isVideo) {
|
||||
fillVideoByMediaMetadataRetriever(context)
|
||||
if (isSized && hasDuration) return this
|
||||
|
|
|
@ -53,7 +53,7 @@ internal class FileImageProvider : ImageProvider() {
|
|||
return
|
||||
}
|
||||
}
|
||||
entry.fillPreCatalogMetadata(context, safe = false)
|
||||
entry.fillPreCatalogMetadata(context)
|
||||
|
||||
if (allowUnsized || entry.isSized || entry.isSvg || entry.isVideo) {
|
||||
callback.onSuccess(entry.toMap())
|
||||
|
|
|
@ -51,10 +51,9 @@ class MediaStoreImageProvider : ImageProvider() {
|
|||
context: Context,
|
||||
knownEntries: Map<Long?, Int?>,
|
||||
directory: String?,
|
||||
safe: Boolean,
|
||||
handleNewEntry: NewEntryHandler,
|
||||
) {
|
||||
Log.d(LOG_TAG, "fetching all media store items for ${knownEntries.size} known entries, directory=$directory safe=$safe")
|
||||
Log.d(LOG_TAG, "fetching all media store items for ${knownEntries.size} known entries, directory=$directory")
|
||||
val isModified = fun(contentId: Long, dateModifiedSecs: Int): Boolean {
|
||||
val knownDate = knownEntries[contentId]
|
||||
return knownDate == null || knownDate < dateModifiedSecs
|
||||
|
@ -84,8 +83,8 @@ class MediaStoreImageProvider : ImageProvider() {
|
|||
} else {
|
||||
handleNew = handleNewEntry
|
||||
}
|
||||
fetchFrom(context, isModified, handleNew, IMAGE_CONTENT_URI, IMAGE_PROJECTION, selection, selectionArgs, safe = safe)
|
||||
fetchFrom(context, isModified, handleNew, VIDEO_CONTENT_URI, VIDEO_PROJECTION, selection, selectionArgs, safe = safe)
|
||||
fetchFrom(context, isModified, handleNew, IMAGE_CONTENT_URI, IMAGE_PROJECTION, selection, selectionArgs)
|
||||
fetchFrom(context, isModified, handleNew, VIDEO_CONTENT_URI, VIDEO_PROJECTION, selection, selectionArgs)
|
||||
}
|
||||
|
||||
// the provided URI can point to the wrong media collection,
|
||||
|
@ -208,7 +207,6 @@ class MediaStoreImageProvider : ImageProvider() {
|
|||
selection: String? = null,
|
||||
selectionArgs: Array<String>? = null,
|
||||
fileMimeType: String? = null,
|
||||
safe: Boolean = false,
|
||||
): Boolean {
|
||||
var found = false
|
||||
val orderBy = "${MediaStore.MediaColumns.DATE_MODIFIED} DESC"
|
||||
|
@ -302,7 +300,7 @@ class MediaStoreImageProvider : ImageProvider() {
|
|||
// missing some attributes such as width, height, orientation.
|
||||
// Also, the reported size of raw images is inconsistent across devices
|
||||
// and Android versions (sometimes the raw size, sometimes the decoded size).
|
||||
val entry = SourceEntry(entryMap).fillPreCatalogMetadata(context, safe)
|
||||
val entry = SourceEntry(entryMap).fillPreCatalogMetadata(context)
|
||||
entryMap = entry.toMap()
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ open class UnknownContentProvider : ImageProvider() {
|
|||
return
|
||||
}
|
||||
|
||||
val entry = SourceEntry(fields).fillPreCatalogMetadata(context, safe = false)
|
||||
val entry = SourceEntry(fields).fillPreCatalogMetadata(context)
|
||||
if (allowUnsized || entry.isSized || entry.isSvg || entry.isVideo) {
|
||||
callback.onSuccess(entry.toMap())
|
||||
} else {
|
||||
|
|
|
@ -21,7 +21,6 @@ class IntentDataKeys {
|
|||
static const mimeType = 'mimeType';
|
||||
static const page = 'page';
|
||||
static const query = 'query';
|
||||
static const safeMode = 'safeMode';
|
||||
static const secureUris = 'secureUris';
|
||||
static const uri = 'uri';
|
||||
static const widgetId = 'widgetId';
|
||||
|
|
|
@ -31,7 +31,7 @@ import 'package:collection/collection.dart';
|
|||
import 'package:event_bus/event_bus.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
enum SourceInitializationState { none, directory, full }
|
||||
enum SourceScope { none, album, full }
|
||||
|
||||
mixin SourceBase {
|
||||
EventBus get eventBus;
|
||||
|
@ -93,7 +93,7 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
|
|||
_rawEntries.forEach((v) => v.dispose());
|
||||
}
|
||||
|
||||
set safeMode(bool enabled);
|
||||
set canAnalyze(bool enabled);
|
||||
|
||||
final EventBus _eventBus = EventBus();
|
||||
|
||||
|
@ -427,13 +427,12 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
|
|||
eventBus.fire(EntryMovedEvent(MoveType.move, movedEntries));
|
||||
}
|
||||
|
||||
SourceInitializationState get initState => SourceInitializationState.none;
|
||||
SourceScope get scope => SourceScope.none;
|
||||
|
||||
Future<void> init({
|
||||
AnalysisController? analysisController,
|
||||
String? directory,
|
||||
AlbumFilter? albumFilter,
|
||||
bool loadTopEntriesFirst = false,
|
||||
bool canAnalyze = true,
|
||||
});
|
||||
|
||||
Future<Set<String>> refreshUris(Set<String> changedUris, {AnalysisController? analysisController});
|
||||
|
@ -518,13 +517,13 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
|
|||
|
||||
// monitoring
|
||||
|
||||
bool _monitoring = true;
|
||||
bool _canRefresh = true;
|
||||
|
||||
void pauseMonitoring() => _monitoring = false;
|
||||
void pauseMonitoring() => _canRefresh = false;
|
||||
|
||||
void resumeMonitoring() => _monitoring = true;
|
||||
void resumeMonitoring() => _canRefresh = true;
|
||||
|
||||
bool get isMonitoring => _monitoring;
|
||||
bool get canRefresh => _canRefresh;
|
||||
|
||||
// filter summary
|
||||
|
||||
|
|
|
@ -21,36 +21,34 @@ class MediaStoreSource extends CollectionSource {
|
|||
final Debouncer _changeDebouncer = Debouncer(delay: ADurations.mediaContentChangeDebounceDelay);
|
||||
final Set<String> _changedUris = {};
|
||||
int? _lastGeneration;
|
||||
SourceInitializationState _initState = SourceInitializationState.none;
|
||||
bool _safeMode = false;
|
||||
SourceScope _scope = SourceScope.none;
|
||||
bool _canAnalyze = true;
|
||||
|
||||
@override
|
||||
set safeMode(bool enabled) => _safeMode = enabled;
|
||||
set canAnalyze(bool enabled) => _canAnalyze = enabled;
|
||||
|
||||
@override
|
||||
SourceInitializationState get initState => _initState;
|
||||
SourceScope get scope => _scope;
|
||||
|
||||
@override
|
||||
Future<void> init({
|
||||
AnalysisController? analysisController,
|
||||
String? directory,
|
||||
AlbumFilter? albumFilter,
|
||||
bool loadTopEntriesFirst = false,
|
||||
bool canAnalyze = true,
|
||||
}) async {
|
||||
await reportService.log('$runtimeType init directory=$directory');
|
||||
if (_initState == SourceInitializationState.none) {
|
||||
await reportService.log('$runtimeType init album=${albumFilter?.album}');
|
||||
if (_scope == SourceScope.none) {
|
||||
await _loadEssentials();
|
||||
}
|
||||
if (_initState != SourceInitializationState.full) {
|
||||
_initState = directory != null ? SourceInitializationState.directory : SourceInitializationState.full;
|
||||
if (_scope != SourceScope.full) {
|
||||
_scope = albumFilter != null ? SourceScope.album : SourceScope.full;
|
||||
}
|
||||
addDirectories(albums: settings.pinnedFilters.whereType<AlbumFilter>().map((v) => v.album).toSet());
|
||||
await updateGeneration();
|
||||
unawaited(_loadEntries(
|
||||
analysisController: analysisController,
|
||||
directory: directory,
|
||||
directory: albumFilter?.album,
|
||||
loadTopEntriesFirst: loadTopEntriesFirst,
|
||||
canAnalyze: canAnalyze && !_safeMode,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -80,7 +78,6 @@ class MediaStoreSource extends CollectionSource {
|
|||
AnalysisController? analysisController,
|
||||
String? directory,
|
||||
required bool loadTopEntriesFirst,
|
||||
required bool canAnalyze,
|
||||
}) async {
|
||||
unawaited(reportService.log('$runtimeType load start'));
|
||||
final stopwatch = Stopwatch()..start();
|
||||
|
@ -158,6 +155,12 @@ class MediaStoreSource extends CollectionSource {
|
|||
knownDateByContentId[contentId] = 0;
|
||||
});
|
||||
|
||||
if (!_canAnalyze) {
|
||||
// it can discover new entries only if it can analyze them
|
||||
state = SourceState.ready;
|
||||
return;
|
||||
}
|
||||
|
||||
// items to add to the collection
|
||||
final newEntries = <AvesEntry>{};
|
||||
|
||||
|
@ -169,7 +172,7 @@ class MediaStoreSource extends CollectionSource {
|
|||
|
||||
// fetch new & modified entries
|
||||
debugPrint('$runtimeType load ${stopwatch.elapsed} fetch new entries');
|
||||
mediaStoreService.getEntries(_safeMode, knownDateByContentId, directory: directory).listen(
|
||||
mediaStoreService.getEntries(knownDateByContentId, directory: directory).listen(
|
||||
(entry) {
|
||||
// when discovering modified entry with known content ID,
|
||||
// reuse known entry ID to overwrite it while preserving favourites, etc.
|
||||
|
@ -210,11 +213,7 @@ class MediaStoreSource extends CollectionSource {
|
|||
if (analysisIds != null) {
|
||||
analysisEntries = visibleEntries.where((entry) => analysisIds.contains(entry.id)).toSet();
|
||||
}
|
||||
if (canAnalyze) {
|
||||
await analyze(analysisController, entries: analysisEntries);
|
||||
} else {
|
||||
state = SourceState.ready;
|
||||
}
|
||||
await analyze(analysisController, entries: analysisEntries);
|
||||
|
||||
// the home page may not reflect the current derived filters
|
||||
// as the initial addition of entries is silent,
|
||||
|
@ -234,7 +233,7 @@ class MediaStoreSource extends CollectionSource {
|
|||
// sometimes yields an entry with its temporary path: `/data/sec/camera/!@#$%^..._temp.jpg`
|
||||
@override
|
||||
Future<Set<String>> refreshUris(Set<String> changedUris, {AnalysisController? analysisController}) async {
|
||||
if (_initState == SourceInitializationState.none || !isMonitoring || !isReady) return changedUris;
|
||||
if (_scope == SourceScope.none || !canRefresh || !isReady) return changedUris;
|
||||
|
||||
state = SourceState.loading;
|
||||
|
||||
|
@ -272,7 +271,8 @@ class MediaStoreSource extends CollectionSource {
|
|||
if (volume != null) {
|
||||
if (existingEntry != null) {
|
||||
entriesToRefresh.add(existingEntry);
|
||||
} else {
|
||||
} else if (_canAnalyze) {
|
||||
// it can discover new entries only if it can analyze them
|
||||
sourceEntry.id = localMediaDb.nextId;
|
||||
newEntries.add(sourceEntry);
|
||||
}
|
||||
|
@ -329,10 +329,6 @@ class MediaStoreSource extends CollectionSource {
|
|||
}
|
||||
|
||||
void onStoreChanged(String? uri) {
|
||||
// dismiss changes if the source is only loaded to view a specific directory
|
||||
// to let the main instance handle the change in the database
|
||||
if (_initState == SourceInitializationState.directory) return;
|
||||
|
||||
if (uri != null) _changedUris.add(uri);
|
||||
if (_changedUris.isNotEmpty) {
|
||||
_changeDebouncer(() async {
|
||||
|
|
|
@ -15,7 +15,7 @@ abstract class MediaStoreService {
|
|||
Future<int?> getGeneration();
|
||||
|
||||
// knownEntries: map of contentId -> dateModifiedSecs
|
||||
Stream<AvesEntry> getEntries(bool safe, Map<int?, int?> knownEntries, {String? directory});
|
||||
Stream<AvesEntry> getEntries(Map<int?, int?> knownEntries, {String? directory});
|
||||
|
||||
// returns media URI
|
||||
Future<Uri?> scanFile(String path, String mimeType);
|
||||
|
@ -77,13 +77,12 @@ class PlatformMediaStoreService implements MediaStoreService {
|
|||
}
|
||||
|
||||
@override
|
||||
Stream<AvesEntry> getEntries(bool safe, Map<int?, int?> knownEntries, {String? directory}) {
|
||||
Stream<AvesEntry> getEntries(Map<int?, int?> knownEntries, {String? directory}) {
|
||||
try {
|
||||
return _stream
|
||||
.receiveBroadcastStream(<String, dynamic>{
|
||||
'knownEntries': knownEntries,
|
||||
'directory': directory,
|
||||
'safe': safe,
|
||||
})
|
||||
.where((event) => event is Map)
|
||||
.map((event) => AvesEntry.fromMap(event as Map));
|
||||
|
|
|
@ -96,7 +96,8 @@ Future<AvesEntry?> _getWidgetEntry(int widgetId, bool reuseEntry) async {
|
|||
readyCompleter.complete();
|
||||
}
|
||||
});
|
||||
await source.init(canAnalyze: false);
|
||||
source.canAnalyze = false;
|
||||
await source.init();
|
||||
await readyCompleter.future;
|
||||
|
||||
final entries = CollectionLens(source: source, filters: filters).sortedEntries;
|
||||
|
|
|
@ -683,7 +683,7 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
|||
|
||||
Future<void> _onAnalysisCompletion() async {
|
||||
debugPrint('Analysis completed');
|
||||
if (_mediaStoreSource.initState != SourceInitializationState.none) {
|
||||
if (_mediaStoreSource.scope != SourceScope.none) {
|
||||
await _mediaStoreSource.loadCatalogMetadata();
|
||||
await _mediaStoreSource.loadAddresses();
|
||||
_mediaStoreSource.updateDerivedFilters();
|
||||
|
|
|
@ -35,9 +35,10 @@ Future<String?> pickAlbum({
|
|||
required MoveType? moveType,
|
||||
}) async {
|
||||
final source = context.read<CollectionSource>();
|
||||
if (source.initState != SourceInitializationState.full) {
|
||||
if (source.scope != SourceScope.full) {
|
||||
await reportService.log('Complete source initialization to pick album');
|
||||
// source may not be fully initialized in view mode
|
||||
source.canAnalyze = true;
|
||||
await source.init();
|
||||
}
|
||||
final filter = await Navigator.maybeOf(context)?.push(
|
||||
|
|
|
@ -98,7 +98,6 @@ class _HomePageState extends State<HomePage> {
|
|||
var appMode = AppMode.main;
|
||||
var error = false;
|
||||
final intentData = widget.intentData ?? await IntentService.getIntentData();
|
||||
final safeMode = (intentData[IntentDataKeys.safeMode] as bool?) ?? false;
|
||||
final intentAction = intentData[IntentDataKeys.action] as String?;
|
||||
_initialFilters = null;
|
||||
_initialExplorerPath = null;
|
||||
|
@ -223,19 +222,16 @@ class _HomePageState extends State<HomePage> {
|
|||
unawaited(GlobalSearch.registerCallback());
|
||||
unawaited(AnalysisService.registerCallback());
|
||||
final source = context.read<CollectionSource>();
|
||||
source.safeMode = safeMode;
|
||||
if (source.initState != SourceInitializationState.full) {
|
||||
await reportService.log('Initialize source (init state=${source.initState.name}) to start app with mode=$appMode');
|
||||
await source.init(
|
||||
loadTopEntriesFirst: settings.homePage == HomePageSetting.collection && settings.homeCustomCollection.isEmpty,
|
||||
);
|
||||
if (source.scope != SourceScope.full) {
|
||||
await reportService.log('Initialize source (init state=${source.scope.name}) to start app with mode=$appMode');
|
||||
final loadTopEntriesFirst = settings.homePage == HomePageSetting.collection && settings.homeCustomCollection.isEmpty;
|
||||
await source.init(loadTopEntriesFirst: loadTopEntriesFirst);
|
||||
}
|
||||
case AppMode.screenSaver:
|
||||
final source = context.read<CollectionSource>();
|
||||
await reportService.log('Initialize source to start screen saver');
|
||||
await source.init(
|
||||
canAnalyze: false,
|
||||
);
|
||||
final source = context.read<CollectionSource>();
|
||||
source.canAnalyze = false;
|
||||
await source.init();
|
||||
case AppMode.view:
|
||||
if (_isViewerSourceable(_viewerEntry) && _secureUris == null) {
|
||||
final directory = _viewerEntry?.directory;
|
||||
|
@ -243,10 +239,8 @@ class _HomePageState extends State<HomePage> {
|
|||
unawaited(AnalysisService.registerCallback());
|
||||
await reportService.log('Initialize source to view item in directory $directory');
|
||||
final source = context.read<CollectionSource>();
|
||||
await source.init(
|
||||
directory: directory,
|
||||
canAnalyze: false,
|
||||
);
|
||||
source.canAnalyze = false;
|
||||
await source.init(albumFilter: AlbumFilter(directory, null));
|
||||
}
|
||||
} else {
|
||||
await _initViewerEssentials();
|
||||
|
@ -311,7 +305,7 @@ class _HomePageState extends State<HomePage> {
|
|||
CollectionLens? collection;
|
||||
|
||||
final source = context.read<CollectionSource>();
|
||||
if (source.initState != SourceInitializationState.none) {
|
||||
if (source.scope != SourceScope.none) {
|
||||
final album = viewerEntry.directory;
|
||||
if (album != null) {
|
||||
// wait for collection to pass the `loading` state
|
||||
|
|
|
@ -437,7 +437,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
showFeedback(context, FeedbackType.warn, l10n.genericFailureFeedback);
|
||||
} else {
|
||||
final source = context.read<CollectionSource>();
|
||||
if (source.initState != SourceInitializationState.none) {
|
||||
if (source.scope != SourceScope.none) {
|
||||
await source.removeEntries({targetEntry.uri}, includeTrash: true);
|
||||
}
|
||||
EntryDeletedNotification({targetEntry}).dispatch(context);
|
||||
|
|
|
@ -33,7 +33,7 @@ class FakeMediaStoreService extends Fake implements MediaStoreService {
|
|||
}
|
||||
|
||||
@override
|
||||
Stream<AvesEntry> getEntries(bool safe, Map<int?, int?> knownEntries, {String? directory}) => Stream.fromIterable(entries);
|
||||
Stream<AvesEntry> getEntries(Map<int?, int?> knownEntries, {String? directory}) => Stream.fromIterable(entries);
|
||||
|
||||
static var _lastId = 1;
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ void main() {
|
|||
final source = MediaStoreSource();
|
||||
unawaited(source.init());
|
||||
await Future.delayed(const Duration(milliseconds: 10));
|
||||
expect(source.initState, SourceInitializationState.full);
|
||||
expect(source.scope, SourceScope.full);
|
||||
await source.refreshUris({refreshEntry.uri});
|
||||
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
|
|
Loading…
Reference in a new issue