From bc55aea701dca3ccd4f55705cae9eec5eab391e8 Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Sun, 12 Jul 2026 01:25:55 +0200 Subject: [PATCH] refactor: remove superseded code paths --- lib/database/download_operations.dart | 33 +++---- lib/providers/download_provider.dart | 35 -------- lib/screens/media_detail_screen.dart | 8 -- .../companion_remote_peer_service.dart | 85 ------------------- .../lan_discovery_service.dart | 45 ---------- lib/services/multi_server_manager.dart | 16 ---- lib/services/plex_auth_service.dart | 36 -------- lib/services/plex_client.dart | 53 ------------ lib/services/plex_client/parts/live_tv.dart | 16 ---- windows/runner/mpv/display_mode_manager.cpp | 45 ---------- windows/runner/mpv/display_mode_manager.h | 7 -- 11 files changed, 14 insertions(+), 365 deletions(-) diff --git a/lib/database/download_operations.dart b/lib/database/download_operations.dart index 8001e032..08a2038a 100644 --- a/lib/database/download_operations.dart +++ b/lib/database/download_operations.dart @@ -22,11 +22,6 @@ extension DownloadDatabaseOperations on AppDatabase { await (delete(downloadOwners)..where((t) => t.profileId.equals(profileId) & t.globalKey.equals(globalKey))).go(); } - Future removeDownloadOwnersForProfile(String profileId) async { - if (profileId.isEmpty) return; - await (delete(downloadOwners)..where((t) => t.profileId.equals(profileId))).go(); - } - Future clearAllDownloadOwners() async { await delete(downloadOwners).go(); } @@ -59,12 +54,7 @@ extension DownloadDatabaseOperations on AppDatabase { final connectionRows = await select(connections).get(); final connectionIds = connectionRows.map((row) => row.id).toSet(); return candidates - .where((row) { - if (localProfileIds.contains(row.profileId)) return true; - final plexHome = parsePlexHomeProfileId(row.profileId); - if (plexHome != null) return connectionIds.contains(plexHome.accountConnectionId); - return localProfileIds.isEmpty; - }) + .where((row) => _isValidDownloadOwner(row, localProfileIds: localProfileIds, connectionIds: connectionIds)) .toList(growable: false); } @@ -83,16 +73,10 @@ extension DownloadDatabaseOperations on AppDatabase { final owners = await select(downloadOwners).get(); final localProfileIds = (await select(profiles).get()).map((row) => row.id).toSet(); final connectionIds = (await select(connections).get()).map((row) => row.id).toSet(); - bool valid(DownloadOwnerItem owner) { - if (localProfileIds.contains(owner.profileId)) return true; - final plexHome = parsePlexHomeProfileId(owner.profileId); - if (plexHome != null) return connectionIds.contains(plexHome.accountConnectionId); - return localProfileIds.isEmpty; - } - final ownedKeys = { for (final owner in owners) - if (valid(owner)) owner.globalKey, + if (_isValidDownloadOwner(owner, localProfileIds: localProfileIds, connectionIds: connectionIds)) + owner.globalKey, }; for (final row in rows) { if (!ownedKeys.contains(row.globalKey)) { @@ -333,3 +317,14 @@ extension DownloadDatabaseOperations on AppDatabase { return item?.bgTaskId; } } + +bool _isValidDownloadOwner( + DownloadOwnerItem owner, { + required Set localProfileIds, + required Set connectionIds, +}) { + if (localProfileIds.contains(owner.profileId)) return true; + final plexHome = parsePlexHomeProfileId(owner.profileId); + if (plexHome != null) return connectionIds.contains(plexHome.accountConnectionId); + return localProfileIds.isEmpty; +} diff --git a/lib/providers/download_provider.dart b/lib/providers/download_provider.dart index fda54253..fe6145fd 100644 --- a/lib/providers/download_provider.dart +++ b/lib/providers/download_provider.dart @@ -198,31 +198,6 @@ class DownloadProvider extends ChangeNotifier with DisposableChangeNotifierMixin await _releaseDownloadsForProfileWhere(profileId, (_) => true); } - Future deleteAllDownloads() async { - final downloads = await _downloadManager.getAllDownloads(); - for (final row in downloads) { - await _downloadManager.deleteDownload(row.globalKey); - } - await _database.clearAllDownloadOwners(); - - try { - final artworkDirectory = await DownloadStorageService.instance.getArtworkDirectory(); - if (await artworkDirectory.exists()) { - await artworkDirectory.delete(recursive: true); - } - } catch (e, stackTrace) { - appLogger.w('Failed to delete shared download artwork directory', error: e, stackTrace: stackTrace); - } - - _downloads.clear(); - _metadata.clear(); - _artworkPaths.clear(); - _queueing.clear(); - _ownedDownloadKeys.clear(); - _deletionProgress.clear(); - safeNotifyListeners(); - } - /// Preserve physical downloads across a full logout while detaching them /// from profiles that are about to be deleted. The next selected profile /// adopts the ownerless rows through [_loadDownloadOwners]. @@ -1695,16 +1670,6 @@ class DownloadProvider extends ChangeNotifier with DisposableChangeNotifierMixin return buildProfileScopedGlobalKey(owner, ServerId(serverId), ratingKey); } - String syncRuleKeyForGlobalKey(String globalKey) { - final scoped = parseProfileScopedGlobalKey(globalKey); - if (scoped != null) { - return syncRuleKeyFor(scoped.serverId, scoped.ratingKey, profileId: scoped.profileId); - } - final parsed = parseGlobalKey(globalKey); - if (parsed == null) return globalKey; - return syncRuleKeyFor(parsed.serverId, parsed.ratingKey); - } - String syncRuleKeyForClient(MediaServerClient client, String ratingKey, {ServerId? serverId}) { return syncRuleKeyFor(serverId ?? client.serverId, ratingKey); } diff --git a/lib/screens/media_detail_screen.dart b/lib/screens/media_detail_screen.dart index d6628d4c..92d158fe 100644 --- a/lib/screens/media_detail_screen.dart +++ b/lib/screens/media_detail_screen.dart @@ -178,14 +178,6 @@ class _SeasonEpisodePager { } } - void updateEpisode(String seasonId, int index, MediaItem updated) { - final state = _states[seasonId]; - if (state == null || index < 0 || index >= state.items.length) return; - final next = List.of(state.items); - next[index] = updated; - _states[seasonId] = state.replaceItems(next); - } - void patchEpisode(String episodeId, MediaItem Function(MediaItem existing) patch) { for (final entry in _states.entries.toList()) { var changed = false; diff --git a/lib/services/companion_remote/companion_remote_peer_service.dart b/lib/services/companion_remote/companion_remote_peer_service.dart index 47c0af97..1dcffbb6 100644 --- a/lib/services/companion_remote/companion_remote_peer_service.dart +++ b/lib/services/companion_remote/companion_remote_peer_service.dart @@ -110,29 +110,6 @@ class CompanionRemotePeerService with KeepaliveMixin { } } - /// Create a host session — starts WebSocket server, returns local addresses and port. - Future<({List addresses, int port})> createSession( - String deviceName, - String platform, - List homeSecret, - String clientIdentifier, - List homeUserUUIDs, - ) async { - final auth = RemoteAuthService.instance; - return createSessionForContexts(deviceName, platform, [ - RemoteAuthContext( - id: auth.computeAuthContextId(homeSecret), - backend: 'legacy', - connectionId: '', - homeSecret: homeSecret, - discoveryKey: const [], - clientIdentifier: clientIdentifier, - userUuid: homeUserUUIDs.isEmpty ? '' : homeUserUUIDs.first, - allowedUserUuids: homeUserUUIDs, - ), - ]); - } - /// Create a host session that accepts any of the provided remote identities. Future<({List addresses, int port})> createSessionForContexts( String deviceName, @@ -425,37 +402,6 @@ class CompanionRemotePeerService with KeepaliveMixin { } } - /// Join a host session as a remote client. - Future joinSession( - String deviceName, - String platform, - String hostAddress, - List homeSecret, - String hostClientId, - String userUUID, - String clientIdentifier, - ) async { - final auth = RemoteAuthService.instance; - final context = RemoteAuthContext( - id: auth.computeAuthContextId(homeSecret), - backend: 'legacy', - connectionId: '', - homeSecret: homeSecret, - discoveryKey: const [], - clientIdentifier: clientIdentifier, - userUuid: userUUID, - allowedUserUuids: [userUUID], - ); - return joinSessionWithContexts( - deviceName, - platform, - hostAddress, - [context], - authContextId: context.id, - expectedHostClientId: hostClientId, - ); - } - /// Join a host session with any local auth context that the host also supports. Future joinSessionWithContexts( String deviceName, @@ -720,37 +666,6 @@ class CompanionRemotePeerService with KeepaliveMixin { ); } - /// Race WebSocket connections to multiple host addresses in parallel. - Future joinSessionRacing( - String deviceName, - String platform, - List hostAddresses, - List homeSecret, - String hostClientId, - String userUUID, - String clientIdentifier, - ) async { - final auth = RemoteAuthService.instance; - final context = RemoteAuthContext( - id: auth.computeAuthContextId(homeSecret), - backend: 'legacy', - connectionId: '', - homeSecret: homeSecret, - discoveryKey: const [], - clientIdentifier: clientIdentifier, - userUuid: userUUID, - allowedUserUuids: [userUUID], - ); - return joinSessionRacingWithContexts( - deviceName, - platform, - hostAddresses, - [context], - authContextId: context.id, - expectedHostClientId: hostClientId, - ); - } - /// Race WebSocket connections and authenticate with the selected shared identity. Future joinSessionRacingWithContexts( String deviceName, diff --git a/lib/services/companion_remote/lan_discovery_service.dart b/lib/services/companion_remote/lan_discovery_service.dart index fe9841ba..c379a410 100644 --- a/lib/services/companion_remote/lan_discovery_service.dart +++ b/lib/services/companion_remote/lan_discovery_service.dart @@ -59,34 +59,6 @@ class LanDiscoveryService { // ── Host: Broadcasting ── - Future startBroadcasting({ - required List discoveryKey, - required String deviceName, - required String platform, - required String clientId, - required int wsPort, - required List ips, - }) async { - return startBroadcastingForContexts( - contexts: [ - RemoteAuthContext( - id: clientId, - backend: 'legacy', - connectionId: clientId, - homeSecret: const [], - discoveryKey: discoveryKey, - clientIdentifier: clientId, - userUuid: '', - allowedUserUuids: const [], - ), - ], - deviceName: deviceName, - platform: platform, - wsPort: wsPort, - ips: ips, - ); - } - Future startBroadcastingForContexts({ required List contexts, required String deviceName, @@ -168,23 +140,6 @@ class LanDiscoveryService { // ── Client: Listening ── - /// Start listening for host beacons. - /// Returns a stream of currently-visible hosts, updated on each beacon or stale cleanup. - Stream> startListening({required List discoveryKey}) { - return startListeningForContexts([ - RemoteAuthContext( - id: '', - backend: 'legacy', - connectionId: '', - homeSecret: const [], - discoveryKey: discoveryKey, - clientIdentifier: '', - userUuid: '', - allowedUserUuids: const [], - ), - ]); - } - Stream> startListeningForContexts(List contexts) { _stopListeningInternal(); _discoveredHosts.clear(); diff --git a/lib/services/multi_server_manager.dart b/lib/services/multi_server_manager.dart index b5fa62fd..0ec91eba 100644 --- a/lib/services/multi_server_manager.dart +++ b/lib/services/multi_server_manager.dart @@ -528,22 +528,6 @@ class MultiServerManager { return bound; } - /// Tear down all servers belonging to the given Plex account. Called when - /// the user removes the account from the Connections screen. Idempotent — - /// servers already gone are silently skipped. - void removePlexAccount(PlexAccountConnection connection) { - for (final server in connection.servers) { - final id = server.clientIdentifier; - final client = _clients.remove(id); - if (client != null) _closeClient(client); - _plexServers.remove(id); - _serverStatus.remove(id); - _authErrorServers.remove(id); - _clientIdByServer.remove(id); - } - _statusController.add(Map.from(_serverStatus)); - } - /// Add a Jellyfin server backed by an authenticated [JellyfinConnection]. /// Returns true on success. /// diff --git a/lib/services/plex_auth_service.dart b/lib/services/plex_auth_service.dart index 6766b9b3..54e8643a 100644 --- a/lib/services/plex_auth_service.dart +++ b/lib/services/plex_auth_service.dart @@ -769,42 +769,6 @@ class PlexServer { return _ConnectionCandidate(httpsConnection, httpsUrl, resultingIsPlexDirect, true); } - Future upgradeConnectionToHttps(PlexConnection current) async { - if (current.uri.startsWith('https://')) { - return current; - } - - final baseConnection = _findMatchingBaseConnection(current); - if (baseConnection == null) { - return null; - } - - final candidate = _ConnectionCandidate( - baseConnection, - current.uri, - current.uri.contains('.plex.direct'), - current.uri.startsWith('https://'), - ); - final upgradedCandidate = await _upgradeCandidateToHttpsIfPossible(candidate); - if (upgradedCandidate == null) { - return null; - } - return _updateConnectionUrl(upgradedCandidate.connection, upgradedCandidate.url); - } - - PlexConnection? _findMatchingBaseConnection(PlexConnection connection) { - for (final base in connections) { - final sameAddress = base.address == connection.address; - final samePort = base.port == connection.port; - final sameLocal = base.local == connection.local; - final sameRelay = base.relay == connection.relay; - if (sameAddress && samePort && sameLocal && sameRelay) { - return base; - } - } - return null; - } - /// Select the best candidate considering priority, latency, and URL type preference _ConnectionCandidate? _selectBestCandidateWithLatency(Map<_ConnectionCandidate, ConnectionTestResult> results) { // Group candidates by connection type (local/remote/relay) diff --git a/lib/services/plex_client.dart b/lib/services/plex_client.dart index e3509972..a982a66f 100644 --- a/lib/services/plex_client.dart +++ b/lib/services/plex_client.dart @@ -2083,11 +2083,6 @@ class PlexClient Future<_LibraryContentResult> _getPlaylist(String playlistId, {int? start, int? size, AbortController? abort}) => _fetchPaginatedList('/playlists/$playlistId/items', start: start, size: size, abort: abort); - /// Fetch every page of a playlist's items. For callers that need the full list - /// (downloads, sync rules, context-menu shuffle). - Future> _fetchAllPlaylistItemsDto(String playlistId) => - _fetchAllPages((start, size, abort) => _getPlaylist(playlistId, start: start, size: size, abort: abort)); - /// Get all playlists. /// Filters by playlistType=video by default. /// Set smart to true/false to filter smart playlists, or null for all. @@ -2509,22 +2504,6 @@ class PlexClient librarySectionTitle: librarySectionTitle, ); - /// Fetch every item in a collection (downloads, sync rules, context-menu shuffle). - Future> _fetchAllCollectionItemsDto( - String collectionId, { - String? librarySectionID, - String? librarySectionTitle, - }) => _fetchAllPages( - (start, size, abort) => _getCollectionItems( - collectionId, - start: start, - size: size, - abort: abort, - librarySectionID: librarySectionID, - librarySectionTitle: librarySectionTitle, - ), - ); - /// Get media featuring a specific person (actor/director), paginated. Future<_LibraryContentResult> _getPersonMedia(String personId, {int? start, int? size, AbortController? abort}) => _fetchPaginatedList('/library/people/$personId/media', start: start, size: size, abort: abort); @@ -2941,12 +2920,6 @@ class PlexClient /// Get library-specific playlists /// Filters playlists by checking if they contain items from the specified library /// This is a client-side filter since the API doesn't support sectionId for playlists - Future> _getLibraryPlaylists({String playlistType = 'video'}) { - // For now, return all video playlists - // Future enhancement: filter by checking playlist items' library - return _getPlaylists(playlistType: playlistType); - } - /// Scan/refresh a library section to detect new files Future scanLibrary(String sectionId) async { await _getWithFailover('/library/sections/$sectionId/refresh'); @@ -4213,26 +4186,6 @@ class PlexClient ); } - /// Plex-specific: full collection contents across pages. - Future> fetchAllCollectionItemsAsMediaItems( - String collectionId, { - String? libraryId, - String? libraryTitle, - }) async { - final raw = await _fetchAllCollectionItemsDto( - collectionId, - librarySectionID: libraryId, - librarySectionTitle: libraryTitle, - ); - return raw.map((m) => PlexMappers.mediaItem(m)).toList(); - } - - /// Plex-specific: full playlist contents across pages. - Future> fetchAllPlaylistItemsAsMediaItems(String playlistId) async { - final raw = await _fetchAllPlaylistItemsDto(playlistId); - return raw.map((m) => PlexMappers.mediaItem(m)).toList(); - } - @override Future> fetchPersonMediaPage( String personId, { @@ -4330,12 +4283,6 @@ class PlexClient return raw.map((m) => PlexMappers.mediaItem(m)).toList(); } - /// Plex-specific: library-scoped playlists. - Future> fetchLibraryPlaylists({String playlistType = 'video'}) async { - final raw = await _getLibraryPlaylists(playlistType: playlistType); - return raw.map((p) => PlexMappers.mediaPlaylist(p)).toList(); - } - /// Plex-specific: paginated library content with raw Plex filter map, /// returning neutral [MediaItem]s. The aggregation bridge uses this when it /// has Plex-specific filter strings (`unwatched=1`, `genre=...`) to forward. diff --git a/lib/services/plex_client/parts/live_tv.dart b/lib/services/plex_client/parts/live_tv.dart index b763177f..c8b4d357 100644 --- a/lib/services/plex_client/parts/live_tv.dart +++ b/lib/services/plex_client/parts/live_tv.dart @@ -28,7 +28,6 @@ mixin _PlexLiveTvClientMethods on MediaServerCacheMixin { Map? _getMediaContainer(MediaServerResponse response); PlexMetadataDto _createTaggedMetadata(Map json); - List _extractMetadataList(MediaServerResponse response); Future> _wrapListApiCall( Future Function() apiCall, @@ -1061,15 +1060,6 @@ mixin _PlexLiveTvClientMethods on MediaServerCacheMixin { return '${config.baseUrl}$streamPath'.withPlexToken(config.token); } - /// Get active live TV sessions - Future> _getLiveTvSessions() { - return _wrapListApiCall( - () => _http.get('/livetv/sessions'), - _extractMetadataList, - 'Failed to get live TV sessions', - ); - } - Future> getLiveTvSessionsDetailed() async { final response = await _getWithFailover('/livetv/sessions'); return _extractContainerList(response, const [ @@ -1153,12 +1143,6 @@ mixin _PlexLiveTvClientMethods on MediaServerCacheMixin { } } - /// Plex-specific: live TV sessions (active recordings/playback). - Future> fetchLiveTvSessions() async { - final raw = await _getLiveTvSessions(); - return raw.map((m) => PlexMappers.mediaItem(m)).toList(); - } - @override LiveTvSupport get liveTv => _PlexLiveTvSupport(this as PlexClient); } diff --git a/windows/runner/mpv/display_mode_manager.cpp b/windows/runner/mpv/display_mode_manager.cpp index 140656f8..871364ff 100644 --- a/windows/runner/mpv/display_mode_manager.cpp +++ b/windows/runner/mpv/display_mode_manager.cpp @@ -533,49 +533,4 @@ bool DisplayModeManager::RecoverIfNeeded(HWND window) { return recovered; } -// --- Refresh rate matching --- - -DWORD DisplayModeManager::FindBestRefreshRate( - double video_fps, const std::vector& modes, DWORD current_width, DWORD current_height) { - if (video_fps <= 0) return 0; - - // Collect unique refresh rates available at the current resolution. - std::vector rates; - for (const auto& mode : modes) { - if (mode.width == current_width && mode.height == current_height) { - if (std::find(rates.begin(), rates.end(), mode.refresh_rate) == rates.end()) { - rates.push_back(mode.refresh_rate); - } - } - } - - if (rates.empty()) return 0; - - DWORD best_rate = 0; - int best_multiplier = 0; - - for (DWORD rate : rates) { - double ratio = static_cast(rate) / video_fps; - double rounded = std::round(ratio); - - // Must be a positive integer multiple (1x, 2x, 3x, ...). - if (rounded < 1.0) continue; - - int multiplier = static_cast(rounded); - double deviation = std::abs(ratio - rounded) / rounded; - - // Within 0.5% tolerance (covers 23.976 -> 24Hz, 29.97 -> 30Hz, etc.). - if (deviation > 0.005) continue; - - // Prefer lowest multiplier (exact match > 2x > 3x > ...). - // Among equal multipliers, prefer higher rate (shouldn't happen, but safe). - if (best_rate == 0 || multiplier < best_multiplier || (multiplier == best_multiplier && rate > best_rate)) { - best_rate = rate; - best_multiplier = multiplier; - } - } - - return best_rate; -} - } // namespace mpv diff --git a/windows/runner/mpv/display_mode_manager.h b/windows/runner/mpv/display_mode_manager.h index 657965fb..f13b747c 100644 --- a/windows/runner/mpv/display_mode_manager.h +++ b/windows/runner/mpv/display_mode_manager.h @@ -98,13 +98,6 @@ class DisplayModeManager { // Should be called early in app startup. Returns true if recovery was performed. static bool RecoverIfNeeded(HWND window); - // --- Refresh rate matching --- - - // Find the best matching refresh rate for a given video fps from available modes. - // Returns 0 if no suitable match found. - static DWORD FindBestRefreshRate( - double video_fps, const std::vector& modes, DWORD current_width, DWORD current_height); - private: // Get the GDI device name for the monitor containing the window. static std::wstring GetMonitorDeviceName(HWND window);