more indication

This commit is contained in:
2026-02-20 22:42:15 -05:00
parent 1a5efceebd
commit 1e6618211a
5 changed files with 168 additions and 135 deletions

View File

@@ -43,13 +43,17 @@ export function DiscoverPage() {
<box
border
padding={1}
borderColor={theme.border}
borderColor={
nav.activeDepth() != DiscoverPagePaneType.CATEGORIES
? theme.border
: theme.accent
}
flexDirection="column"
gap={1}
>
<text
fg={
nav.activeDepth == DiscoverPagePaneType.CATEGORIES
nav.activeDepth() == DiscoverPagePaneType.CATEGORIES
? theme.accent
: theme.text
}
@@ -76,61 +80,67 @@ export function DiscoverPage() {
</For>
</box>
</box>
<box
flexDirection="column"
flexGrow={1}
border
borderColor={theme.border}
>
<box padding={1}>
<SelectableText
selected={() => false}
primary={nav.activeDepth == DiscoverPagePaneType.SHOWS}
>
Trending in{" "}
{DISCOVER_CATEGORIES.find(
(c) => c.id === discoverStore.selectedCategory(),
)?.name ?? "All"}
</SelectableText>
</box>
<box flexDirection="column" height="100%">
<Show
fallback={
<box padding={2}>
{discoverStore.filteredPodcasts().length !== 0 ? (
<text fg={theme.warning}>Loading trending shows...</text>
) : (
<text fg={theme.textMuted}>
No podcasts found in this category.
</text>
)}
</box>
}
when={
!discoverStore.isLoading() &&
discoverStore.filteredPodcasts().length === 0
}
>
<scrollbox>
<box flexDirection="column">
<For each={discoverStore.filteredPodcasts()}>
{(podcast, index) => (
<PodcastCard
podcast={podcast}
selected={
index() === showIndex() &&
nav.activeDepth == DiscoverPagePaneType.SHOWS
}
onSelect={() => handleShowSelect(index())}
onSubscribe={() => handleSubscribe(podcast)}
/>
<box
flexDirection="column"
flexGrow={1}
border
borderColor={
nav.activeDepth() == DiscoverPagePaneType.SHOWS
? theme.accent
: theme.border
}
>
<box padding={1}>
<SelectableText
selected={() => false}
primary={nav.activeDepth() == DiscoverPagePaneType.SHOWS}
>
Trending in{" "}
{DISCOVER_CATEGORIES.find(
(c) => c.id === discoverStore.selectedCategory(),
)?.name ?? "All"}
</SelectableText>
</box>
<box flexDirection="column" height="100%">
<Show
fallback={
<box padding={2}>
{discoverStore.filteredPodcasts().length !== 0 ? (
<text fg={theme.warning}>Loading trending shows...</text>
) : (
<text fg={theme.textMuted}>
No podcasts found in this category.
</text>
)}
</For>
</box>
</scrollbox>
</Show>
</box>
}
when={
!discoverStore.isLoading() &&
discoverStore.filteredPodcasts().length === 0
}
>
<scrollbox
focused={nav.activeDepth() == DiscoverPagePaneType.SHOWS}
>
<box flexDirection="column">
<For each={discoverStore.filteredPodcasts()}>
{(podcast, index) => (
<PodcastCard
podcast={podcast}
selected={
index() === showIndex() &&
nav.activeDepth() == DiscoverPagePaneType.SHOWS
}
onSelect={() => handleShowSelect(index())}
onSubscribe={() => handleSubscribe(podcast)}
/>
)}
</For>
</box>
</scrollbox>
</Show>
</box>
</box>
</box>
</box>
);
}

View File

@@ -129,8 +129,14 @@ export function MyShowsPage() {
}
>
<scrollbox
border
height="100%"
focused={nav.activeDepth == MyShowsPaneType.SHOWS}
borderColor={
nav.activeDepth() == MyShowsPaneType.SHOWS
? theme.accent
: theme.border
}
focused={nav.activeDepth() == MyShowsPaneType.SHOWS}
>
<For each={shows()}>
{(feed, index) => (
@@ -171,26 +177,32 @@ export function MyShowsPage() {
</Show>
</box>
<box flexDirection="column" height="100%">
<Show
when={selectedShow()}
fallback={
<box padding={1}>
<text fg={theme.muted}>Select a show</text>
</box>
}
>
<Show
when={episodes().length > 0}
when={selectedShow()}
fallback={
<box padding={1}>
<text fg={theme.muted}>No episodes. Press [r] to refresh.</text>
<text fg={theme.muted}>Select a show</text>
</box>
}
>
<scrollbox
height="100%"
focused={nav.activeDepth == MyShowsPaneType.EPISODES}
<Show
when={episodes().length > 0}
fallback={
<box padding={1}>
<text fg={theme.muted}>No episodes. Press [r] to refresh.</text>
</box>
}
>
<scrollbox
border
height="100%"
borderColor={
nav.activeDepth() == MyShowsPaneType.EPISODES
? theme.accent
: theme.border
}
focused={nav.activeDepth() == MyShowsPaneType.EPISODES}
>
<For each={episodes()}>
{(episode, index) => (
<box

View File

@@ -3,6 +3,7 @@ import { RealtimeWaveform } from "./RealtimeWaveform";
import { useAudio } from "@/hooks/useAudio";
import { useAppStore } from "@/stores/app";
import { useTheme } from "@/context/ThemeContext";
import { useNavigation } from "@/context/NavigationContext";
enum PlayerPaneType {
PLAYER = 1,
@@ -12,6 +13,7 @@ export const PlayerPaneCount = 1;
export function PlayerPage() {
const audio = useAudio();
const { theme } = useTheme();
const nav = useNavigation();
const progressPercent = () => {
const d = audio.duration();
@@ -41,7 +43,7 @@ export function PlayerPage() {
<box
border
borderColor={theme.border}
borderColor={nav.activeDepth() == PlayerPaneType.PLAYER ? theme.accent : theme.border}
padding={1}
flexDirection="column"
gap={1}

View File

@@ -69,7 +69,7 @@ export function SearchPage() {
setInputValue(value);
}}
placeholder="Enter podcast name, topic, or author..."
focused={nav.activeDepth === SearchPaneType.INPUT}
focused={nav.activeDepth() === SearchPaneType.INPUT}
width={50}
/>
<box
@@ -92,76 +92,80 @@ export function SearchPage() {
</Show>
</box>
{/* Main Content - Results or History */}
<box flexDirection="row" height="100%" gap={2}>
{/* Results Panel */}
<box
flexDirection="column"
flexGrow={1}
border
borderColor={theme.border}
>
<box padding={1}>
<text
fg={
nav.activeDepth === SearchPaneType.RESULTS
? theme.primary
: theme.muted
}
>
Results ({searchStore.results().length})
</text>
</box>
<Show
when={searchStore.results().length > 0}
fallback={
<box padding={2}>
<text fg={theme.muted}>
{searchStore.query()
? "No results found"
: "Enter a search term to find podcasts"}
</text>
</box>
{/* Main Content - Results or History */}
<box flexDirection="row" height="100%" gap={2}>
{/* Results Panel */}
<box
flexDirection="column"
flexGrow={1}
border
borderColor={
nav.activeDepth() === SearchPaneType.RESULTS
? theme.accent
: theme.border
}
>
<SearchResults
results={searchStore.results()}
selectedIndex={resultIndex()}
focused={nav.activeDepth === SearchPaneType.RESULTS}
onSelect={handleResultSelect}
onChange={setResultIndex}
isSearching={searchStore.isSearching()}
error={searchStore.error()}
/>
</Show>
</box>
{/* History Sidebar */}
<box width={30} border borderColor={theme.border}>
<box padding={1} flexDirection="column">
<box paddingBottom={1}>
<box padding={1}>
<text
fg={
nav.activeDepth === SearchPaneType.HISTORY
nav.activeDepth() === SearchPaneType.RESULTS
? theme.primary
: theme.muted
}
>
History
Results ({searchStore.results().length})
</text>
</box>
<SearchHistory
history={searchStore.history()}
selectedIndex={historyIndex()}
focused={nav.activeDepth === SearchPaneType.HISTORY}
onSelect={handleHistorySelect}
onRemove={searchStore.removeFromHistory}
onClear={searchStore.clearHistory}
onChange={setHistoryIndex}
/>
<Show
when={searchStore.results().length > 0}
fallback={
<box padding={2}>
<text fg={theme.muted}>
{searchStore.query()
? "No results found"
: "Enter a search term to find podcasts"}
</text>
</box>
}
>
<SearchResults
results={searchStore.results()}
selectedIndex={resultIndex()}
focused={nav.activeDepth() === SearchPaneType.RESULTS}
onSelect={handleResultSelect}
onChange={setResultIndex}
isSearching={searchStore.isSearching()}
error={searchStore.error()}
/>
</Show>
</box>
{/* History Sidebar */}
<box width={30} border borderColor={theme.border}>
<box padding={1} flexDirection="column">
<box paddingBottom={1}>
<text
fg={
nav.activeDepth() === SearchPaneType.HISTORY
? theme.primary
: theme.muted
}
>
History
</text>
</box>
<SearchHistory
history={searchStore.history()}
selectedIndex={historyIndex()}
focused={nav.activeDepth() === SearchPaneType.HISTORY}
onSelect={handleHistorySelect}
onRemove={searchStore.removeFromHistory}
onClear={searchStore.clearHistory}
onChange={setHistoryIndex}
/>
</box>
</box>
</box>
</box>
</box>
);
}

View File

@@ -28,6 +28,11 @@ export function SettingsPage() {
const { theme } = useTheme();
const nav = useNavigation();
// Helper function to check if a depth is active
const isActive = (depth: SettingsPaneType): boolean => {
return nav.activeDepth() === depth;
};
return (
<box flexDirection="column" gap={1} height="100%" width="100%">
<box flexDirection="row" gap={1}>
@@ -56,23 +61,23 @@ export function SettingsPage() {
<box
border
borderColor={theme.border}
borderColor={isActive(SettingsPaneType.SYNC) || isActive(SettingsPaneType.SOURCES) || isActive(SettingsPaneType.PREFERENCES) || isActive(SettingsPaneType.VISUALIZER) || isActive(SettingsPaneType.ACCOUNT) ? theme.accent : theme.border}
flexGrow={1}
padding={1}
flexDirection="column"
gap={1}
>
{nav.activeDepth === SettingsPaneType.SYNC && <SyncPanel />}
{nav.activeDepth === SettingsPaneType.SOURCES && (
{isActive(SettingsPaneType.SYNC) && <SyncPanel />}
{isActive(SettingsPaneType.SOURCES) && (
<SourceManager focused />
)}
{nav.activeDepth === SettingsPaneType.PREFERENCES && (
{isActive(SettingsPaneType.PREFERENCES) && (
<PreferencesPanel />
)}
{nav.activeDepth === SettingsPaneType.VISUALIZER && (
{isActive(SettingsPaneType.VISUALIZER) && (
<VisualizerSettings />
)}
{nav.activeDepth === SettingsPaneType.ACCOUNT && (
{isActive(SettingsPaneType.ACCOUNT) && (
<box flexDirection="column" gap={1}>
<text fg={theme.textMuted}>Account</text>
</box>