From 7f5d25a03b3e1c7661976d1b0320cdf35396f32c Mon Sep 17 00:00:00 2001 From: Honey Date: Sun, 16 Aug 2026 21:52:11 +0200 Subject: [PATCH] =?UTF-8?q?feat(android):=20swipe=20between=20Erkunden=20s?= =?UTF-8?q?ub-tabs=20(Bibliothek=20=E2=86=94=20Global)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wrap the Erkunden content in a HorizontalPager so a left/right swipe switches between the Bibliothek and Global search tabs, two-way synced with the TabRow: a chip tap animates the pager; a settled swipe updates the selected tab (and stops any preview, like a tap). Removes the idea from the backlog now that it's built. Co-Authored-By: Claude Opus 4.8 --- CHANGELOG.md | 1 - .../novasonic/app/ui/screen/ExploreScreen.kt | 58 ++++++++++++------- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28b57e2..c6d78c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -453,7 +453,6 @@ Primary causes identified: - **New-release alerts:** periodic check for new albums/singles by followed artists (sources: iTunes lookup / MusicBrainz / Last.fm), surfaced in the existing in-app notification bell (and optionally push). - **Concert alerts:** reuse the existing **Ticketmaster** events integration to notify when a followed artist has nearby/upcoming shows. - Ties into the importer: a "download this new release" action straight from the notification. -- **Android** — **Swipe between Erkunden sub-tabs** — a left/right swipe gesture on the Erkunden tab to switch between "Bibliothek" and "Global" search (instead of only tapping the chips). A fun, natural pager-style gesture (e.g. HorizontalPager). - **Android** — Playlist drag-and-drop / sort order - **Android** — Artist page iTunes fallback (for artists not in Navidrome) - **Android** — Romaji / Japanese sort support diff --git a/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ExploreScreen.kt b/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ExploreScreen.kt index e5b9b04..4f98d15 100644 --- a/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ExploreScreen.kt +++ b/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ExploreScreen.kt @@ -3,6 +3,8 @@ package com.novasonic.app.ui.screen import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items @@ -148,6 +150,17 @@ fun ExploreScreen( return } + // Swipe left/right to switch between the Bibliothek and Erkunden sub-tabs, kept in sync with the + // TabRow: a chip tap animates the pager; a settled swipe updates the selected tab. + val pagerState = rememberPagerState(initialPage = state.tab.ordinal) { ExploreTab.values().size } + LaunchedEffect(state.tab) { + if (pagerState.currentPage != state.tab.ordinal) pagerState.animateScrollToPage(state.tab.ordinal) + } + LaunchedEffect(pagerState.settledPage) { + val t = ExploreTab.values()[pagerState.settledPage] + if (t != state.tab) { vm.selectTab(t); vm.stopPreview() } + } + Column(Modifier.fillMaxSize()) { // ── Tabs ───────────────────────────────────────────────────────────── TabRow( @@ -230,26 +243,31 @@ fun ExploreScreen( } } - // ── Content ────────────────────────────────────────────────────────── - when (state.tab) { - ExploreTab.LIBRARY -> LibrarySearchContent( - query = state.query, - coverUrl = coverUrl, - playerState = playerState, - onSongPlay = onSongPlay, - onAlbumClick = onAlbumClick, - onArtistClick = onArtistClick, - onShowContextMenu = onShowContextMenu, - ) - ExploreTab.GLOBAL -> GlobalExploreContent( - state = state, - vm = vm, - coverUrl = coverUrl, - playerState = playerState, - onAlbumClick = onAlbumClick, - onSongPlay = onSongPlay, - onDownload = vm::showDownloadSheet, - ) + // ── Content (swipeable) ──────────────────────────────────────────────── + HorizontalPager( + state = pagerState, + modifier = Modifier.weight(1f), + ) { page -> + when (page) { + ExploreTab.LIBRARY.ordinal -> LibrarySearchContent( + query = state.query, + coverUrl = coverUrl, + playerState = playerState, + onSongPlay = onSongPlay, + onAlbumClick = onAlbumClick, + onArtistClick = onArtistClick, + onShowContextMenu = onShowContextMenu, + ) + else -> GlobalExploreContent( + state = state, + vm = vm, + coverUrl = coverUrl, + playerState = playerState, + onAlbumClick = onAlbumClick, + onSongPlay = onSongPlay, + onDownload = vm::showDownloadSheet, + ) + } } } }