format code using prettier
This commit is contained in:
		
							parent
							
								
									f06a7a6da1
								
							
						
					
					
						commit
						93b4cd065a
					
				
					 27 changed files with 326 additions and 260 deletions
				
			
		| 
						 | 
				
			
			@ -9,4 +9,4 @@
 | 
			
		|||
 | 
			
		||||
.custom-emoji {
 | 
			
		||||
  width: 1.25em;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")!);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
  },
 | 
			
		||||
);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
  );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,7 @@
 | 
			
		|||
import type { Component } from "solid-js";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const TootBottomSheet: Component = (props) => {
 | 
			
		||||
  return <></>
 | 
			
		||||
}
 | 
			
		||||
  return <></>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default TootBottomSheet
 | 
			
		||||
export default TootBottomSheet;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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()!}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(" ");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue