Skip to content

Commit

Permalink
feat(views): use combined statusbar and view title
Browse files Browse the repository at this point in the history
  • Loading branch information
Garrett Downs committed Dec 1, 2021
1 parent cb63db4 commit d3884a6
Show file tree
Hide file tree
Showing 22 changed files with 245 additions and 224 deletions.
25 changes: 25 additions & 0 deletions src/components/Statusbar.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.root {
display: flex;
align-items: center;
padding: 0px 5px 0px 5px;
font-size: 1.2rem;
font-weight: bold;
}

.root > div {
margin-left: 5px;
}
.root > div:first-child {
margin-left: 0px;
}

.text {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.battery > span {
font-size: 1rem;
}
79 changes: 79 additions & 0 deletions src/components/Statusbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { format } from 'date-fns';
import { h, VNode } from 'preact';
import { useEffect, useState } from 'preact/hooks';
import { ComponentBaseProps } from '../models';
import { KaiOS } from '../services/kaios';
import styles from './Statusbar.module.css';

type StatusbarProps = ComponentBaseProps & {
text?: string;
};

export default function Statusbar(props: StatusbarProps): VNode {
const [time, setTime] = useState(new Date());
const [battery, setBattery] = useState(0);
const [connection, setConnection] = useState<'wifi' | 'cellular' | 'none'>('none');

useEffect(() => {
const timeInterval = setInterval(() => setTime(new Date()), 1000);

setBattery(KaiOS.battery.level * 100);
const handleLevelChange = () => setBattery(KaiOS.battery.level * 100);
KaiOS.battery.addEventListener('levelchange', handleLevelChange);

setConnection(KaiOS.connection.type);
const handleTypeChange = () => setConnection(KaiOS.connection.type);
KaiOS.connection.addEventListener('typechange', handleTypeChange);

return () => {
clearInterval(timeInterval);
KaiOS.battery.removeEventListener('levelchange', handleLevelChange);
KaiOS.connection.removeEventListener('typechange', handleTypeChange);
};
}, []);

function renderIcon() {
switch (connection) {
case 'cellular':
return (
<svg
xmlns="http://www.w3.org/2000/svg"
height="18px"
viewBox="0 0 24 24"
width="18px"
fill="var(--primary-text-color)"
>
<path d="M0 0h24v24H0V0z" fill="none" />
<path d="M17 4h3v16h-3V4zM5 14h3v6H5v-6zm6-5h3v11h-3V9z" />
</svg>
);
case 'wifi':
return (
<svg
xmlns="http://www.w3.org/2000/svg"
height="18px"
viewBox="0 0 24 24"
width="18px"
fill="var(--primary-text-color)"
>
<path d="M0 0h24v24H0V0zm0 0h24v24H0V0z" fill="none" />
<path d="M1 9l2 2c4.97-4.97 13.03-4.97 18 0l2-2C16.93 2.93 7.08 2.93 1 9zm8 8l3 3 3-3c-1.65-1.66-4.34-1.66-6 0zm-4-4l2 2c2.76-2.76 7.24-2.76 10 0l2-2C15.14 9.14 8.87 9.14 5 13z" />
</svg>
);
default:
return null;
}
}

return (
<div className={styles.root}>
<div className={styles.text}>{props.text}</div>
{renderIcon()}
<div className={styles.battery}>
{battery}
<span>%</span>
</div>
<div className={styles.time}>{format(time, 'h:mm')}</div>
</div>
);
}
49 changes: 12 additions & 37 deletions src/routes/AppSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
import { AppBar } from 'mai-ui/dist/components/appbar';
import {
Input,
RangeRow,
Select,
ToggleRow,
} from 'mai-ui/dist/components/form';
import {
View,
ViewHeader,
ViewTab,
ViewTabBar,
} from 'mai-ui/dist/components/view';
import { Input, RangeRow, Select, ToggleRow } from 'mai-ui/dist/components/form';
import { View, ViewTab, ViewTabBar } from 'mai-ui/dist/components/view';
import { useListNav } from 'mai-ui/dist/hooks';
import { h, VNode } from 'preact';
import { route } from 'preact-router';
import { FoxcastsAppMenu } from '../components/FoxcastsAppMenu';
import Statusbar from '../components/Statusbar';
import { useSettings } from '../contexts/SettingsProvider';
import { SelectablePriority } from '../enums';
import {
Expand All @@ -40,10 +31,7 @@ export default function AppSettings({ tabId }: Props): VNode {
updateRouteOnChange: false,
});

function handleSettingSelect<T extends keyof Settings>(
key: T,
value: Settings[T]
): void {
function handleSettingSelect<T extends keyof Settings>(key: T, value: Settings[T]): void {
if (key === 'theme') {
// We want to use the theme's original accent color
const theme = themes.find((a) => a.id === value) as ThemeConfig;
Expand All @@ -59,7 +47,7 @@ export default function AppSettings({ tabId }: Props): VNode {

return (
<View>
<ViewHeader>Settings</ViewHeader>
<Statusbar text="Settings" />
<ViewTabBar
tabs={[
{ id: 'display', label: 'display' },
Expand Down Expand Up @@ -150,8 +138,7 @@ export default function AppSettings({ tabId }: Props): VNode {
selected: selectedId === 'accentColor',
}}
onChange={(value) =>
value.match(/[0-9a-fA-F]{6}/) &&
handleSettingSelect('accentColor', value)
value.match(/[0-9a-fA-F]{6}/) && handleSettingSelect('accentColor', value)
}
/>
<ToggleRow
Expand All @@ -170,9 +157,7 @@ export default function AppSettings({ tabId }: Props): VNode {
id: 'dynamicThemeColor',
selected: selectedId === 'dynamicThemeColor',
}}
onChange={(value): void =>
handleSettingSelect('dynamicThemeColor', value)
}
onChange={(value): void => handleSettingSelect('dynamicThemeColor', value)}
/>
<ToggleRow
label="Dynamic Background"
Expand All @@ -181,9 +166,7 @@ export default function AppSettings({ tabId }: Props): VNode {
id: 'dynamicBackgrounds',
selected: selectedId === 'dynamicBackgrounds',
}}
onChange={(value): void =>
handleSettingSelect('dynamicBackgrounds', value)
}
onChange={(value): void => handleSettingSelect('dynamicBackgrounds', value)}
/>
</ViewTab>
<ViewTab tabId="player" activeTabId={tabId}>
Expand Down Expand Up @@ -224,9 +207,7 @@ export default function AppSettings({ tabId }: Props): VNode {
id: 'playbackSkipBack',
selected: selectedId === 'playbackSkipBack',
}}
onChange={(value): void =>
handleSettingSelect('playbackSkipBack', value)
}
onChange={(value): void => handleSettingSelect('playbackSkipBack', value)}
/>
<RangeRow
label="Skip Forward"
Expand All @@ -239,9 +220,7 @@ export default function AppSettings({ tabId }: Props): VNode {
id: 'playbackSkipForward',
selected: selectedId === 'playbackSkipForward',
}}
onChange={(value): void =>
handleSettingSelect('playbackSkipForward', value)
}
onChange={(value): void => handleSettingSelect('playbackSkipForward', value)}
/>
<RangeRow
label="Playback Speed"
Expand All @@ -254,9 +233,7 @@ export default function AppSettings({ tabId }: Props): VNode {
id: 'playbackSpeed',
selected: selectedId === 'playbackSpeed',
}}
onChange={(value): void =>
handleSettingSelect('playbackSpeed', value)
}
onChange={(value): void => handleSettingSelect('playbackSpeed', value)}
/>
<ToggleRow
label="Auto Delete Download"
Expand All @@ -266,9 +243,7 @@ export default function AppSettings({ tabId }: Props): VNode {
id: 'autoDeleteDownload',
selected: selectedId === 'autoDeleteDownload',
}}
onChange={(value): void =>
handleSettingSelect('autoDeleteDownload', value)
}
onChange={(value): void => handleSettingSelect('autoDeleteDownload', value)}
/>
</ViewTab>
<AppBar appMenuContent={<FoxcastsAppMenu />} />
Expand Down
23 changes: 7 additions & 16 deletions src/routes/Downloads.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { formatFileSize } from 'foxcasts-core/lib/utils';
import { AppBar, AppBarAction } from 'mai-ui/dist/components/appbar';
import { ListItem } from 'mai-ui/dist/components/list';
import { Typography } from 'mai-ui/dist/components/Typography';
import { View, ViewContent, ViewHeader } from 'mai-ui/dist/components/view';
import { View, ViewContent } from 'mai-ui/dist/components/view';
import { useListNav } from 'mai-ui/dist/hooks';
import { Fragment, h, VNode } from 'preact';
import { route } from 'preact-router';
import { useEffect, useState } from 'preact/hooks';
import { FoxcastsAppMenu } from '../components/FoxcastsAppMenu';
import ProgressBar from '../components/ProgressBar';
import Statusbar from '../components/Statusbar';
import { useDownloadManager } from '../contexts/DownloadManagerProvider';
import { Download, DownloadStatus } from '../models';
import styles from './Downloads.module.css';
Expand Down Expand Up @@ -90,26 +91,19 @@ export default function Downloads({ selectedItemId }: Props): VNode {

const bytes = (item.currentBytes / item.totalBytes) * 100 || 0;
if (bytes < 100) {
return `${formatFileSize(item.currentBytes)}/${formatFileSize(
item.totalBytes
)}`;
return `${formatFileSize(item.currentBytes)}/${formatFileSize(item.totalBytes)}`;
}

return 'Complete';
}

function getActions(): AppBarAction[] {
const actions: AppBarAction[] = [
{ id: 'test', label: 'Test', actionFn: () => runTest() },
];
const actions: AppBarAction[] = [{ id: 'test', label: 'Test', actionFn: () => runTest() }];

const item = getSelectedItem();
if (!item) return actions;

if (
item.status === DownloadStatus.Queued ||
item.status === DownloadStatus.Downloading
) {
if (item.status === DownloadStatus.Queued || item.status === DownloadStatus.Downloading) {
actions.push({
id: 'remove',
label: 'Cancel download',
Expand All @@ -118,10 +112,7 @@ export default function Downloads({ selectedItemId }: Props): VNode {
route(`/downloads/`, true);
},
});
} else if (
item.status === DownloadStatus.Cancelled ||
item.status === DownloadStatus.Error
) {
} else if (item.status === DownloadStatus.Cancelled || item.status === DownloadStatus.Error) {
actions.push({
id: 'retry',
label: 'Retry download',
Expand All @@ -143,7 +134,7 @@ export default function Downloads({ selectedItemId }: Props): VNode {

return (
<View>
<ViewHeader>Downloads</ViewHeader>
<Statusbar text="Downloads" />
<ViewContent>
{downloads.downloading.map((item) => (
<div key={item.episodeId}>
Expand Down
43 changes: 12 additions & 31 deletions src/routes/EpisodeDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Fragment, h, VNode } from 'preact';
import { route } from 'preact-router';
import { useEffect, useState } from 'preact/hooks';
import { FoxcastsAppMenu } from '../components/FoxcastsAppMenu';
import Statusbar from '../components/Statusbar';
import { useDownloadManager } from '../contexts/DownloadManagerProvider';
import { usePlayer } from '../contexts/playerContext';
import { useSettings } from '../contexts/SettingsProvider';
Expand All @@ -25,13 +26,12 @@ interface EpisodeDetailProps {
tabId: string;
}

export default function EpisodeDetail({
episodeId,
tabId,
}: EpisodeDetailProps): VNode {
export default function EpisodeDetail({ episodeId, tabId }: EpisodeDetailProps): VNode {
const [episode, setEpisode] = useState<EpisodeExtended>();
const [chapters, setChapters] = useState<Chapter[] | null>();

console.log(episode);

const player = usePlayer();
const { addToQueue } = useDownloadManager();
const { settings } = useSettings();
Expand All @@ -54,13 +54,8 @@ export default function EpisodeDetail({

const { selectedId } = useListNav({
onSelect: (itemId) => {
if (
itemId.startsWith('chapter') &&
chapters &&
Number(episodeId) === player.episode?.id
) {
if (itemId.startsWith('chapter') && chapters && Number(episodeId) === player.episode?.id) {
const index = parseInt(itemId.split('_')[1], 10);
console.log('chapter selected', index);
player.goTo(Math.floor(chapters[index].startTime / 1000));
}
},
Expand Down Expand Up @@ -90,9 +85,7 @@ export default function EpisodeDetail({
},
{
id: 'toggleFavorite',
label: episode.isFavorite
? 'Remove from favorites'
: 'Add to favorites',
label: episode.isFavorite ? 'Remove from favorites' : 'Add to favorites',
actionFn: () =>
Core.episodes
.update(episode.id, {
Expand Down Expand Up @@ -138,14 +131,11 @@ export default function EpisodeDetail({

return (
<View
backgroundImageUrl={
settings.dynamicBackgrounds ? artwork?.image : undefined
}
accentColor={
settings.dynamicThemeColor ? episode?.accentColor : undefined
}
backgroundImageUrl={settings.dynamicBackgrounds ? artwork?.image : undefined}
accentColor={settings.dynamicThemeColor ? episode?.accentColor : undefined}
enableCustomColor={true}
>
<Statusbar text={episode?.podcastTitle} />
<ViewTabBar
tabs={[
{ id: 'info', label: 'info' },
Expand All @@ -165,11 +155,7 @@ export default function EpisodeDetail({
<Fragment>
<LabeledRow
label="Published"
text={
episode
? format(new Date(episode.date), 'ccc, MMMM do p')
: null
}
text={episode ? format(new Date(episode.date), 'ccc, MMMM do p') : null}
/>
<LabeledRow
label="Progress"
Expand All @@ -179,14 +165,9 @@ export default function EpisodeDetail({
/>
<LabeledRow
label="File Size"
text={
episode.fileSize ? formatFileSize(episode?.fileSize) : 'Unknown'
}
/>
<LabeledRow
label="Downloaded"
text={episode.localFileUrl || 'No'}
text={episode.fileSize ? formatFileSize(episode?.fileSize) : 'Unknown'}
/>
<LabeledRow label="Downloaded" text={episode.localFileUrl || 'No'} />
</Fragment>
) : null}

Expand Down
Loading

0 comments on commit d3884a6

Please sign in to comment.