|
18 | 18 | type AmbiguousImportItem, |
19 | 19 | DEFAULT_IMPORT_SOURCE, |
20 | 20 | IMPORT_SOURCE_CONFIGS, |
| 21 | + type ImportAction, |
| 22 | + type ImportActionSelection, |
21 | 23 | type ImportCounts, |
22 | 24 | type ImportSource, |
23 | 25 | type ImportSourceConfig, |
24 | 26 | type ImportStatus, |
25 | 27 | type UniversalImportItem, |
26 | 28 | } from "../import/ImportTypes.ts"; |
| 29 | + import { filterImportItemsByActionSelection } from "../import/filterImportItemsByActionSelection.ts"; |
27 | 30 | import { getParser } from "../import/parsers/getParser.ts"; |
28 | 31 | import { syncToTrakt } from "../import/syncToTrakt.ts"; |
29 | 32 | import type { SyncState } from "../sync/models/SyncState.ts"; |
|
40 | 43 | return DEFAULT_IMPORT_SOURCE; |
41 | 44 | } |
42 | 45 |
|
| 46 | + function defaultSelectedActions(): ImportActionSelection { |
| 47 | + return { |
| 48 | + history: true, |
| 49 | + watchlist: true, |
| 50 | + ratings: true, |
| 51 | + }; |
| 52 | + } |
| 53 | +
|
43 | 54 | const { importInProgress } = useImportInProgress(); |
44 | 55 | const { invalidate } = useInvalidator(); |
45 | 56 | const { record } = useAnalytics(); |
|
48 | 59 |
|
49 | 60 | type ImportUIState = SyncState<ImportStatus> & { |
50 | 61 | selectedSource: ImportSource; |
| 62 | + selectedActions: ImportActionSelection; |
51 | 63 | parsedItems: ReadonlyArray<UniversalImportItem>; |
52 | 64 | errorCount: number; |
53 | 65 | unresolved: ReadonlyArray<UniversalImportItem>; |
|
59 | 71 |
|
60 | 72 | const state = $state<ImportUIState>({ |
61 | 73 | selectedSource: DEFAULT_IMPORT_SOURCE, |
| 74 | + selectedActions: defaultSelectedActions(), |
62 | 75 | status: "idle", |
63 | 76 | parsedItems: [], |
64 | 77 | processedCount: 0, |
|
76 | 89 | watchlist: state.parsedItems.filter((i) => i.action === "watchlist").length, |
77 | 90 | ratings: state.parsedItems.filter((i) => i.action === "ratings").length, |
78 | 91 | }); |
| 92 | + const selectedItems = $derived( |
| 93 | + filterImportItemsByActionSelection({ |
| 94 | + items: state.parsedItems, |
| 95 | + selectedActions: state.selectedActions, |
| 96 | + }), |
| 97 | + ); |
| 98 | + const selectedCounts = $derived<ImportCounts>({ |
| 99 | + history: state.selectedActions.history ? counts.history : 0, |
| 100 | + watchlist: state.selectedActions.watchlist ? counts.watchlist : 0, |
| 101 | + ratings: state.selectedActions.ratings ? counts.ratings : 0, |
| 102 | + }); |
| 103 | + const selectedTotalCount = $derived(selectedItems.length); |
79 | 104 |
|
80 | 105 | const sourceConfig = $derived(IMPORT_SOURCE_CONFIGS[state.selectedSource]); |
81 | 106 | const isGuideCollapsed = $derived( |
|
94 | 119 | const parser = getParser(state.selectedSource); |
95 | 120 |
|
96 | 121 | state.parseError = null; |
| 122 | + state.selectedActions = defaultSelectedActions(); |
97 | 123 | state.status = "parsing"; |
98 | 124 |
|
99 | 125 | try { |
|
126 | 152 | } |
127 | 153 |
|
128 | 154 | async function startImport() { |
| 155 | + const itemsToImport = selectedItems; |
| 156 | + const countsToImport = selectedCounts; |
| 157 | + const totalToImport = selectedTotalCount; |
| 158 | + if (totalToImport === 0) return; |
| 159 | +
|
129 | 160 | abortController = new AbortController(); |
130 | 161 | const startTime = Date.now(); |
131 | 162 | state.processedCount = 0; |
|
136 | 167 |
|
137 | 168 | try { |
138 | 169 | const { errorCount, unresolved, ambiguous } = await syncToTrakt( |
139 | | - state.parsedItems, |
| 170 | + itemsToImport, |
140 | 171 | { |
141 | 172 | signal: abortController.signal, |
142 | 173 | onMatchProgress: (processed, total) => { |
|
160 | 191 | ); |
161 | 192 |
|
162 | 193 | const duration = Date.now() - startTime; |
163 | | - const successCount = state.totalCount - errorCount - unresolved.length - |
| 194 | + const successCount = totalToImport - errorCount - unresolved.length - |
164 | 195 | ambiguous.length; |
165 | 196 |
|
166 | 197 | state.errorCount = errorCount; |
|
169 | 200 |
|
170 | 201 | record(AnalyticsEvent.ImportCompleted, { |
171 | 202 | source: state.selectedSource, |
172 | | - totalItems: state.totalCount, |
173 | | - historyCount: counts.history, |
174 | | - watchlistCount: counts.watchlist, |
175 | | - ratingsCount: counts.ratings, |
| 203 | + totalItems: totalToImport, |
| 204 | + historyCount: countsToImport.history, |
| 205 | + watchlistCount: countsToImport.watchlist, |
| 206 | + ratingsCount: countsToImport.ratings, |
176 | 207 | successCount, |
177 | 208 | failedCount: errorCount, |
178 | 209 | unresolvedCount: unresolved.length, |
|
222 | 253 | function reset() { |
223 | 254 | abortController?.abort(); |
224 | 255 | state.status = "idle"; |
| 256 | + state.selectedActions = defaultSelectedActions(); |
225 | 257 | state.parsedItems = []; |
226 | 258 | state.processedCount = 0; |
227 | 259 | state.errorCount = 0; |
|
258 | 290 | return config.name; |
259 | 291 | } |
260 | 292 | }; |
| 293 | +
|
| 294 | + function onActionChange(action: ImportAction, isIncluded: boolean) { |
| 295 | + state.selectedActions = { |
| 296 | + ...state.selectedActions, |
| 297 | + [action]: isIncluded, |
| 298 | + }; |
| 299 | + } |
261 | 300 | </script> |
262 | 301 |
|
263 | 302 | {#snippet importRow()} |
|
283 | 322 | {:else if state.status === "review"} |
284 | 323 | <ImportSummary |
285 | 324 | {counts} |
286 | | - totalItems={state.totalCount} |
| 325 | + selectedActions={state.selectedActions} |
287 | 326 | source={state.selectedSource} |
| 327 | + onactionchange={onActionChange} |
288 | 328 | onstart={startImport} |
289 | 329 | onreset={reset} |
290 | 330 | /> |
|
300 | 340 | {:else if state.status === "syncing"} |
301 | 341 | <SyncProgress |
302 | 342 | processedCount={state.processedCount} |
303 | | - totalCount={state.totalCount} |
| 343 | + totalCount={selectedTotalCount} |
304 | 344 | label={m.import_status_syncing({ |
305 | 345 | processed: state.processedCount, |
306 | | - total: state.totalCount, |
| 346 | + total: selectedTotalCount, |
307 | 347 | })} |
308 | 348 | /> |
309 | 349 | {:else if state.status === "complete"} |
|
0 commit comments