some nav cleanup

This commit is contained in:
2026-03-08 19:25:48 -04:00
parent 1618588a30
commit f003377f0d
8 changed files with 69 additions and 38 deletions

View File

@@ -86,8 +86,9 @@ export function App() {
const isQuit = keybind.match("quit", keyEvent); const isQuit = keybind.match("quit", keyEvent);
const isInverting = keybind.isInverting(keyEvent); const isInverting = keybind.isInverting(keyEvent);
// only handling top navigation here, cycle through tabs, just to high priority(player) all else to be handled in each tab // unified navigation: left->right, top->bottom across all tabs
if (nav.activeDepth() == 0) { if (nav.activeDepth() == 0) {
// at top level: cycle through tabs
if ( if (
(isCycle && !isInverting) || (isCycle && !isInverting) ||
(isDown && !isInverting) || (isDown && !isInverting) ||
@@ -104,6 +105,7 @@ export function App() {
nav.prevTab(); nav.prevTab();
return; return;
} }
// dive out to first pane
if ( if (
(isDive && !isInverting) || (isDive && !isInverting) ||
(isOut && isInverting) || (isOut && isInverting) ||
@@ -112,8 +114,8 @@ export function App() {
) { ) {
nav.setActiveDepth(1); nav.setActiveDepth(1);
} }
} } else {
if (nav.activeDepth() == 1) { // in panes: navigate between them
if ( if (
(isDive && isInverting) || (isDive && isInverting) ||
(isOut && !isInverting) || (isOut && !isInverting) ||
@@ -121,6 +123,10 @@ export function App() {
(isLeft && !isInverting) (isLeft && !isInverting)
) { ) {
nav.setActiveDepth(0); nav.setActiveDepth(0);
} else if (isDown && !isInverting) {
nav.nextPane();
} else if (isUp && isInverting) {
nav.prevPane();
} }
} }
}, },

View File

@@ -17,7 +17,7 @@ export const { use: useNavigation, provider: NavigationProvider } =
), ),
); );
//conveniences // unified navigation: left->right, top->bottom across all tabs
const nextTab = () => { const nextTab = () => {
if (activeTab() >= TabsCount) { if (activeTab() >= TabsCount) {
setActiveTab(1); setActiveTab(1);
@@ -31,10 +31,19 @@ export const { use: useNavigation, provider: NavigationProvider } =
setActiveTab(TabsCount); setActiveTab(TabsCount);
return; return;
} }
setActiveTab(activeTab() - 1); setActiveTab(activeTab() - 1);
}; };
const nextPane = () => {
// move to next pane in same tab, wrap around
setActiveDepth((prev) => (prev % TabsCount) + 1);
};
const prevPane = () => {
// move to previous pane in same tab, wrap around
setActiveDepth((prev) => (prev - 2 + TabsCount) % TabsCount + 1);
};
return { return {
activeTab, activeTab,
activeDepth, activeDepth,
@@ -44,6 +53,8 @@ export const { use: useNavigation, provider: NavigationProvider } =
setInputFocused, setInputFocused,
nextTab, nextTab,
prevTab, prevTab,
nextPane,
prevPane,
}; };
}, },
}); });

View File

@@ -31,6 +31,7 @@ export function DiscoverPage() {
const isUp = keybind.match("up", keyEvent); const isUp = keybind.match("up", keyEvent);
const isCycle = keybind.match("cycle", keyEvent); const isCycle = keybind.match("cycle", keyEvent);
const isSelect = keybind.match("select", keyEvent); const isSelect = keybind.match("select", keyEvent);
const isInverting = keybind.isInverting(keyEvent);
if (isSelect) { if (isSelect) {
const filteredPodcasts = discoverStore.filteredPodcasts(); const filteredPodcasts = discoverStore.filteredPodcasts();
@@ -40,15 +41,20 @@ export function DiscoverPage() {
return; return;
} }
// don't handle pane navigation here - unified in App.tsx
if (nav.activeDepth() !== DiscoverPagePaneType.SHOWS) return;
const filteredPodcasts = discoverStore.filteredPodcasts(); const filteredPodcasts = discoverStore.filteredPodcasts();
if (filteredPodcasts.length === 0) return; if (filteredPodcasts.length === 0) return;
if (isDown) { if (isDown && !isInverting()) {
setShowIndex((i) => (i + 1) % filteredPodcasts.length); setShowIndex((i) => (i + 1) % filteredPodcasts.length);
} else if (isUp) { } else if (isUp && isInverting()) {
setShowIndex((i) => (i - 1 + filteredPodcasts.length) % filteredPodcasts.length); setShowIndex((i) => (i - 1 + filteredPodcasts.length) % filteredPodcasts.length);
} else if (isCycle) { } else if ((isCycle && !isInverting()) || (isDown && !isInverting())) {
setShowIndex((i) => (i + 1) % filteredPodcasts.length); setShowIndex((i) => (i + 1) % filteredPodcasts.length);
} else if ((isCycle && isInverting()) || (isUp && isInverting())) {
setShowIndex((i) => (i - 1 + filteredPodcasts.length) % filteredPodcasts.length);
} }
}, },
{ release: false }, { release: false },

View File

@@ -41,6 +41,7 @@ export function FeedPage() {
const isUp = keybind.match("up", keyEvent); const isUp = keybind.match("up", keyEvent);
const isCycle = keybind.match("cycle", keyEvent); const isCycle = keybind.match("cycle", keyEvent);
const isSelect = keybind.match("select", keyEvent); const isSelect = keybind.match("select", keyEvent);
const isInverting = keybind.isInverting(keyEvent);
if (isSelect) { if (isSelect) {
const episodes = allEpisodes(); const episodes = allEpisodes();
@@ -50,15 +51,20 @@ export function FeedPage() {
return; return;
} }
// don't handle pane navigation here - unified in App.tsx
if (nav.activeDepth() !== FeedPaneType.FEED) return;
const episodes = allEpisodes(); const episodes = allEpisodes();
if (episodes.length === 0) return; if (episodes.length === 0) return;
if (isDown) { if (isDown && !isInverting()) {
setFocusedIndex((i) => (i + 1) % episodes.length); setFocusedIndex((i) => (i + 1) % episodes.length);
} else if (isUp) { } else if (isUp && isInverting()) {
setFocusedIndex((i) => (i - 1 + episodes.length) % episodes.length); setFocusedIndex((i) => (i - 1 + episodes.length) % episodes.length);
} else if (isCycle) { } else if ((isCycle && !isInverting()) || (isDown && !isInverting())) {
setFocusedIndex((i) => (i + 1) % episodes.length); setFocusedIndex((i) => (i + 1) % episodes.length);
} else if ((isCycle && isInverting()) || (isUp && isInverting())) {
setFocusedIndex((i) => (i - 1 + episodes.length) % episodes.length);
} }
}, },
{ release: false }, { release: false },

View File

@@ -42,10 +42,10 @@ export function MyShowsPage() {
const isUp = keybind.match("up", keyEvent); const isUp = keybind.match("up", keyEvent);
const isCycle = keybind.match("cycle", keyEvent); const isCycle = keybind.match("cycle", keyEvent);
const isSelect = keybind.match("select", keyEvent); const isSelect = keybind.match("select", keyEvent);
const isInverting = keybind.isInverting(keyEvent);
const shows = feedStore.getFilteredFeeds(); const shows = feedStore.getFilteredFeeds();
const episodesList = episodes(); const episodesList = episodes();
const selected = selectedShow();
if (isSelect) { if (isSelect) {
if (shows.length > 0 && showIndex() < shows.length) { if (shows.length > 0 && showIndex() < shows.length) {
@@ -57,23 +57,18 @@ export function MyShowsPage() {
return; return;
} }
if (shows.length > 0) { // don't handle pane navigation here - unified in App.tsx
if (isDown) { if (nav.activeDepth() !== MyShowsPaneType.EPISODES) return;
setShowIndex((i) => (i + 1) % shows.length);
} else if (isUp) {
setShowIndex((i) => (i - 1 + shows.length) % shows.length);
} else if (isCycle) {
setShowIndex((i) => (i + 1) % shows.length);
}
}
if (episodesList.length > 0) { if (episodesList.length > 0) {
if (isDown) { if (isDown && !isInverting()) {
setEpisodeIndex((i) => (i + 1) % episodesList.length); setEpisodeIndex((i) => (i + 1) % episodesList.length);
} else if (isUp) { } else if (isUp && isInverting()) {
setEpisodeIndex((i) => (i - 1 + episodesList.length) % episodesList.length); setEpisodeIndex((i) => (i - 1 + episodesList.length) % episodesList.length);
} else if (isCycle) { } else if ((isCycle && !isInverting()) || (isDown && !isInverting())) {
setEpisodeIndex((i) => (i + 1) % episodesList.length); setEpisodeIndex((i) => (i + 1) % episodesList.length);
} else if ((isCycle && isInverting()) || (isUp && isInverting())) {
setEpisodeIndex((i) => (i - 1 + episodesList.length) % episodesList.length);
} }
} }
}, },

View File

@@ -23,6 +23,8 @@ export function PlayerPage() {
onMount(() => { onMount(() => {
useKeyboard( useKeyboard(
(keyEvent: any) => { (keyEvent: any) => {
const isInverting = keybind.isInverting(keyEvent);
if (keybind.match("audio-toggle", keyEvent)) { if (keybind.match("audio-toggle", keyEvent)) {
audio.togglePlayback(); audio.togglePlayback();
return; return;

View File

@@ -36,6 +36,7 @@ export function SearchPage() {
const isUp = keybind.match("up", keyEvent); const isUp = keybind.match("up", keyEvent);
const isCycle = keybind.match("cycle", keyEvent); const isCycle = keybind.match("cycle", keyEvent);
const isSelect = keybind.match("select", keyEvent); const isSelect = keybind.match("select", keyEvent);
const isInverting = keybind.isInverting(keyEvent);
if (isSelect) { if (isSelect) {
const results = searchStore.results(); const results = searchStore.results();
@@ -45,15 +46,20 @@ export function SearchPage() {
return; return;
} }
// don't handle pane navigation here - unified in App.tsx
if (nav.activeDepth() !== SearchPaneType.RESULTS) return;
const results = searchStore.results(); const results = searchStore.results();
if (results.length === 0) return; if (results.length === 0) return;
if (isDown) { if (isDown && !isInverting()) {
setResultIndex((i) => (i + 1) % results.length); setResultIndex((i) => (i + 1) % results.length);
} else if (isUp) { } else if (isUp && isInverting()) {
setResultIndex((i) => (i - 1 + results.length) % results.length); setResultIndex((i) => (i - 1 + results.length) % results.length);
} else if (isCycle) { } else if ((isCycle && !isInverting()) || (isDown && !isInverting())) {
setResultIndex((i) => (i + 1) % results.length); setResultIndex((i) => (i + 1) % results.length);
} else if ((isCycle && isInverting()) || (isUp && isInverting())) {
setResultIndex((i) => (i - 1 + results.length) % results.length);
} }
}, },
{ release: false }, { release: false },

View File

@@ -45,20 +45,19 @@ export function SettingsPage() {
const isUp = keybind.match("up", keyEvent); const isUp = keybind.match("up", keyEvent);
const isCycle = keybind.match("cycle", keyEvent); const isCycle = keybind.match("cycle", keyEvent);
const isSelect = keybind.match("select", keyEvent); const isSelect = keybind.match("select", keyEvent);
const isInverting = keybind.isInverting(keyEvent);
if (isSelect) { // don't handle pane navigation here - unified in App.tsx
if (nav.activeDepth() < 1 || nav.activeDepth() > SettingsPaneCount) return;
if (isDown && !isInverting()) {
nav.setActiveDepth((nav.activeDepth() % SettingsPaneCount) + 1); nav.setActiveDepth((nav.activeDepth() % SettingsPaneCount) + 1);
return; } else if (isUp && isInverting()) {
} nav.setActiveDepth((nav.activeDepth() - 2 + SettingsPaneCount) % SettingsPaneCount + 1);
} else if ((isCycle && !isInverting()) || (isDown && !isInverting())) {
const nextDepth = isDown
? (nav.activeDepth() % SettingsPaneCount) + 1
: (nav.activeDepth() - 2 + SettingsPaneCount) % SettingsPaneCount + 1;
if (isCycle) {
nav.setActiveDepth((nav.activeDepth() % SettingsPaneCount) + 1); nav.setActiveDepth((nav.activeDepth() % SettingsPaneCount) + 1);
} else { } else if ((isCycle && isInverting()) || (isUp && isInverting())) {
nav.setActiveDepth(nextDepth); nav.setActiveDepth((nav.activeDepth() - 2 + SettingsPaneCount) % SettingsPaneCount + 1);
} }
}, },
{ release: false }, { release: false },