| Age | Commit message (Collapse) | Author |
|
- New ShareViewerScreen (/share/:token): unauthenticated share-viewer that
fetches share metadata via publicApiClientProvider, renders filename, type,
duration, thumbnail, and a Play button routing to the video/audio player.
- New publicApiClientProvider: bare Dio client (no auth interceptors) for the
public share endpoint; shares kPlayerBaseUrl with the authenticated client.
- AndroidManifest: http + https deep-link intent-filters for /share/.* so
Android routes share URLs directly into the app (App Links / autoVerify).
- router.dart: /share/:token bypasses the authentication redirect; guard uses
AppRoutes.shareViewerPrefix constant instead of a raw '/share/' string (DIP).
- app_routes.dart: shareViewer route constant, shareViewerPrefix, shareViewerPath helper.
- error_mappers.dart: shareViewerErrorMessage — 404 invalid/revoked, 410 expired.
- player_api_client.dart: baseUrl getter encapsulates rawDio.options.baseUrl so
screens never access transport internals directly (ISP, DIP).
- Review fixes: OCP icon map in _FallbackThumbnail, LSP explicit baseUrl
overrides in test fakes, DIP shareViewerPrefix constant.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Introduces ProgressQueue backed by SQLite for offline-capable progress
tracking, with ProgressQueueBase (LSP+DIP), databaseFactory injection
(DIP), and ProgressSyncClient narrow interface (ISP).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
navigation (va)
Adds a FolderBrowserScreen that calls browseSet on init and pull-to-refresh,
renders subfolders first (with cover via setFolderCoverUrl) then media items,
and provides a scrollable breadcrumb bar for navigating the folder hierarchy.
Key changes:
- player-android/lib/screens/folder_browser_screen.dart: new screen with
loading/empty/error/refresh states, generation-counter cancellation, and
no Dio import in the screen layer (DIP).
- player-android/lib/api/player_api_client.dart: add setFolderCoverUrl() so
screens never access rawDio directly for URL construction (DIP).
- player-android/lib/utils/duration_formatter.dart: extract shared
formatDuration() from MediaGridScreen to eliminate the DRY violation.
- player-android/lib/screens/media_grid_screen.dart: delegate to
formatDuration() from the shared utility.
- player-android/lib/utils/error_mappers.dart: add folderErrorMessage().
- player-android/lib/app_routes.dart: add folderBrowser and folderBrowserPath().
- player-android/lib/router.dart: wire /browse/:setId GoRoute.
- player-android/test/screens/folder_browser_screen_test.dart: 16 widget tests
covering renders, breadcrumbs, folder/media tap navigation, empty, error,
retry, and pull-to-refresh.
All 298 tests pass; flutter analyze reports no issues.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Implements every previously-unimplemented method in DioPlayerApiClient:
shares (listSharesForMedia, listMyShares, revokeShare), public shared-media
endpoints (getSharedMediaPage, streamSharedMedia, getSharedThumbnail,
downloadSharedMedia), config (getConfig), sets (getSetCover, updateSetCover,
uploadToSet), media helpers (regenerateThumbnail, deleteMedia, restoreMedia),
progress batch (batchUpdateProgress), podcasts (listPodcasts, listEpisodes,
downloadEpisode, toggleEpisodeComplete), admin users/permissions/scanner
(listUsers, createUser, deleteUser, listPermissions, grantPermission,
revokePermission, triggerRescan, getScanProgress, listTrash), and API tokens
(listAPITokens, createAPIToken, revokeAPIToken).
Adds listAPITokens/createAPIToken/revokeAPIToken/batchUpdateProgress to the
abstract PlayerApiClient. Corrects listPermissions return type from
List<Map> to Map<String,dynamic> to match the server's single-object response.
Adds 18 new unit tests covering shares (listMyShares success/empty/401,
revokeShare success/404/401) and podcasts (listEpisodes success/pagination/
empty/401, toggleEpisodeComplete success/404/401). All 264 tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
tests (ua)
- Replace placeholder MediaGridScreen with a full implementation: loads
media via listMedia(setId:), renders a Material 3 2-column grid of
thumbnail cards with filename, type icon, and duration overlay.
- Add thumbnailUrl(int mediaId) to PlayerApiClient so screen files
construct thumbnail URLs without importing Dio (DIP).
- Add mediaErrorMessage() top-level helper to error_mappers.dart
(Open-Closed Principle; matches setsErrorMessage pattern).
- Update router.dart to forward the set name as a route extra so
MediaGridScreen shows the name in the app bar without extra API calls.
- Update home_screen.dart _SetCard tap to pass set name as route extra.
- Add 10 widget tests covering: loading, grid render, tap navigation
to /media/:id, empty state, error state + retry, and pull-to-refresh.
- All 109 tests pass; flutter analyze reports no issues.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Server: expose a public countUsers endpoint (GET /api/v1/auth/count)
so mobile clients can detect first-run (count=0) without a session.
Android: wire countUsers via DioPlayerApiClient, add firstRunProvider
(FutureProvider), update go_router redirect to drive /bootstrap vs /login
based on the count, rework LoginScreen to handle loading/error states, and
add widget tests for the new login screen and smoke-test updates.
Fix review issues: correct FutureProvider cache-lifetime comment in
first_run_provider.dart; add TestServer_CountUsers covering zero-users
and users-exist cases to handlers_test.go.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Introduces dio_client.dart with _AuthInterceptor (guards Bearer token
injection with containsKey so callers can override Authorization) and
_UnauthorizedInterceptor (private fields, 401 → login redirect).
PlayerApiClient is refactored to accept a pre-configured Dio instance
instead of raw credentials; adds dio + flutter_secure_storage deps.
Fixes review issues: Auth header comment/behavior corrected, private
fields on _UnauthorizedInterceptor, unused import removed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Remove const from PlayerApiClient constructor (Uri is not const-constructable)
- Replace .cast<String>() with .whereType<String>().toList() in Media.fromJson
to silently drop non-string and null tag elements instead of throwing TypeError
- Add regression test: tags [1, 'valid', null] deserialized as ['valid']
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
|
|