format code using prettier

This commit is contained in:
thislight 2024-08-05 15:33:00 +08:00
parent 91999a6303
commit abde6817f0
27 changed files with 326 additions and 260 deletions

View file

@ -9,4 +9,4 @@
.custom-emoji {
width: 1.25em;
}
}

View file

@ -44,12 +44,12 @@ const MastodonOAuth2Callback: Component = () => {
setDocumentTitle(`Back from ${ins.title}...`);
setSiteTitle(ins.title);
const srcset = []
const srcset = [];
if (ins.thumbnail.versions["@1x"]) {
srcset.push(`${ins.thumbnail.versions["@1x"]} 1x`)
srcset.push(`${ins.thumbnail.versions["@1x"]} 1x`);
}
if (ins.thumbnail.versions["@2x"]) {
srcset.push(`${ins.thumbnail.versions["@2x"]} 2x`)
srcset.push(`${ins.thumbnail.versions["@2x"]} 2x`);
}
setSiteImg({
@ -66,8 +66,8 @@ const MastodonOAuth2Callback: Component = () => {
onGoingOAuth2Process,
params.code,
);
$settings.setKey('onGoingOAuth2Process', undefined)
navigate('/', {replace: true})
$settings.setKey("onGoingOAuth2Process", undefined);
navigate("/", { replace: true });
return;
}
@ -95,18 +95,27 @@ const MastodonOAuth2Callback: Component = () => {
<div class={cards.layoutCentered}>
<div class={cards.card} aria-busy="true" aria-describedby={progressId}>
<LinearProgress
class={[cards.cardNoPad, cards.cardGutSkip].join(' ')}
class={[cards.cardNoPad, cards.cardGutSkip].join(" ")}
id={progressId}
aria-labelledby={titleId}
/>
<Show when={siteImg()} fallback={<i aria-busy="true" aria-label="Preparing image..." style={{"height": "235px", display: "block"}}></i>}>
<Show
when={siteImg()}
fallback={
<i
aria-busy="true"
aria-label="Preparing image..."
style={{ height: "235px", display: "block" }}
></i>
}
>
<Img
src={siteImg()?.src}
srcset={siteImg()?.srcset}
blurhash={siteImg()?.blurhash}
class={[cards.cardNoPad, cards.cardGutSkip].join(' ')}
class={[cards.cardNoPad, cards.cardGutSkip].join(" ")}
alt={`Banner image for ${siteTitle()}`}
style={{"height": "235px", "display": "block"}}
style={{ height: "235px", display: "block" }}
/>
</Show>
@ -114,7 +123,8 @@ const MastodonOAuth2Callback: Component = () => {
Contracting {siteTitle}...
</Title>
<p>
If this page stays too long, you can close this page and sign in again.
If this page stays too long, you can close this page and sign in
again.
</p>
</div>
</div>

View file

@ -69,8 +69,8 @@ const SignIn: Component = () => {
});
onMount(() => {
$settings.setKey('onGoingOAuth2Process', undefined)
})
$settings.setKey("onGoingOAuth2Process", undefined);
});
const onStartOAuth2 = async (e: Event) => {
e.preventDefault();
@ -107,7 +107,7 @@ const SignIn: Component = () => {
for (const [k, v] of Object.entries(args)) {
searches.set(k, v);
}
$settings.setKey("onGoingOAuth2Process", url)
$settings.setKey("onGoingOAuth2Process", url);
window.location.href = authStart.toString();
} catch (e) {
setServerUrlHelperText(

View file

@ -95,9 +95,13 @@ export const updateAcctInf = action(
},
);
export const signOut = action($accounts, "signOut", ($store, predicate: (acct: Account) => boolean) => {
$store.set($store.get().filter(a => !predicate(a)));
});
export const signOut = action(
$accounts,
"signOut",
($store, predicate: (acct: Account) => boolean) => {
$store.set($store.get().filter((a) => !predicate(a)));
},
);
export type RegisteredApp = {
site: string;

View file

@ -1,5 +1,5 @@
import {render} from 'solid-js/web'
import App from './App.js'
import "./material/theme.css"
import { render } from "solid-js/web";
import App from "./App.js";
import "./material/theme.css";
render(() => <App />, document.getElementById("root")!)
render(() => <App />, document.getElementById("root")!);

View file

@ -12,9 +12,7 @@ type Timeline = {
}): mastodon.Paginator<mastodon.v1.Status[], unknown>;
};
export function useTimeline(
timeline: Accessor<Timeline>,
) {
export function useTimeline(timeline: Accessor<Timeline>) {
let minId: string | undefined;
let maxId: string | undefined;
let otl: Timeline | undefined;

View file

@ -1,5 +1,5 @@
.bottomSheet {
composes: surface from 'material.module.css';
composes: surface from "material.module.css";
border: none;
position: absolute;
left: 50%;
@ -29,4 +29,4 @@
height: 100dvh;
}
}
}
}

View file

@ -1,5 +1,5 @@
import { createEffect, type ParentComponent } from "solid-js";
import styles from './BottomSheet.module.css'
import styles from "./BottomSheet.module.css";
export type BottomSheetProps = {
open?: boolean;
@ -20,7 +20,11 @@ const BottomSheet: ParentComponent<BottomSheetProps> = (props) => {
}
});
return <dialog class={styles.bottomSheet} ref={element!}>{props.children}</dialog>;
return (
<dialog class={styles.bottomSheet} ref={element!}>
{props.children}
</dialog>
);
};
export default BottomSheet;

View file

@ -9,12 +9,12 @@ import materialStyles from "./material.module.css";
const Button: Component<JSX.ButtonHTMLAttributes<HTMLButtonElement>> = (
props,
) => {
const [managed, passthough] = splitProps(props, ["class", 'type']);
const [managed, passthough] = splitProps(props, ["class", "type"]);
const classes = () =>
managed.class
? [materialStyles.button, managed.class].join(" ")
: materialStyles.button;
const type = () => managed.type ?? 'button'
const type = () => managed.type ?? "button";
return <button type={type()} class={classes()} {...passthough}></button>;
};

View file

@ -1,5 +1,5 @@
.card {
composes: surface from 'material.module.css';
composes: surface from "material.module.css";
border-radius: 2px;
box-shadow: var(--tutu-shadow-e2);
transition: var(--tutu-transition-shadow);
@ -12,7 +12,7 @@
}
&:not(.manualMargin) {
&>:not(.cardNoPad) {
& > :not(.cardNoPad) {
margin-inline: var(--card-pad, 20px);
}
@ -20,7 +20,7 @@
margin-top: var(--card-gut, 20px);
}
>.cardGutSkip+*:not(.cardGutSkip) {
> .cardGutSkip + *:not(.cardGutSkip) {
margin-top: var(--card-gut, 20px);
}
@ -28,7 +28,6 @@
margin-bottom: var(--card-gut, 20px);
}
}
}
.layoutCentered {
@ -52,4 +51,4 @@
overflow: auto;
}
}
}
}

View file

@ -1,5 +1,5 @@
.textfield {
composes: touchTarget from 'material.module.css';
composes: touchTarget from "material.module.css";
--border-color: var(--tutu-color-inactive-on-surface);
--active-border-color: var(--tutu-color-primary);
@ -7,74 +7,78 @@
--active-label-color: var(--tutu-color-primary);
--helper-text-color: var(--tutu-color-inactive-on-surface);
&>* {
width: 100%;
& > * {
width: 100%;
}
&.error, &:has(>input[aria-invalid="true"]) {
&:not(:focus-within) {
--border-color: var(--tutu-color-error-on-surface);
--label-color: var(--tutu-color-error-on-surface);
--helper-text-color: var(--tutu-color-error-on-surface);
}
&.error,
&:has(> input[aria-invalid="true"]) {
&:not(:focus-within) {
--border-color: var(--tutu-color-error-on-surface);
--label-color: var(--tutu-color-error-on-surface);
--helper-text-color: var(--tutu-color-error-on-surface);
}
&:focus-within {
--helper-text-color: var(--tutu-color-error-on-surface);
}
&:focus-within {
--helper-text-color: var(--tutu-color-error-on-surface);
}
}
position: relative;
&>label {
position: absolute;
left: 0;
bottom: calc(10px + var(--bottom-height, 0px));
color: var(--label-color);
transition: bottom .2s ease-in-out, font-size .2s ease-in-out, color .2s ease-in-out;
cursor: text;
font-size: 0.8125rem;
& > label {
position: absolute;
left: 0;
bottom: calc(10px + var(--bottom-height, 0px));
color: var(--label-color);
transition:
bottom 0.2s ease-in-out,
font-size 0.2s ease-in-out,
color 0.2s ease-in-out;
cursor: text;
font-size: 0.8125rem;
}
&>label:has(+ input:not(:placeholder-shown)) {
bottom: calc(100% - 0.8125rem);
& > label:has(+ input:not(:placeholder-shown)) {
bottom: calc(100% - 0.8125rem);
}
&:focus-within>label, &.float-label>label {
bottom: calc(100% - 0.8125rem);
color: var(--active-label-color);
&:focus-within > label,
&.float-label > label {
bottom: calc(100% - 0.8125rem);
color: var(--active-label-color);
}
&>input[type='text'],
&>input[type='password'] {
border: none;
outline: none;
border-bottom: 1px solid var(--border-color);
background-color: transparent;
padding-top: 16px;
padding-bottom: 8px;
margin-bottom: 1px;
transition: border-color .2s ease-in-out;
& > input[type="text"],
& > input[type="password"] {
border: none;
outline: none;
border-bottom: 1px solid var(--border-color);
background-color: transparent;
padding-top: 16px;
padding-bottom: 8px;
margin-bottom: 1px;
transition: border-color 0.2s ease-in-out;
&:focus {
border-bottom: 2px solid var(--active-border-color);
margin-bottom: 0;
}
&:focus {
border-bottom: 2px solid var(--active-border-color);
margin-bottom: 0;
}
}
&.withHelperText {
--bottom-height: 0.8125rem;
--bottom-height: 0.8125rem;
}
& .helperText {
color: var(--helper-text-color);
font-size: 0.8125rem;
line-height: 100%;
-webkit-line-clamp: 1;
line-clamp: 1;
display: flex;
justify-content: space-between;
min-height: 0.8125rem;
cursor: auto;
color: var(--helper-text-color);
font-size: 0.8125rem;
line-height: 100%;
-webkit-line-clamp: 1;
line-clamp: 1;
display: flex;
justify-content: space-between;
min-height: 0.8125rem;
cursor: auto;
}
}
}

View file

@ -10,7 +10,7 @@
}
.button {
composes: buttonText from './typography.module.css';
composes: buttonText from "./typography.module.css";
composes: touchTarget;
border: none;
@ -18,28 +18,34 @@
color: var(--tutu-color-primary);
font-family: inherit;
&:focus,&:hover,&:focus-visible {
background-color: var(--tutu-color-surface-dd);
&:focus,
&:hover,
&:focus-visible {
background-color: var(--tutu-color-surface-dd);
}
&.pressed {
background-color: var(--tutu-color-surface-d);
background-color: var(--tutu-color-surface-d);
}
&.raised {
background-color: var(--tutu-color-primary);
color: var(--tutu-color-on-primary);
background-color: var(--tutu-color-primary);
color: var(--tutu-color-on-primary);
}
&:disabled, &[aria-disabled]:not([aria-disabled="false"]) {
color: #9e9e9e;
&:disabled,
&[aria-disabled]:not([aria-disabled="false"]) {
color: #9e9e9e;
&:focus,&:hover,&:focus-visible {
background-color: transparent;
}
&:focus,
&:hover,
&:focus-visible {
background-color: transparent;
}
}
.toolbar &, .appbar & {
.toolbar &,
.appbar & {
height: 100%;
margin-block: 0;
padding-block: 0;
@ -49,7 +55,9 @@
.appbar & {
color: var(--tutu-color-on-primary);
&:focus,&:hover,&:focus-visible {
&:focus,
&:hover,
&:focus-visible {
background-color: var(--tutu-color-primary-ll);
}
@ -62,4 +70,3 @@
color: var(--tutu-color-on-surface);
}
}

View file

@ -2,15 +2,16 @@ import { Theme, createTheme } from "@suid/material/styles";
import { deepPurple, amber } from "@suid/material/colors";
import { Accessor } from "solid-js";
export function useRootTheme() : Accessor<Theme> {
return () => createTheme({
palette: {
primary: {
main: deepPurple[500]
export function useRootTheme(): Accessor<Theme> {
return () =>
createTheme({
palette: {
primary: {
main: deepPurple[500],
},
secondary: {
main: amber.A200,
},
},
secondary: {
main: amber.A200
}
}
})
});
}

View file

@ -1,5 +1,6 @@
:root,
[lang^="en"], [lang="en"] {
[lang^="en"],
[lang="en"] {
--md-typography-type: "regular";
--title-size: 1.25rem;
--title-weight: 500;
@ -19,9 +20,12 @@
}
}
[lang^="zh"], [lang="zh"],
[lang^="kr"], [lang="kr"],
[lang^="ja"], [lang="ja"] {
[lang^="zh"],
[lang="zh"],
[lang^="kr"],
[lang="kr"],
[lang^="ja"],
[lang="ja"] {
--md-typography-type: "dense";
--title-size: 1.4375rem;
--subheading-size: 1.1875rem;
@ -95,7 +99,6 @@
--tutu-anim-curve-sharp: cubic-bezier(0.4, 0, 0.6, 1);
@media (max-width: 300px) {
/* XS screen, like wearables */
& {
--tutu-transition-shadow: box-shadow 157.5ms var(--tutu-anim-curve-std);
@ -103,7 +106,6 @@
}
@media (max-width: 600px) {
/* Mobile */
& {
--tutu-transition-shadow: box-shadow 225ms var(--tutu-anim-curve-std);
@ -111,7 +113,6 @@
}
@media (max-width: 1200px) {
/* Tablet */
& {
--tutu-transition-shadow: box-shadow 292.5ms var(--tutu-anim-curve-std);
@ -125,11 +126,17 @@
}
* {
font-family: Roboto, "Noto Sans", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
font-family:
Roboto,
"Noto Sans",
system-ui,
-apple-system,
BlinkMacSystemFont,
sans-serif;
box-sizing: border-box;
margin: 0;
}
body {
font-size: var(--body-size, 1rem);
}
}

View file

@ -3,7 +3,7 @@ import { Dynamic } from "solid-js/web";
import typography from "./typography.module.css";
import { mergeClass } from "../utils";
type AnyElement = keyof JSX.IntrinsicElements | ParentComponent<any>
type AnyElement = keyof JSX.IntrinsicElements | ParentComponent<any>;
type PropsOf<E extends AnyElement> =
E extends ParentComponent<infer Props>
@ -12,9 +12,7 @@ type PropsOf<E extends AnyElement> =
? JSX.IntrinsicElements[E]
: JSX.HTMLAttributes<HTMLElement>;
export type TypographyProps<
E extends AnyElement,
> = {
export type TypographyProps<E extends AnyElement> = {
ref?: Ref<E>;
component?: E;
class?: string;
@ -33,7 +31,9 @@ type TypographyKind =
| "caption"
| "buttonText";
export function Typography<T extends AnyElement>(props: {typography: TypographyKind } & TypographyProps<T>) {
export function Typography<T extends AnyElement>(
props: { typography: TypographyKind } & TypographyProps<T>,
) {
const [managed, passthough] = splitProps(props, [
"ref",
"component",
@ -50,38 +50,38 @@ export function Typography<T extends AnyElement>(props: {typography: TypographyK
{...passthough}
></Dynamic>
);
};
}
export function Display4<E extends AnyElement>(props: TypographyProps<E>) {
return <Typography typography={"display4"} {...props}></Typography>
return <Typography typography={"display4"} {...props}></Typography>;
}
export function Display3<E extends AnyElement>(props: TypographyProps<E>) {
return <Typography typography={"display3"} {...props}></Typography>
return <Typography typography={"display3"} {...props}></Typography>;
}
export function Display2<E extends AnyElement>(props: TypographyProps<E>) {
return <Typography typography={"display2"} {...props}></Typography>
return <Typography typography={"display2"} {...props}></Typography>;
}
export function Display1<E extends AnyElement>(props: TypographyProps<E>) {
return <Typography typography={"display1"} {...props}></Typography>
return <Typography typography={"display1"} {...props}></Typography>;
}
export function Headline<E extends AnyElement>(props: TypographyProps<E>) {
return <Typography typography={"headline"} {...props}></Typography>
return <Typography typography={"headline"} {...props}></Typography>;
}
export function Title<E extends AnyElement>(props: TypographyProps<E>) {
return <Typography typography={"title"} {...props}></Typography>
return <Typography typography={"title"} {...props}></Typography>;
}
export function Subheading<E extends AnyElement>(props: TypographyProps<E>) {
return <Typography typography={"subheading"} {...props}></Typography>
return <Typography typography={"subheading"} {...props}></Typography>;
}
export function Body1<E extends AnyElement>(props: TypographyProps<E>) {
return <Typography typography={"body1"} {...props}></Typography>
return <Typography typography={"body1"} {...props}></Typography>;
}
export function Body2<E extends AnyElement>(props: TypographyProps<E>) {
return <Typography typography={"body2"} {...props}></Typography>
return <Typography typography={"body2"} {...props}></Typography>;
}
export function Caption<E extends AnyElement>(props: TypographyProps<E>) {
return <Typography typography={"caption"} {...props}></Typography>
return <Typography typography={"caption"} {...props}></Typography>;
}
export function ButtonText<E extends AnyElement>(props: TypographyProps<E>) {
return <Typography typography={"buttonText"} {...props}></Typography>
return <Typography typography={"buttonText"} {...props}></Typography>;
}

View file

@ -1,11 +1,13 @@
import { createContext, useContext, type Accessor } from "solid-js";
export type HeroSource = {[key: string | symbol | number]: HTMLElement | undefined}
export type HeroSource = {
[key: string | symbol | number]: HTMLElement | undefined;
};
const HeroSourceContext = createContext<Accessor<HeroSource>>(() => ({}))
const HeroSourceContext = createContext<Accessor<HeroSource>>(() => ({}));
export const HeroSourceProvider = HeroSourceContext.Provider
export const HeroSourceProvider = HeroSourceContext.Provider;
export function useHeroSource() {
return useContext(HeroSourceContext)
return useContext(HeroSourceContext);
}

View file

@ -1,11 +1,15 @@
import { persistentMap } from "@nanostores/persistent";
type Settings = {
onGoingOAuth2Process?: string
prefetchTootsDisabled?: boolean
}
onGoingOAuth2Process?: string;
prefetchTootsDisabled?: boolean;
};
export const $settings = persistentMap<Settings>("settings::", {}, {
encode: JSON.stringify,
decode: JSON.parse
})
export const $settings = persistentMap<Settings>(
"settings::",
{},
{
encode: JSON.stringify,
decode: JSON.parse,
},
);

View file

@ -18,16 +18,14 @@ const CompactToot: Component<CompactTootProps> = (props) => {
const toot = () => props.status;
return (
<section
class={[tootStyle.compact, props.class || ""].join(" ")}
class={[tootStyle.compact, props.class || ""].join(" ")}
lang={toot().language || undefined}
>
<Img
src={toot().account.avatar}
class={[
tootStyle.tootAvatar,
].join(" ")}
class={[tootStyle.tootAvatar].join(" ")}
/>
<div class={[tootStyle.compactAuthorGroup].join(' ')}>
<div class={[tootStyle.compactAuthorGroup].join(" ")}>
<Body2
ref={(e: { innerHTML: string }) => {
appliedCustomEmoji(
@ -48,7 +46,7 @@ const CompactToot: Component<CompactTootProps> = (props) => {
ref={(e: { innerHTML: string }) => {
appliedCustomEmoji(e, toot().content, toot().emojis);
}}
class={[tootStyle.compactTootContent].join(' ')}
class={[tootStyle.compactTootContent].join(" ")}
></div>
</section>
);

View file

@ -155,20 +155,20 @@ const Home: ParentComponent = (props) => {
useDocumentTitle("Timelines");
const now = createTimeSource();
const settings$ = useStore($settings)
const settings$ = useStore($settings);
const sessions = useSessions();
const client = () => sessions()[0].client;
const [profile] = useAcctProfile(client);
const [panelOffset, setPanelOffset] = createSignal(0);
const prefetching = () => !settings$().prefetchTootsDisabled
const prefetching = () => !settings$().prefetchTootsDisabled;
const [currentFocusOn, setCurrentFocusOn] = createSignal<HTMLElement[]>([]);
const [focusRange, setFocusRange] = createSignal([0, 0] as readonly [
number,
number,
]);
const child = children(() => props.children)
const child = children(() => props.children);
let scrollEventLockReleased = true;
@ -269,7 +269,11 @@ const Home: ParentComponent = (props) => {
<Scaffold
topbar={
<AppBar position="static">
<Toolbar variant="dense" class="responsive" sx={{ paddingTop: "var(--safe-area-inset-top, 0px)" }}>
<Toolbar
variant="dense"
class="responsive"
sx={{ paddingTop: "var(--safe-area-inset-top, 0px)" }}
>
<Tabs onFocusChanged={setCurrentFocusOn} offset={panelOffset()}>
<Tab focus={isTabFocus(0)} onClick={[onTabClick, 0]}>
Home
@ -282,7 +286,14 @@ const Home: ParentComponent = (props) => {
</Tab>
</Tabs>
<ProfileMenuButton profile={profile()}>
<MenuItem onClick={(e) => $settings.setKey("prefetchTootsDisabled", !$settings.get().prefetchTootsDisabled)}>
<MenuItem
onClick={(e) =>
$settings.setKey(
"prefetchTootsDisabled",
!$settings.get().prefetchTootsDisabled,
)
}
>
<ListItemText>Prefetch Toots</ListItemText>
<ListItemSecondaryAction>
<Switch checked={prefetching()}></Switch>

View file

@ -11,7 +11,7 @@ const MediaAttachmentGrid: Component<{
}> = (props) => {
let rootRef: HTMLElement;
const [viewerIndex, setViewerIndex] = createSignal<number>();
const viewerOpened = () => typeof viewerIndex() !== "undefined"
const viewerOpened = () => typeof viewerIndex() !== "undefined";
const gridTemplateColumns = () => {
const l = props.attachments.length;
if (l < 2) {

View file

@ -36,7 +36,7 @@ function within(n: number, target: number, range: number) {
}
function clamp(input: number, min: number, max: number) {
return Math.min(Math.max(input, min), max)
return Math.min(Math.max(input, min), max);
}
const MediaViewer: ParentComponent<MediaViewerProps> = (props) => {
@ -207,7 +207,13 @@ const MediaViewer: ParentComponent<MediaViewerProps> = (props) => {
move: number,
idx: number,
) => {
const { ref, top: otop, left: oleft, scale: oscale, osize: [owidth, oheight] } = state[idx];
const {
ref,
top: otop,
left: oleft,
scale: oscale,
osize: [owidth, oheight],
} = state[idx];
const [cx, cy] = center;
const iy = clamp(cy - otop, 0, oheight),
ix = clamp(cx - oleft, 0, owidth); // in image coordinate system

View file

@ -8,7 +8,13 @@ import {
Menu,
MenuItem,
} from "@suid/material";
import { Show, createSignal, createUniqueId, type ParentComponent } from "solid-js";
import {
ErrorBoundary,
Show,
createSignal,
createUniqueId,
type ParentComponent,
} from "solid-js";
import {
Settings as SettingsIcon,
Bookmark as BookmarkIcon,
@ -42,79 +48,79 @@ const ProfileMenuButton: ParentComponent<{
return (
<>
<ButtonBase
aria-haspopup="true"
sx={{ borderRadius: "50%" }}
id={buttonId}
onClick={onClick}
aria-controls={open() ? menuId : undefined}
aria-expanded={open() ? "true" : undefined}
>
<Avatar
alt={`${props.profile?.displayName}'s avatar`}
src={props.profile?.avatar}
></Avatar>
</ButtonBase>
<Menu
id={menuId}
anchorEl={anchor()}
open={open()}
onClose={onClose}
MenuListProps={{
"aria-labelledby": buttonId,
sx: {
minWidth: "220px",
}
}}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
>
<MenuItem>
<ListItemAvatar>
<Avatar src={props.profile?.avatar}></Avatar>
</ListItemAvatar>
<ListItemText
primary={props.profile?.displayName}
secondary={`@${props.profile?.username}`}
></ListItemText>
</MenuItem>
<ButtonBase
aria-haspopup="true"
sx={{ borderRadius: "50%" }}
id={buttonId}
onClick={onClick}
aria-controls={open() ? menuId : undefined}
aria-expanded={open() ? "true" : undefined}
>
<Avatar
alt={`${props.profile?.displayName}'s avatar`}
src={props.profile?.avatar}
></Avatar>
</ButtonBase>
<Menu
id={menuId}
anchorEl={anchor()}
open={open()}
onClose={onClose}
MenuListProps={{
"aria-labelledby": buttonId,
sx: {
minWidth: "220px",
},
}}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
>
<MenuItem>
<ListItemAvatar>
<Avatar src={props.profile?.avatar}></Avatar>
</ListItemAvatar>
<ListItemText
primary={props.profile?.displayName}
secondary={`@${props.profile?.username}`}
></ListItemText>
</MenuItem>
<MenuItem>
<ListItemIcon>
<BookmarkIcon />
</ListItemIcon>
<ListItemText>Bookmarks</ListItemText>
</MenuItem>
<MenuItem>
<ListItemIcon>
<LikeIcon />
</ListItemIcon>
<ListItemText>Likes</ListItemText>
</MenuItem>
<MenuItem>
<ListItemIcon>
<ListIcon />
</ListItemIcon>
<ListItemText>Lists</ListItemText>
</MenuItem>
<Divider />
<Show when={props.children}>
{props.children}
<MenuItem>
<ListItemIcon>
<BookmarkIcon />
</ListItemIcon>
<ListItemText>Bookmarks</ListItemText>
</MenuItem>
<MenuItem>
<ListItemIcon>
<LikeIcon />
</ListItemIcon>
<ListItemText>Likes</ListItemText>
</MenuItem>
<MenuItem>
<ListItemIcon>
<ListIcon />
</ListItemIcon>
<ListItemText>Lists</ListItemText>
</MenuItem>
<Divider />
</Show>
<MenuItem component={A} href="/settings" onClick={onClose}>
<ListItemIcon>
<SettingsIcon />
</ListItemIcon>
<ListItemText>Settings</ListItemText>
</MenuItem>
</Menu>
<Show when={props.children}>
{props.children}
<Divider />
</Show>
<MenuItem component={A} href="/settings" onClick={onClose}>
<ListItemIcon>
<SettingsIcon />
</ListItemIcon>
<ListItemText>Settings</ListItemText>
</MenuItem>
</Menu>
</>
);
};

View file

@ -211,7 +211,7 @@ const RegularToot: Component<TootCardProps> = (props) => {
classList={{
[tootStyle.toot]: true,
[tootStyle.expanded]: managed.evaluated,
[managed.class || ""]: true
[managed.class || ""]: true,
}}
ref={rootRef!}
lang={toot().language || managed.lang}

View file

@ -1,8 +1,7 @@
import type { Component } from "solid-js";
const TootBottomSheet: Component = (props) => {
return <></>
}
return <></>;
};
export default TootBottomSheet
export default TootBottomSheet;

View file

@ -38,7 +38,9 @@ const TootThread: Component<TootThreadProps> = (props) => {
css`
article {
transition: margin 90ms var(--tutu-anim-curve-sharp), var(--tutu-transition-shadow);
transition:
margin 90ms var(--tutu-anim-curve-sharp),
var(--tutu-transition-shadow);
user-select: none;
cursor: pointer;
}
@ -64,7 +66,10 @@ const TootThread: Component<TootThreadProps> = (props) => {
`;
return (
<article classList={{ "thread-line": !!inReplyTo(), "expanded": expanded() }} onClick={() => setExpanded((x) => !x)}>
<article
classList={{ "thread-line": !!inReplyTo(), expanded: expanded() }}
onClick={() => setExpanded((x) => !x)}
>
<Show when={inReplyTo()}>
<CompactToot
status={inReplyTo()!}

View file

@ -6,13 +6,14 @@
&.toot {
/* fix composition ordering: I think the css module processor should aware the overriding and behaves, but no */
transition: margin-block 125ms var(--tutu-anim-curve-std),
transition:
margin-block 125ms var(--tutu-anim-curve-std),
height 225ms var(--tutu-anim-curve-std),
var(--tutu-transition-shadow);
border-radius: 0;
}
&>.toot {
& > .toot {
box-shadow: none;
}
@ -46,11 +47,11 @@
display: grid;
grid-template-columns: 1fr auto;
>* {
> * {
color: var(--tutu-color-secondary-text-on-surface);
}
>:last-child {
> :last-child {
grid-column: 1 /3;
}
@ -80,7 +81,7 @@
}
.tootContent {
composes: cardNoPad from '../material/cards.module.css';
composes: cardNoPad from "../material/cards.module.css";
margin-left: calc(var(--card-pad, 0) + var(--toot-avatar-size, 0) + 8px);
margin-right: var(--card-pad, 0);
line-height: 1.5;
@ -150,14 +151,14 @@
}
.tootAttachmentGrp {
composes: cardNoPad from '../material/cards.module.css';
composes: cardNoPad from "../material/cards.module.css";
margin-top: 1em;
margin-left: calc(var(--card-pad, 0) + var(--toot-avatar-size, 0) + 8px);
margin-right: var(--card-pad, 0);
display: grid;
gap: 4px;
>:where(img) {
> :where(img) {
max-height: 35vh;
min-height: 40px;
object-fit: none;
@ -168,7 +169,7 @@
}
.tootBottomActionGrp {
composes: cardGutSkip from '../material/cards.module.css';
composes: cardGutSkip from "../material/cards.module.css";
padding-block: calc((var(--card-gut) - 10px) / 2);
animation: 225ms var(--tutu-anim-curve-std) tootBottomExpanding;
@ -176,7 +177,7 @@
flex-flow: row wrap;
justify-content: space-evenly;
> button{
> button {
color: var(--tutu-color-on-surface);
padding: 10px 8px;
@ -206,4 +207,4 @@
100% {
opacity: 1;
}
}
}

View file

@ -1,26 +1,26 @@
import { createRenderEffect, createSignal, onCleanup } from "solid-js";
export function useDocumentTitle(newTitle?: string) {
const capturedTitle = document.title
const [title, setTitle] = createSignal(newTitle ?? capturedTitle)
const capturedTitle = document.title;
const [title, setTitle] = createSignal(newTitle ?? capturedTitle);
createRenderEffect(() => {
document.title = title()
})
document.title = title();
});
onCleanup(() => {
document.title = capturedTitle
})
document.title = capturedTitle;
});
return setTitle
return setTitle;
}
export function mergeClass(c1: string | undefined, c2: string | undefined) {
if (!c1) {
return c2
return c2;
}
if (!c2) {
return c1
return c1;
}
return [c1, c2].join(' ')
return [c1, c2].join(" ");
}