ReplyEditor: promote the blur condition up

This commit is contained in:
thislight 2024-09-25 21:24:39 +08:00
parent 6c98f1e78d
commit a1a587a77f
2 changed files with 23 additions and 21 deletions

View file

@ -1,4 +1,5 @@
import { import {
batch,
createSignal, createSignal,
createUniqueId, createUniqueId,
onMount, onMount,
@ -57,14 +58,12 @@ const TootVisibilityPickerDialog: Component<{
const discoverable = () => { const discoverable = () => {
return props.visibility === "public"; return props.visibility === "public";
}
const setDiscoverable = (setter: (v: boolean) => boolean) => {
const nval = setter(discoverable())
props.onVisibilityChange(nval ? "public" : "unlisted"); // trigger change
}; };
const setDiscoverable = (setter: (v: boolean) => boolean) => {
const nval = setter(discoverable());
props.onVisibilityChange(nval ? "public" : "unlisted"); // trigger change
};
return ( return (
<BottomSheet open={props.open} onClose={props.onClose} bottomUp> <BottomSheet open={props.open} onClose={props.onClose} bottomUp>
@ -83,7 +82,7 @@ const TootVisibilityPickerDialog: Component<{
</div> </div>
} }
> >
<List> <List dense>
<ListItemButton onClick={[setKind, "public"]}> <ListItemButton onClick={[setKind, "public"]}>
<ListItemIcon> <ListItemIcon>
<PublicIcon /> <PublicIcon />
@ -155,27 +154,29 @@ const TootVisibilityPickerDialog: Component<{
const ReplyEditor: Component<{ const ReplyEditor: Component<{
profile: Account; profile: Account;
replyToDisplayName: string; replyToDisplayName: string;
isTyping?: boolean
onTypingChange: (value: boolean) => void
}> = (props) => { }> = (props) => {
let inputRef: HTMLTextAreaElement; let inputRef: HTMLTextAreaElement;
const buttonId = createUniqueId(); const buttonId = createUniqueId();
const menuId = createUniqueId(); const menuId = createUniqueId();
const [typing, setTyping] = createSignal(false); const typing = () => props.isTyping
const setTyping = (v: boolean) => props.onTypingChange(v)
const [visibility, setVisibility] = createSignal<TootVisibility>("public"); const [visibility, setVisibility] = createSignal<TootVisibility>("public");
const [permPicker, setPermPicker] = createSignal(false); const [permPicker, setPermPicker] = createSignal(false);
onMount(() => { onMount(() => {
makeEventListener(inputRef, "focus", () => setTyping(true)); makeEventListener(inputRef, "focus", () => setTyping(true));
makeEventListener(inputRef, "blur", () => setTyping(false));
}); });
const containerStyle = () => const containerStyle = () =>
typing() typing() || permPicker()
? { ? {
position: "sticky" as const, position: "sticky" as const,
top: "var(--scaffold-topbar-height, 0)", top: "var(--scaffold-topbar-height, 0)",
bottom: "var(--safe-area-inset-bottom, 0)", bottom: "var(--safe-area-inset-bottom, 0)",
"z-index": 1, "z-index": 2,
} }
: undefined; : undefined;
@ -196,7 +197,7 @@ const ReplyEditor: Component<{
<div <div
class={tootComposers.composer} class={tootComposers.composer}
style={containerStyle()} style={containerStyle()}
onClick={() => setTyping(true)} onClick={(e) => inputRef.focus()}
> >
<div class={tootComposers.replyInput}> <div class={tootComposers.replyInput}>
<Avatar src={props.profile.inf?.avatar} /> <Avatar src={props.profile.inf?.avatar} />
@ -219,7 +220,7 @@ const ReplyEditor: Component<{
> >
<Button onClick={[setPermPicker, true]} id={buttonId}> <Button onClick={[setPermPicker, true]} id={buttonId}>
{visibilityText()} {visibilityText()}
<ArrowDropDown /> <ArrowDropDown sx={{ marginTop: "-0.25em" }} />
</Button> </Button>
</div> </div>

View file

@ -3,17 +3,13 @@ import {
createEffect, createEffect,
createRenderEffect, createRenderEffect,
createResource, createResource,
createSignal,
For, For,
Show, Show,
type Component, type Component,
} from "solid-js"; } from "solid-js";
import Scaffold from "../material/Scaffold"; import Scaffold from "../material/Scaffold";
import { import { AppBar, CircularProgress, IconButton, Toolbar } from "@suid/material";
AppBar,
CircularProgress,
IconButton,
Toolbar,
} from "@suid/material";
import { Title } from "../material/typography"; import { Title } from "../material/typography";
import { import {
ArrowBack as BackIcon, ArrowBack as BackIcon,
@ -41,14 +37,13 @@ function getCache(acct: string, id: string) {
} }
} }
const TootBottomSheet: Component = (props) => { const TootBottomSheet: Component = (props) => {
const params = useParams<{ acct: string; id: string }>(); const params = useParams<{ acct: string; id: string }>();
const location = useLocation<{ tootBottomSheetPushedCount?: number }>(); const location = useLocation<{ tootBottomSheetPushedCount?: number }>();
const navigate = useNavigate(); const navigate = useNavigate();
const allSession = useSessions(); const allSession = useSessions();
const time = createTimeSource(); const time = createTimeSource();
const [isInTyping, setInTyping] = createSignal(false);
const acctText = () => decodeURIComponent(params.acct); const acctText = () => decodeURIComponent(params.acct);
const session = () => { const session = () => {
const [inputUsername, inputSite] = acctText().split("@", 2); const [inputUsername, inputSite] = acctText().split("@", 2);
@ -164,6 +159,10 @@ const TootBottomSheet: Component = (props) => {
}; };
const switchContext = (status: mastodon.v1.Status) => { const switchContext = (status: mastodon.v1.Status) => {
if (isInTyping()) {
setInTyping(false);
return;
}
setCache(params.acct, status); setCache(params.acct, status);
navigate(`/${params.acct}/${status.id}`, { navigate(`/${params.acct}/${status.id}`, {
state: { state: {
@ -240,6 +239,8 @@ const TootBottomSheet: Component = (props) => {
<Show when={profile()}> <Show when={profile()}>
<ReplyEditor <ReplyEditor
isTyping={isInTyping()}
onTypingChange={setInTyping}
profile={profile()!} profile={profile()!}
replyToDisplayName={toot()?.account?.displayName || ""} replyToDisplayName={toot()?.account?.displayName || ""}
/> />