mirror of
https://github.com/FluxaMedia/fluxa-desktop.git
synced 2026-08-20 05:58:10 +00:00
Delegate desktop sync decisions to core
This commit is contained in:
parent
87d9739956
commit
73b5c5c2ec
3 changed files with 54 additions and 49 deletions
|
|
@ -7,6 +7,7 @@ export const CORE_METHODS = [
|
|||
'addonStoreInputType',
|
||||
'addonStoreSearchPolicy',
|
||||
'addonStreamsWithProvider',
|
||||
'addonUptimeMatchPlan',
|
||||
'airDateRefreshCandidates',
|
||||
'airDateRefreshPlan',
|
||||
'anilistEntriesToSync',
|
||||
|
|
@ -43,11 +44,14 @@ export const CORE_METHODS = [
|
|||
'catalogHasRequiredExtraExcept',
|
||||
'catalogRequiresExtra',
|
||||
'catalogSupportsExtra',
|
||||
'chapterSkipSegments',
|
||||
'classifyMetaLinks',
|
||||
'clearPlaybackProgressItem',
|
||||
'collectionFolderItemsPlan',
|
||||
'collectionMergePlan',
|
||||
'computeContinueWatchingBadges',
|
||||
'contentBaseId',
|
||||
'contentImdbId',
|
||||
'contentMergeKeys',
|
||||
'contentTraktKeysBatch',
|
||||
'contentWatchedKeysBatch',
|
||||
|
|
@ -83,6 +87,8 @@ export const CORE_METHODS = [
|
|||
'episodeTextMatches',
|
||||
'exportCollections',
|
||||
'externalProviderActionPlan',
|
||||
'externalSyncRefreshRetryAction',
|
||||
'externalSyncResponseAction',
|
||||
'extractAddonManifestUrl',
|
||||
'extractAnilistIdFromLinks',
|
||||
'filterDiscoverResults',
|
||||
|
|
@ -92,6 +98,12 @@ export const CORE_METHODS = [
|
|||
'folderPageState',
|
||||
'folderSourcePagePlan',
|
||||
'formatEpisodeLine',
|
||||
'homeBillboardCandidateScore',
|
||||
'homeBillboardEditorialMatchScore',
|
||||
'homeBillboardHasBackdrop',
|
||||
'homeBillboardIdentityKey',
|
||||
'homeBillboardNormalizedTitle',
|
||||
'homeBillboardVisualScore',
|
||||
'homeHeroPlan',
|
||||
'homeOverlapRatio',
|
||||
'homePersonalizationScore',
|
||||
|
|
@ -99,6 +111,7 @@ export const CORE_METHODS = [
|
|||
'importCollections',
|
||||
'isEpisodeReleased',
|
||||
'isSecureRemoteUrl',
|
||||
'isTmdbLikeContentId',
|
||||
'isUpNextContinueWatchingItem',
|
||||
'itemListDiff',
|
||||
'itemListNewEntries',
|
||||
|
|
@ -112,6 +125,8 @@ export const CORE_METHODS = [
|
|||
'librarySortPlan',
|
||||
'libraryViewPlan',
|
||||
'libraryWatchlistItems',
|
||||
'malWatchedUpdate',
|
||||
'malWatchlistUpdate',
|
||||
'manifestCandidates',
|
||||
'manifestFetchDecision',
|
||||
'manifestFetchPlan',
|
||||
|
|
@ -142,15 +157,22 @@ export const CORE_METHODS = [
|
|||
'normalizeLibraryDocument',
|
||||
'normalizeManifestUrl',
|
||||
'normalizePluginRepositoryUrl',
|
||||
'normalizeSeriesLookupId',
|
||||
'normalizeTrailerSubtitleUrl',
|
||||
'nuvioAddonReconciliationPlan',
|
||||
'nuvioAddonState',
|
||||
'nuvioBuildLocalProfiles',
|
||||
'nuvioCollectionRequest',
|
||||
'nuvioExportPushPlan',
|
||||
'nuvioImportMergePlan',
|
||||
'nuvioLibraryItemRequest',
|
||||
'nuvioLibraryMutationPlan',
|
||||
'nuvioLibraryToWatchlist',
|
||||
'nuvioMapCollections',
|
||||
'nuvioPlaybackProgressRequest',
|
||||
'nuvioProgressMetaNeeds',
|
||||
'nuvioSortAddonsByPriority',
|
||||
'nuvioWatchedItemsRequest',
|
||||
'offlineDownloadPlan',
|
||||
'optimizeHomeRows',
|
||||
'orderStreamsPlan',
|
||||
|
|
@ -160,6 +182,8 @@ export const CORE_METHODS = [
|
|||
'parseAndPlanAddonResource',
|
||||
'parseAnimeSkipResults',
|
||||
'parseAniskipResults',
|
||||
'parseCatalogItems',
|
||||
'parseDirectStreams',
|
||||
'parseEpisodeLocator',
|
||||
'parseExtraArgs',
|
||||
'parseIntroDbSegments',
|
||||
|
|
@ -188,6 +212,7 @@ export const CORE_METHODS = [
|
|||
'playerShouldSendScrobbleStart',
|
||||
'playerSourceSidebarPlan',
|
||||
'playerTrackState',
|
||||
'pluginExecutionPlan',
|
||||
'pluginManifestParse',
|
||||
'pluginStreamResultsParse',
|
||||
'pluginStreamResultsToStreams',
|
||||
|
|
@ -245,6 +270,7 @@ export const CORE_METHODS = [
|
|||
'selectStreamIndex',
|
||||
'setMetadataFeedGroupEnabled',
|
||||
'shouldAttemptAnimeTracking',
|
||||
'simklHistoryRequest',
|
||||
'simklLookupIdForType',
|
||||
'simklMarkWatchedBody',
|
||||
'simklMatchEpisode',
|
||||
|
|
@ -255,6 +281,8 @@ export const CORE_METHODS = [
|
|||
'simklWatchedToIds',
|
||||
'simklWatchingToItems',
|
||||
'simklWatchlistBody',
|
||||
'simklWatchlistRemovalRequest',
|
||||
'simklWatchlistRequest',
|
||||
'simklWatchlistToItems',
|
||||
'stableFeedPart',
|
||||
'streamDiscoveryCacheKey',
|
||||
|
|
@ -284,6 +312,7 @@ export const CORE_METHODS = [
|
|||
'tmdbImageUrl',
|
||||
'tmdbLanguage',
|
||||
'tmdbMetaToMeta',
|
||||
'tmdbNumericId',
|
||||
'tmdbPeopleImagesFromCredits',
|
||||
'tmdbPeopleRequestPlan',
|
||||
'tmdbResolveIdHint',
|
||||
|
|
@ -304,6 +333,7 @@ export const CORE_METHODS = [
|
|||
'traktIdsFromContentId',
|
||||
'traktMarkWatchedBody',
|
||||
'traktOAuthErrorCode',
|
||||
'traktPlaybackDeleteIds',
|
||||
'traktPlaybackItemsDedup',
|
||||
'traktPlaybackItemsToLibrary',
|
||||
'traktPlaybackUrl',
|
||||
|
|
@ -313,6 +343,7 @@ export const CORE_METHODS = [
|
|||
'traktScrobblePlan',
|
||||
'traktScrobbleUrl',
|
||||
'traktShowIdFromEpisodeId',
|
||||
'traktSyncItemToMeta',
|
||||
'traktTokenExpiresAt',
|
||||
'traktWatchedToIds',
|
||||
'traktWatchlistToItems',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { coreInvoke } from './engine';
|
||||
|
||||
export interface NuvioSession {
|
||||
access_token: string;
|
||||
|
|
@ -285,38 +286,25 @@ export async function nuvioReplaceAddons(
|
|||
addons: Array<{ url: string; name?: string; enabled?: boolean; sort_order?: number }>,
|
||||
): Promise<void> {
|
||||
const current = await nuvioPullAddons(token, profileId);
|
||||
const desiredByUrl = new Map(addons.map((addon, index) => [addon.url, {
|
||||
url: addon.url,
|
||||
name: addon.name ?? null,
|
||||
enabled: addon.enabled ?? true,
|
||||
sort_order: addon.sort_order ?? index,
|
||||
}]));
|
||||
const plan = await coreInvoke<{
|
||||
deleteIds: string[];
|
||||
updates: Array<{ id: string; payload: Record<string, unknown> }>;
|
||||
creates: Record<string, unknown>[];
|
||||
}>('nuvioAddonReconciliationPlan', JSON.stringify({ current, desired: addons, userId, profileId }));
|
||||
if (!plan) return;
|
||||
|
||||
await Promise.all(current
|
||||
.filter((addon) => !desiredByUrl.has(addon.url))
|
||||
.map((addon) => nuvioRequest<void>(
|
||||
await Promise.all(plan.deleteIds.map((id) => nuvioRequest<void>(
|
||||
'DELETE',
|
||||
`/rest/v1/addons?id=eq.${encodeURIComponent(addon.id)}&profile_id=eq.${profileId}`,
|
||||
`/rest/v1/addons?id=eq.${encodeURIComponent(id)}&profile_id=eq.${profileId}`,
|
||||
undefined,
|
||||
token,
|
||||
)));
|
||||
|
||||
await Promise.all([...desiredByUrl.values()].map(async (addon) => {
|
||||
const existing = current.find((candidate) => candidate.url === addon.url);
|
||||
if (existing) {
|
||||
await patch<void>(
|
||||
`/rest/v1/addons?id=eq.${encodeURIComponent(existing.id)}&profile_id=eq.${profileId}`,
|
||||
addon,
|
||||
token,
|
||||
);
|
||||
} else {
|
||||
await post<void>('/rest/v1/addons', {
|
||||
user_id: userId,
|
||||
profile_id: profileId,
|
||||
...addon,
|
||||
}, token);
|
||||
}
|
||||
}));
|
||||
await Promise.all(plan.updates.map(({ id, payload }) => patch<void>(
|
||||
`/rest/v1/addons?id=eq.${encodeURIComponent(id)}&profile_id=eq.${profileId}`,
|
||||
payload,
|
||||
token,
|
||||
)));
|
||||
await Promise.all(plan.creates.map((payload) => post<void>('/rest/v1/addons', payload, token)));
|
||||
}
|
||||
|
||||
export async function nuvioPullPlugins(token: string, profileId: number): Promise<unknown[]> {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { platformFetch } from './httpClient';
|
||||
import { loadActiveProfile } from './libraryOps';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { coreInvoke } from './engine';
|
||||
|
||||
export async function getOAuthClientId(service: string): Promise<string> {
|
||||
try {
|
||||
|
|
@ -35,28 +36,13 @@ export async function dropTraktPlaybackProgress(showId: string): Promise<void> {
|
|||
const playbackItems = await res.json() as unknown[];
|
||||
if (!Array.isArray(playbackItems)) return;
|
||||
|
||||
const deletePromises: Promise<void>[] = [];
|
||||
for (const raw of playbackItems) {
|
||||
const entry = raw as Record<string, unknown>;
|
||||
const traktNumericId = typeof entry.id === 'number' ? entry.id : null;
|
||||
if (!traktNumericId) continue;
|
||||
|
||||
const show = entry.show as Record<string, unknown> | undefined;
|
||||
const movie = entry.movie as Record<string, unknown> | undefined;
|
||||
const source = show ?? movie;
|
||||
const ids = source?.ids as Record<string, unknown> | undefined;
|
||||
const imdb = typeof ids?.imdb === 'string' ? ids.imdb : null;
|
||||
const tmdb = ids?.tmdb != null ? `tmdb:${ids.tmdb}` : null;
|
||||
|
||||
if (imdb === showId || tmdb === showId) {
|
||||
deletePromises.push(
|
||||
platformFetch(`https://api.trakt.tv/sync/playback/${traktNumericId}`, {
|
||||
method: 'DELETE',
|
||||
headers,
|
||||
}).then(() => undefined).catch(() => undefined),
|
||||
);
|
||||
}
|
||||
}
|
||||
const deleteIds = await coreInvoke<number[]>('traktPlaybackDeleteIds', JSON.stringify({ contentId: showId, items: playbackItems })) ?? [];
|
||||
const deletePromises = deleteIds.map((id) =>
|
||||
platformFetch(`https://api.trakt.tv/sync/playback/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers,
|
||||
}).then(() => undefined).catch(() => undefined),
|
||||
);
|
||||
|
||||
await Promise.all(deletePromises);
|
||||
} catch {
|
||||
|
|
|
|||
Loading…
Reference in a new issue