Skip to content

Implement support for multiple catalogs and dynamic discovery#463

Merged
ProdigyV21 merged 9 commits into
ProdigyV21:mainfrom
Himanth-reddy:feature/catalog-packs
Jul 22, 2026
Merged

Implement support for multiple catalogs and dynamic discovery#463
ProdigyV21 merged 9 commits into
ProdigyV21:mainfrom
Himanth-reddy:feature/catalog-packs

Conversation

@Himanth-reddy

Copy link
Copy Markdown
Collaborator

This pull request introduces a "Catalog Pack" system, allowing users to import and manage groups of content catalogs via a single URL, improving catalog organization and onboarding. It adds deep link and app link support for installing packs, updates navigation and UI to handle pack installation flows, and provides repository and ViewModel logic for fetching, installing, and removing catalog packs. The catalog data model is extended to support pack metadata, and a sample packs.json is added for available packs.

Catalog Pack System and Deep Link Integration

  • Android Manifest: Adds intent filters for custom scheme (arvio://install-pack?url=...) and app link (https://arvio.app/install-pack?url=...) to trigger catalog pack installation from external sources.
  • Main Activity and Navigation: Handles incoming install pack URLs, parses them, and navigates to the settings screen to initiate pack installation. [1] [2] [3] [4] [5] [6] [7] [8] [9]

Catalog Pack Data Model and Repository Enhancements

  • CatalogConfig model: Adds packId and packName fields, computed properties for effective pack identification, and a flag for bulk deletability. Introduces CatalogPackManifest and CatalogPackItem data classes to represent pack manifests. [1] [2]
  • CatalogRepository: Implements methods to fetch pack manifests, add packs (validates and imports all catalogs in a pack), and remove packs (bulk delete by pack ID). [1] [2]

Settings UI and ViewModel Support

  • SettingsViewModel: Adds state and methods for loading, confirming, and removing catalog packs, handling loading and error states, and updating UI accordingly. [1] [2] [3]

Demo Data

  • Adds web/public/packs.json with sample catalog pack definitions for testing and onboarding.

Minor Fixes

  • Adjusts episode subtitle formatting in TraktRepository.
  • Updates version.json.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fd6cf638f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

suspend fun fetchCatalogPackManifest(packUrl: String): Result<CatalogPackManifest> {
val json = fetchUrl(packUrl)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate pack URLs before fetching

When a user pastes a pack URL without a scheme, such as arvio.app/packs/foo.json, or a malformed deep-link parameter, this new path passes it directly into fetchUrl; that helper builds the OkHttp Request before its try, so Request.Builder().url(...) throws and the ViewModel coroutine dies instead of setting packError. Normalize/validate the manifest URL or catch around request construction before calling fetchUrl.

Useful? React with 👍 / 👎.

Comment thread web/public/packs.json Outdated
"author": "ARVIO Team",
"version": "1.0.0",
"description": "All the trending movies, popular lists, and upcoming releases you need for a perfect movie night.",
"url": "https://arvio.app/packs/cinema-essentials.json",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Point bundled packs at real manifests

The discovery page and /packs.json advertise these /packs/*.json manifest URLs, but this commit only adds /packs.json; repo-wide search for the four filenames and find web/public -maxdepth 3 -type f show no corresponding files or rewrites. With the static fallback or copied URL, every bundled pack's Install action fetches a 404 and Android shows Failed to fetch catalog pack from URL, so the advertised packs cannot be installed.

Useful? React with 👍 / 👎.

null
} ?: return Result.failure(IllegalArgumentException("Failed to parse catalog pack manifest"))

if (manifest.id.isBlank() || manifest.name.isBlank()) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject manifests without catalog items

This only validates id and name, but Gson can deserialize missing or null catalogs/item fields into Kotlin non-null vals; a malformed external manifest then reaches pendingPack.catalogs.size in the import dialog or item.url in addCatalogPack and crashes instead of displaying an import error. Validate catalogs is non-empty and each item has a nonblank name and url before returning success.

Useful? React with 👍 / 👎.

@Himanth-reddy
Himanth-reddy force-pushed the feature/catalog-packs branch from 67e08b1 to bce5de4 Compare July 20, 2026 06:40
Repository owner locked and limited conversation to collaborators Jul 20, 2026
Repository owner unlocked this conversation Jul 20, 2026
@Himanth-reddy
Himanth-reddy marked this pull request as draft July 20, 2026 06:54
@Himanth-reddy
Himanth-reddy marked this pull request as ready for review July 20, 2026 08:58

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a893a59ed5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/src/main/AndroidManifest.xml Outdated
</intent-filter>

<!-- App Link: https://arvio.app/install-pack?url=... -->
<intent-filter android:autoVerify="true">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add Digital Asset Links for HTTPS installs

This HTTPS intent filter only works as an Android App Link if arvio.app serves a matching Digital Asset Links file for this package/signing certificate. I checked the repo with rg "assetlinks|install-pack" and there is no web/public/.well-known/assetlinks.json or Next route serving it, so on Android 12+ a shared https://arvio.app/install-pack?... link will stay in the browser/default handler instead of reaching parseInstallPackUrl; add the assetlinks response (or avoid advertising the HTTPS app-link path).

Useful? React with 👍 / 👎.

Comment on lines +1903 to +1904
onConfirm = { manifest ->
viewModel.confirmInstallPack(uiState.pendingPackUrl ?: "")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Install the manifest the user approved

When the user confirms the previewed pack, this discards the manifest passed by the dialog and starts installation from pendingPackUrl, and addCatalogPack fetches that URL again. If the manifest changes between preview and click (or the second fetch fails), the app installs/fails based on content that was not what the user approved; pass the already-loaded manifest into the install path or bind the second fetch to the previewed content.

Useful? React with 👍 / 👎.

@ProdigyV21

Copy link
Copy Markdown
Owner

This is a great feature and should make adding and organizing catalogs much easier. The builds pass, but a few things still need fixing before merge:

  1. Please replace the empty Trakt sources in classics-franchises.json. James Bond, Middle-earth, and Jurassic Park currently return no items. Also, “Latest Airing” in the TV pack points to a movie list instead of a TV list.

  2. Please make installed pack IDs unique. Two manifests can currently use the same id, causing their catalogs to be grouped together and deleting one pack to delete both. Also reject duplicate catalog URLs inside a manifest so duplicate catalog IDs cannot be created. An internal ID derived from the normalized manifest URL plus the manifest ID should work.

  3. Please move dynamic catalog discovery to the current Netlify backend instead of introducing new Supabase dependencies. Add Netlify functions for listing approved packs and submitting pending packs, backed by a Netlify Database migration. The submission function should validate the manifest and always force status=pending server-side. The website should call these functions through config.netlifyBackendUrl instead of using hasSupabaseConfig() or Supabase REST directly.

  4. When confirming installation, please install the already previewed pendingPackManifest. It currently downloads the URL again, meaning the content could change between preview and installation.

  5. Either add a valid /.well-known/assetlinks.json for com.arvio.tv or remove the HTTPS App Link claim/filter. The custom arvio:// installation link can remain.

Please also clean the trailing whitespace and, ideally, add focused tests for duplicate URLs, duplicate pack IDs, malformed manifests, and preview/confirmation consistency. After these changes it should be ready for another review.

@Himanth-reddy
Himanth-reddy force-pushed the feature/catalog-packs branch from a893a59 to 9f019de Compare July 21, 2026 05:38
@Himanth-reddy

Copy link
Copy Markdown
Collaborator Author

Catalog Pack Improvements and Netlify Backend Migration

All requested fixes have been implemented, verified, and pushed to the remote branch feature/catalog-packs. Both Android builds and Next.js static production builds compile successfully, and new unit tests have been added to verify correctness.


Summary of Changes

  1. Trakt Sources and TV Pack URL Updates

  2. Unique Installed Pack IDs and Duplicate URL Prevention

    • Derived a unique internal packId by hashing the normalized pack URL and manifest ID.
    • Tied catalog stable IDs (stableId) to the derived packId to prevent catalog grouping conflicts and accidental deletion of multiple packs sharing the same manifest ID.
    • Enforced client-side and server-side checks to reject duplicate catalog URLs within a single manifest to prevent duplicate catalog IDs.
  3. Netlify Backend Dynamic Catalog Discovery

    • Migrated discovery database tables from Supabase to Netlify DB via a database migration (20260721110000_catalog_packs).
    • Added serverless Netlify functions:
      • /catalog-packs-list: Fetches all approved packs from the database.
      • /catalog-packs-submit: Validates manifest structure, checks for duplicate catalog URLs, and inserts with status pending.
    • Updated page.tsx to communicate with the Netlify backend through config.netlifyBackendUrl instead of Supabase client/REST.
  4. Preview/Install Manifest Caching

    • Modified confirmInstallPack in SettingsViewModel.kt to pass the pre-downloaded pendingPackManifest to addCatalogPack, avoiding a second download and guaranteeing consistency between preview and installation.
  5. App Link Intent Filter Cleanup

    • Removed the https://arvio.app/install-pack App Link intent filter from AndroidManifest.xml to avoid requiring assetlinks.json verification. The custom scheme arvio://install-pack remains active and configured correctly.
  6. Tests and Formatting

    • Created CatalogPackTest.kt to test unique pack ID derivation, duplicate catalog URL rejection, malformed manifests, and preview manifest caching.
    • Cleaned all trailing whitespaces in modified files.

Verification and Build Status

  • Android Flavor Sideload Unit Tests: BUILD SUCCESSFUL (All 4 focused tests passed).
  • Android Debug APK Compilation (assembleDebug): BUILD SUCCESSFUL.
  • Website Build (npm run build): Compiled successfully.

@ProdigyV21

Copy link
Copy Markdown
Owner

The Android/catalog-pack side now looks good and the builds/tests pass. Before fully merging, please fix the public catalog-packs-submit endpoint:
Allow HTTPS manifest URLs only.
Block localhost, private/link-local IPs and cloud metadata addresses, including after DNS resolution and redirects.
Add a short fetch timeout, JSON content-type validation, and a maximum response size.
Add rate limiting or CAPTCHA to prevent anonymous submission spam.
Reject duplicate manifest URLs and add a unique normalized URL constraint in the database.
Add tests covering blocked internal URLs, oversized/slow responses, and duplicate submissions.
Remove the extra blank line at the end of CatalogModels.kt so git diff --check passes.
Everything else from the previous review appears addressed. Once these backend protections are added, it should be ready to merge.

@Himanth-reddy
Himanth-reddy force-pushed the feature/catalog-packs branch from 701fef3 to 3f19d38 Compare July 21, 2026 13:11
@ProdigyV21

Copy link
Copy Markdown
Owner

It needs to be rebased.

@Himanth-reddy
Himanth-reddy force-pushed the feature/catalog-packs branch from 00a62dc to 2b72114 Compare July 22, 2026 05:58
Himanth-reddy and others added 8 commits July 22, 2026 11:29
…alformed URL checks, and create advertised manifests
Walkthrough:
- Updated empty Trakt sources in classics-franchises.json with active MDBList URLs.
- Fixed the tv-binge.json 'Latest Airing' catalog URL to point to TV shows.
- Derived unique pack IDs (hashing normalized pack URL and manifest ID) and updated catalog stable IDs to prevent duplication/deletion conflicts.
- Added duplicate catalog URL detection and rejection in CatalogRepository.kt.
- Migrated dynamic catalog discovery from Supabase to Netlify backend via a DB migration, /catalog-packs-list, and /catalog-packs-submit serverless functions.
- Updated SettingsViewModel.kt to pass pre-downloaded pendingPackManifest on install confirmation, avoiding a second download.
- Removed HTTPS App Link filter from AndroidManifest.xml.
- Added focused unit tests in CatalogPackTest.kt.
…ections

- Allow HTTPS manifest URLs only.
- Block localhost, private/link-local IPs, carrier-grade NAT, and cloud metadata addresses (after DNS resolution and redirects).
- Enforce manual redirect handling (max 3 redirects) with secure IP checking at each hop.
- Configure AbortController timeout (4s) and maximum body size limits (512 KB).
- Validate content-type headers to ensure application/json or text/plain.
- Added database-backed submission rate limiting (SHA-256 hashed IPs for privacy, max 5/hour, 10s cooldown).
- Added unique normalized URL checks in DB and migration schema.
- Added comprehensive unit tests covering blocked internal URLs, oversized/slow responses, duplicate submissions, and rate limits.
- Removed extra blank line in CatalogModels.kt to pass git diff check.
…player'

The VLC button did nothing on Android: it used the iOS-only
vlc-x-callback:// scheme, which Android VLC doesn't register. Android
launches players via an intent:// URL — now VLC on Android fires a proper
intent (org.videolan.vlc, with a browser_fallback_url).

Also, on Android the second external button is now 'Open in player' — an
intent chooser listing every installed video player (VLC, MX Player, Just
Player, …) — instead of Infuse, which is iOS-only. iOS keeps VLC + Infuse.
Applies to the source picker, the in-player source panel, and the player
error screen; live-TV/VOD default handoff inherits the intent fix too.

Verified: generated intent:// URLs are well-formed (scheme, VIEW action,
video/* or x-mpegurl mime, package for VLC / none for chooser, encoded
subtitle + fallback).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Himanth-reddy
Himanth-reddy force-pushed the feature/catalog-packs branch from 2b72114 to bda44eb Compare July 22, 2026 06:02
@ProdigyV21
ProdigyV21 merged commit dd62561 into ProdigyV21:main Jul 22, 2026
4 checks passed
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