@page "/media/libraries" @using ErsatzTV.Application.Emby @using ErsatzTV.Application.Jellyfin @using ErsatzTV.Application.Libraries @using ErsatzTV.Application.MediaSources @using ErsatzTV.Application.Plex @using ErsatzTV.Core.Metadata @using MediatR.Courier @using PlexLibraryViewModel = ErsatzTV.Application.Libraries.PlexLibraryViewModel @implements IDisposable @inject IMediator Mediator @inject IEntityLocker Locker @inject ChannelWriter ScannerWorkerChannel; @inject ICourier Courier
Libraries @if (_showServerNames) { } Library Kind @if (_showServerNames) { Server Name } Library Name Media Kind @context.LibraryKind @if (_showServerNames) { @context.MediaSourceName } @context.Name @switch (context.MediaKind) { case LibraryMediaKind.MusicVideos: @:Music Videos break; case LibraryMediaKind.OtherVideos: @:Other Videos break; case LibraryMediaKind.RemoteStreams: @:Remote Streams break; default: @(context.MediaKind) break; }
@if (Locker.IsLibraryLocked(context.Id)) {
@if (_progressByLibrary[context.Id] > 0) { @($"{_progressByLibrary[context.Id]} %") }
} else { if (context is PlexLibraryViewModel or EmbyLibraryViewModel or JellyfinLibraryViewModel) { } else {
} }
External Collections @if (_externalCollections.Any()) { Library Kind @context.LibraryKind
@if (AreCollectionsLocked(context.LibraryKind)) {
} else {
}
}
@code { private readonly CancellationTokenSource _cts = new(); private IList _libraries = new List(); private IList _externalCollections = new List(); private Dictionary _progressByLibrary = new(); private bool _showServerNames; protected override void OnInitialized() { Locker.OnLibraryChanged += LockChanged; Locker.OnEmbyCollectionsChanged += LockChanged; Locker.OnJellyfinCollectionsChanged += LockChanged; Locker.OnPlexCollectionsChanged += LockChanged; Courier.Subscribe(HandleScanProgress); } protected override async Task OnParametersSetAsync() => await LoadLibraries(_cts.Token); private async Task LoadLibraries(CancellationToken cancellationToken) { _libraries = await Mediator.Send(new GetConfiguredLibraries(), cancellationToken); _showServerNames = _libraries.Any(l => l is PlexLibraryViewModel); _externalCollections = await Mediator.Send(new GetExternalCollections(), cancellationToken); _progressByLibrary = _libraries.ToDictionary(vm => vm.Id, _ => 0); } private async Task ScanLibrary(LibraryViewModel library, bool deepScan = false) { if (Locker.LockLibrary(library.Id)) { switch (library) { case LocalLibraryViewModel: await ScannerWorkerChannel.WriteAsync(new ForceScanLocalLibrary(library.Id), _cts.Token); break; case PlexLibraryViewModel: await ScannerWorkerChannel.WriteAsync(new SynchronizePlexLibraries(library.MediaSourceId), _cts.Token); await ScannerWorkerChannel.WriteAsync(new ForceSynchronizePlexLibraryById(library.Id, deepScan), _cts.Token); await ScannerWorkerChannel.WriteAsync(new SynchronizePlexNetworks(library.Id, true), _cts.Token); break; case JellyfinLibraryViewModel: await ScannerWorkerChannel.WriteAsync(new SynchronizeJellyfinLibraries(library.MediaSourceId), _cts.Token); await ScannerWorkerChannel.WriteAsync(new ForceSynchronizeJellyfinLibraryById(library.Id, deepScan), _cts.Token); break; case EmbyLibraryViewModel: await ScannerWorkerChannel.WriteAsync(new SynchronizeEmbyLibraries(library.MediaSourceId), _cts.Token); await ScannerWorkerChannel.WriteAsync(new ForceSynchronizeEmbyLibraryById(library.Id, deepScan), _cts.Token); break; } StateHasChanged(); } } private async Task ScanExternalCollections(LibraryViewModel library) { switch (library.LibraryKind.ToLowerInvariant()) { case "emby": if (Locker.LockEmbyCollections()) { await ScannerWorkerChannel.WriteAsync(new SynchronizeEmbyCollections(library.MediaSourceId, true)); } break; case "jellyfin": if (Locker.LockJellyfinCollections()) { await ScannerWorkerChannel.WriteAsync(new SynchronizeJellyfinCollections(library.MediaSourceId, true)); } break; case "plex": if (Locker.LockPlexCollections()) { await ScannerWorkerChannel.WriteAsync(new SynchronizePlexCollections(library.MediaSourceId, true)); } break; } } private void LockChanged(object sender, EventArgs e) => InvokeAsync(StateHasChanged); private bool AreCollectionsLocked(string libraryKind) { switch (libraryKind.ToLowerInvariant()) { case "emby": return Locker.AreEmbyCollectionsLocked(); case "jellyfin": return Locker.AreJellyfinCollectionsLocked(); case "plex": return Locker.ArePlexCollectionsLocked(); } return false; } private async Task HandleScanProgress(LibraryScanProgress libraryScanProgress, CancellationToken cancellationToken) { try { if (_progressByLibrary != null && _progressByLibrary.ContainsKey(libraryScanProgress.LibraryId)) { _progressByLibrary[libraryScanProgress.LibraryId] = (int)(libraryScanProgress.Progress * 100); await InvokeAsync(StateHasChanged); } } catch (Exception) { // ignore } } void IDisposable.Dispose() { Locker.OnLibraryChanged -= LockChanged; Locker.OnEmbyCollectionsChanged -= LockChanged; Locker.OnJellyfinCollectionsChanged -= LockChanged; Locker.OnPlexCollectionsChanged -= LockChanged; Courier.UnSubscribe(HandleScanProgress); _cts.Cancel(); _cts.Dispose(); } }