add settings for autoplay gifs and vids

This commit is contained in:
thislight 2024-10-09 18:45:19 +08:00
parent c8f2179298
commit 7d3c97c56b
7 changed files with 153 additions and 14 deletions

View file

@ -25,13 +25,17 @@ const AccountMastodonOAuth2Callback = lazy(
const TimelineHome = lazy(() => import("./timelines/Home.js"));
const Settings = lazy(() => import("./settings/Settings.js"));
const TootBottomSheet = lazy(() => import("./timelines/TootBottomSheet.js"));
const MotionSettings = lazy(() => import("./settings/Motions.js"));
const Routing: Component = () => {
return (
<Router>
<Route path="/" component={TimelineHome}>
<Route path=""></Route>
<Route path="/settings" component={Settings}></Route>
<Route path="/settings" component={Settings}>
<Route path=""></Route>
<Route path="/motions" component={MotionSettings}></Route>
</Route>
<Route path="/:acct/:id" component={TootBottomSheet}></Route>
</Route>
<Route path={"/accounts"}>

89
src/settings/Motions.tsx Normal file
View file

@ -0,0 +1,89 @@
import type { Component } from "solid-js";
import Scaffold from "../material/Scaffold";
import {
AppBar,
Divider,
IconButton,
List,
ListItemButton,
ListItemSecondaryAction,
ListItemText,
ListSubheader,
Switch,
Toolbar,
} from "@suid/material";
import { Title } from "../material/typography";
import { useNavigate } from "@solidjs/router";
import { Close as CloseIcon } from "@suid/icons-material";
import { createTranslator } from "../platform/i18n";
import { useStore } from "@nanostores/solid";
import { $settings } from "./stores";
const Motions: Component = () => {
const navigate = useNavigate();
const [t] = createTranslator(
(code) =>
import(`./i18n/${code}.json`) as Promise<{
default: Record<string, string | undefined>;
}>,
);
const settings = useStore($settings);
return (
<Scaffold
topbar={
<AppBar position="static">
<Toolbar
variant="dense"
sx={{ paddingTop: "var(--safe-area-inset-top, 0px)" }}
>
<IconButton color="inherit" onClick={[navigate, -1]} disableRipple>
<CloseIcon />
</IconButton>
<Title>{t("motions")}</Title>
</Toolbar>
</AppBar>
}
>
<List
sx={{
paddingBottom: "calc(var(--safe-area-inset-bottom, 0px) + 16px)",
}}
>
<li>
<ul style={{ "padding-left": 0 }}>
<ListSubheader>{t("motions.gifs")}</ListSubheader>
<ListItemButton
onClick={() =>
$settings.setKey("autoPlayGIFs", !settings().autoPlayGIFs)
}
>
<ListItemText>{t("motions.gifs.autoplay")}</ListItemText>
<ListItemSecondaryAction>
<Switch checked={settings().autoPlayGIFs}></Switch>
</ListItemSecondaryAction>
</ListItemButton>
<Divider />
</ul>
</li>
<li>
<ul style={{ "padding-left": 0 }}>
<ListSubheader>{t("motions.vids")}</ListSubheader>
<ListItemButton
onClick={() =>
$settings.setKey("autoPlayVideos", !settings().autoPlayVideos)
}
>
<ListItemText>{t("motions.vids.autoplay")}</ListItemText>
<ListItemSecondaryAction>
<Switch checked={settings().autoPlayVideos}></Switch>
</ListItemSecondaryAction>
</ListItemButton>
<Divider />
</ul>
</li>
</List>
</Scaffold>
);
};
export default Motions;

View file

@ -1,4 +1,10 @@
import { createSignal, For, Show, type ParentComponent } from "solid-js";
import {
children,
createSignal,
For,
Show,
type ParentComponent,
} from "solid-js";
import Scaffold from "../material/Scaffold.js";
import {
AppBar,
@ -11,18 +17,18 @@ import {
ListItemSecondaryAction,
ListItemText,
ListSubheader,
NativeSelect,
Switch,
Toolbar,
} from "@suid/material";
import {
Animation as AnimationIcon,
Close as CloseIcon,
Logout,
Public as PublicIcon,
Refresh as RefreshIcon,
Translate as TranslateIcon,
} from "@suid/icons-material";
import { useNavigate } from "@solidjs/router";
import { A, useNavigate } from "@solidjs/router";
import { Title } from "../material/typography.jsx";
import { css } from "solid-styled";
import { useSignedInProfiles } from "../masto/acct.js";
@ -43,12 +49,13 @@ import { type Template } from "@solid-primitives/i18n";
import BottomSheet from "../material/BottomSheet.jsx";
import ChooseLang from "./ChooseLang.jsx";
import ChooseRegion from "./ChooseRegion.jsx";
import { Portal } from "solid-js/web";
type Strings = {
["lang.auto"]: Template<{ detected: string }>;
} & Record<string, string | undefined>;
const Settings: ParentComponent = () => {
const Settings: ParentComponent = (props) => {
const [t] = createTranslator(
(code) =>
import(`./i18n/${code}.json`) as Promise<{
@ -71,6 +78,8 @@ const Settings: ParentComponent = () => {
signOut((a) => a.site === acct.site && a.accessToken === acct.accessToken);
};
const subpage = children(() => props.children);
css`
ul {
padding: 0;
@ -96,6 +105,10 @@ const Settings: ParentComponent = () => {
</AppBar>
}
>
<BottomSheet open={!!subpage()} onClose={() => navigate(-1)}>
{subpage()}
</BottomSheet>
<List class="setting-list" use:solid-styled>
<li>
<ul>
@ -135,7 +148,7 @@ const Settings: ParentComponent = () => {
</For>
</li>
<li>
<ListSubheader>{t("Reading")}</ListSubheader>
<ListSubheader>{t("timelines")}</ListSubheader>
<ListItemButton
onClick={(e) =>
$settings.setKey(
@ -152,6 +165,13 @@ const Settings: ParentComponent = () => {
</ListItemSecondaryAction>
</ListItemButton>
<Divider />
<ListItemButton component={A} href="./motions">
<ListItemIcon>
<AnimationIcon></AnimationIcon>
</ListItemIcon>
<ListItemText>{t("motions")}</ListItemText>
</ListItemButton>
<Divider />
</li>
<li>
<ListSubheader>{t("This Application")}</ListSubheader>

View file

@ -3,7 +3,7 @@
"Accounts": "Accounts",
"All Notifications": "All Notifications",
"Sign in...": "Sign in...",
"Reading": "Reading",
"timelines": "Timelines and Toot Lists",
"Prefetch Toots": "Prefetch Toots",
"Prefetch Toots.2nd": "Tutu will download the toots before you need.",
"This Application": "This Application",
@ -26,5 +26,11 @@
"Choose Language": "Choose Language",
"Supported": "Supported",
"Unsupported": "Unsupported",
"Choose Region": "Choose Region"
"Choose Region": "Choose Region",
"motions": "GIFs and Videos",
"motions.gifs": "GIFs",
"motions.gifs.autoplay": "Auto-play GIFs",
"motions.vids": "Videos",
"motions.vids.autoplay": "Auto-play Videos"
}

View file

@ -3,7 +3,7 @@
"Accounts": "所有账户",
"All Notifications": "所有通知",
"Sign in...": "登录新账户...",
"Reading": "阅读",
"timelines": "时间线和嘟文列表",
"Prefetch Toots": "提前下载嘟文",
"Prefetch Toots.2nd": "图图会在你可能需要的时候提前下载嘟文。",
"This Application": "本应用",
@ -26,5 +26,11 @@
"Choose Language": "选择语言",
"Supported": "已支持",
"Unsupported": "尚未支持",
"Choose Region": "选择区域"
"Choose Region": "选择区域",
"motions": "动图和视频",
"motions.gifs": "动图",
"motions.gifs.autoplay": "自动播放动图",
"motions.vids": "视频",
"motions.vids.autoplay": "自动播放视频"
}

View file

@ -5,6 +5,10 @@ type Settings = {
prefetchTootsDisabled?: boolean;
language?: string;
region?: string;
// GIFs and Videos
autoPlayGIFs?: boolean;
autoPlayVideos?: boolean;
};
export const $settings = persistentMap<Settings>(

View file

@ -13,6 +13,8 @@ import tootStyle from "./toot.module.css";
import MediaViewer from "./MediaViewer";
import { render } from "solid-js/web";
import { useWindowSize } from "@solid-primitives/resize-observer";
import { useStore } from "@nanostores/solid";
import { $settings } from "../settings/stores";
const MediaAttachmentGrid: Component<{
attachments: mastodon.v1.MediaAttachment[];
@ -22,6 +24,7 @@ const MediaAttachmentGrid: Component<{
const viewerOpened = () => typeof viewerIndex() !== "undefined";
const windowSize = useWindowSize();
const vh35 = () => Math.floor(windowSize.height * 0.35);
const settings = useStore($settings);
createRenderEffect((lastDispose?: () => void) => {
lastDispose?.();
@ -70,7 +73,11 @@ const MediaAttachmentGrid: Component<{
<section
ref={rootRef!}
class={[tootStyle.tootAttachmentGrp, "attachments"].join(" ")}
onClick={(e) => e.stopImmediatePropagation()}
onClick={(e) => {
if (e.target !== e.currentTarget) {
e.stopImmediatePropagation();
}
}}
>
<For each={props.attachments}>
{(item, index) => {
@ -109,20 +116,23 @@ const MediaAttachmentGrid: Component<{
src={item.url || undefined}
style={style()}
onLoadedMetadata={[setLoaded, true]}
autoplay={false}
autoplay={settings().autoPlayVideos}
playsinline={settings().autoPlayVideos ? true : undefined}
controls
poster={item.previewUrl}
/>
);
case "gifv": // Later we can handle the preview
case "gifv":
return (
<video
src={item.url || undefined}
style={style()}
onLoadedMetadata={[setLoaded, true]}
autoplay={false}
autoplay={settings().autoPlayGIFs}
controls
playsinline /* or safari on iOS will play in full-screen */
loop
poster={item.previewUrl}
/>
);