Skip to content

Add Import/Export feature: JSON state backup and filesystem metadata export#170

Merged
Kallb123 merged 6 commits into
mainfrom
copilot/add-import-export-options
May 26, 2026
Merged

Add Import/Export feature: JSON state backup and filesystem metadata export#170
Kallb123 merged 6 commits into
mainfrom
copilot/add-import-export-options

Conversation

Copilot AI commented May 26, 2026

Copy link
Copy Markdown
Contributor

Adds three import/export capabilities to the Settings page: JSON backup/restore of app state, and writing enriched metadata alongside media files for persistence across rescans.

Settings UI

  • New collapsible Import / Export section above Troubleshooting, matching existing style
  • Three checkboxes control JSON export scope: Settings, Overrides, Matches
  • Three action buttons: Export to JSON, Import from JSON, Export metadata to media folders

JSON export/import (ImportExportService)

  • exportJson saves selected state slices (API keys/view options, overrides, matched TMDB/TVDB IDs + episode names) to a single smb_export_YYYY-MM-DD.json via SAF directory picker
  • importJson restores via document picker; only sections present in the file are applied

Filesystem metadata export

  • exportToFilesystem writes alongside each show/movie folder:
    • smb.json — versioned (smbVersion: 1) with provider IDs, metadataSource, episode titles, and user overrides
    • poster.jpg — copied from local provider cache
    • smb_thumb_s01e02.jpg — per-episode thumbnails written to their season directory

FileScanner pickup on rescan

  • recursiveCollect detects smb.json and smb_thumb_*.jpg during traversal
  • IDs, episode titles, and thumbnail URIs are applied in buildLibrary/buildMovieList
  • API-enriched data always wins over smb.json values (smb.json acts as a fallback/seed)
  • Shared smbThumbFilename() + SMB_THUMB_REGEX in SmbTypes.ts keep writer and reader in sync

Copilot AI changed the title Add Import/Export feature Add Import/Export feature: JSON state backup and filesystem metadata export May 26, 2026
Copilot AI requested a review from Kallb123 May 26, 2026 19:02
@Kallb123

Copy link
Copy Markdown
Owner

@copilot There are new import references to LegacyFileSystem. Refactor these into the modern class based system.
Have look across the changes as a reviewer, there are some variables with old names.

Copilot AI commented May 26, 2026

Copy link
Copy Markdown
Contributor Author

@copilot There are new import references to LegacyFileSystem. Refactor these into the modern class based system.
Have look across the changes as a reviewer, there are some variables with old names.

Done in commits b9e2e3c and dbfad88.

LegacyFileSystem removed:

  • FileScanner.ts: dropped the import * as LegacyFileSystem line; the single SAF-based readAsStringAsync call (for smb.json) now goes through StorageAccessFramework which was already imported.
  • ImportExportService.ts: replaced the wildcard import with import { File } from 'expo-file-system' and import { StorageAccessFramework } from 'expo-file-system/legacy' directly; all LegacyFileSystem.readAsStringAsync calls replaced with await new File(uri).text() (text) or await new File(uri).base64() (binary) using the modern class API.

Old variable names fixed:

  • ShowMatchExport.seasons[*].episodes[*] field renamed from tmdbTitleepisodeTitle (provider-agnostic), with the export/import mapping updated accordingly (ep.tmdbTitle → JSON episodeTitle on export; JSON ep.episodeTitle → Redux tmdbTitle on import).

@Kallb123

Copy link
Copy Markdown
Owner

@copilot the import of StorageAccessFramework from the legacy library should be able to be updated to a modern version. I don't think we use this elsewhere for the same purpose.

Copilot AI commented May 26, 2026

Copy link
Copy Markdown
Contributor Author

@copilot the import of StorageAccessFramework from the legacy library should be able to be updated to a modern version. I don't think we use this elsewhere for the same purpose.

Done in the latest commit. The expo-file-system/legacy import for StorageAccessFramework has been removed from ImportExportService.ts and replaced entirely with the modern class-based API:

  • StorageAccessFramework.requestDirectoryPermissionsAsync()Directory.pickDirectoryAsync()
  • StorageAccessFramework.readDirectoryAsync()new Directory(dirUri).list() (synchronous, returns (Directory | File)[])
  • StorageAccessFramework.createFileAsync()directory.createFile(name, mimeType) (synchronous)
  • StorageAccessFramework.writeAsStringAsync()file.write(content, { encoding }) (synchronous, accepts 'base64' encoding natively)

The writeSafBase64 helper wrapper was also removed since the modern File.write() accepts a { encoding: 'base64' } option directly. The modern Directory/File classes fully support SAF content:// URIs on Android via the SAFDocumentFile backend, confirmed from the native Kotlin source.

@Kallb123 Kallb123 marked this pull request as ready for review May 26, 2026 21:39
@Kallb123 Kallb123 merged commit 637ae6e into main May 26, 2026
1 check passed
@Kallb123 Kallb123 deleted the copilot/add-import-export-options branch May 26, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants