Compare commits
No commits in common. "b133a9b9a779f9a21d0b4a021502c1b5ffe7b726" and "35f51db294e48eb4129089cd46ba112370137364" have entirely different histories.
b133a9b9a7
...
35f51db294
8 changed files with 19 additions and 164 deletions
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
@ -36,9 +36,7 @@
|
|||
"@suid/icons-material": "^0.7.0",
|
||||
"@suid/material": "^0.16.0",
|
||||
"blurhash": "^2.0.5",
|
||||
"colorjs.io": "^0.5.2",
|
||||
"date-fns": "^3.6.0",
|
||||
"fast-average-color": "^9.4.0",
|
||||
"hammerjs": "^2.0.8",
|
||||
"masto": "^6.8.0",
|
||||
"nanostores": "^0.9.5",
|
||||
|
|
|
@ -43,7 +43,7 @@ const MOVE_SPEED = 1400; // 1400px/s, bottom sheet is big and a bit heavier than
|
|||
const BottomSheet: ParentComponent<BottomSheetProps> = (props) => {
|
||||
let element: HTMLDialogElement;
|
||||
let animation: Animation | undefined;
|
||||
const [hero, setHero] = useHeroSignal(HERO);
|
||||
const hero = useHeroSignal(HERO);
|
||||
const [cache, setCache] = createSignal<ResolvedChildren | undefined>();
|
||||
const ochildren = children(() => props.children);
|
||||
|
||||
|
@ -70,13 +70,11 @@ const BottomSheet: ParentComponent<BottomSheetProps> = (props) => {
|
|||
const animation = animateHero(startRect, endRect, element, true);
|
||||
const onClose = () => {
|
||||
element.close();
|
||||
setHero();
|
||||
};
|
||||
animation.addEventListener("finish", onClose);
|
||||
animation.addEventListener("cancel", onClose);
|
||||
} else {
|
||||
element.close();
|
||||
setHero();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -12,9 +12,7 @@ export type HeroSource = {
|
|||
[key: string | symbol | number]: DOMRect | undefined;
|
||||
};
|
||||
|
||||
const HeroSourceContext = createContext<Signal<HeroSource>>(
|
||||
/* __@PURE__ */ undefined,
|
||||
);
|
||||
const HeroSourceContext = createContext<Signal<HeroSource>>(/* __@PURE__ */undefined);
|
||||
|
||||
export const HeroSourceProvider = HeroSourceContext.Provider;
|
||||
|
||||
|
@ -27,7 +25,7 @@ function useHeroSource() {
|
|||
*/
|
||||
export function useHeroSignal(
|
||||
key: string | symbol | number,
|
||||
): Signal<DOMRect | undefined> {
|
||||
): Accessor<DOMRect | undefined> {
|
||||
const source = useHeroSource();
|
||||
if (source) {
|
||||
const [get, set] = createSignal<DOMRect>();
|
||||
|
@ -44,8 +42,8 @@ export function useHeroSignal(
|
|||
}
|
||||
});
|
||||
|
||||
return [get, set];
|
||||
return get;
|
||||
} else {
|
||||
return [() => undefined, () => undefined];
|
||||
return () => undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ const CompactToot: Component<CompactTootProps> = (props) => {
|
|||
const toot = () => props.status;
|
||||
return (
|
||||
<section
|
||||
class={[tootStyle.toot, tootStyle.compact, props.class || ""].join(" ")}
|
||||
class={[tootStyle.compact, props.class || ""].join(" ")}
|
||||
lang={toot().language || undefined}
|
||||
>
|
||||
<Img
|
||||
|
|
|
@ -146,7 +146,7 @@ const TimelinePanel: Component<{
|
|||
expanded={item.id === expandedThreadId() ? 1 : 0}
|
||||
onExpandChange={(x) => {
|
||||
if (item.id !== expandedThreadId()) {
|
||||
setExpandedThreadId((x) => (x ? undefined : item.id));
|
||||
setExpandedThreadId(item.id);
|
||||
} else if (x === 2) {
|
||||
props.openFullScreenToot(item, element);
|
||||
}
|
||||
|
@ -198,16 +198,8 @@ const Home: ParentComponent = (props) => {
|
|||
const settings$ = useStore($settings);
|
||||
|
||||
const [profiles] = useSignedInProfiles();
|
||||
const profile = () => {
|
||||
const all = profiles();
|
||||
if (all.length > 0) {
|
||||
return all[0].inf;
|
||||
}
|
||||
};
|
||||
const client = () => {
|
||||
const all = profiles();
|
||||
return all?.[0]?.client;
|
||||
};
|
||||
const profile = () => profiles()[0].inf;
|
||||
const client = () => profiles()[0].client;
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [heroSrc, setHeroSrc] = createSignal<HeroSource>({});
|
||||
|
|
|
@ -5,19 +5,11 @@ import {
|
|||
type JSX,
|
||||
Show,
|
||||
createRenderEffect,
|
||||
createSignal,
|
||||
createEffect,
|
||||
} from "solid-js";
|
||||
import tootStyle from "./toot.module.css";
|
||||
import { formatRelative } from "date-fns";
|
||||
import Img from "../material/Img.js";
|
||||
import {
|
||||
Body1,
|
||||
Body2,
|
||||
Caption,
|
||||
Subheading,
|
||||
Title,
|
||||
} from "../material/typography.js";
|
||||
import { Body2 } from "../material/typography.js";
|
||||
import { css } from "solid-styled";
|
||||
import {
|
||||
BookmarkAddOutlined,
|
||||
|
@ -34,8 +26,6 @@ import { Divider } from "@suid/material";
|
|||
import cardStyle from "../material/cards.module.css";
|
||||
import Button from "../material/Button.js";
|
||||
import MediaAttachmentGrid from "./MediaAttachmentGrid.js";
|
||||
import { FastAverageColor } from "fast-average-color";
|
||||
import Color from "colorjs.io";
|
||||
|
||||
type TootContentViewProps = {
|
||||
source?: string;
|
||||
|
@ -197,67 +187,6 @@ function TootAuthorGroup(props: { status: mastodon.v1.Status; now: Date }) {
|
|||
);
|
||||
}
|
||||
|
||||
function TootPreviewCard(props: { src: mastodon.v1.PreviewCard }) {
|
||||
let root: HTMLAnchorElement;
|
||||
|
||||
createEffect(() => {
|
||||
if (!props.src.width) return;
|
||||
const width = root.getBoundingClientRect().width;
|
||||
if (width > props.src.width) {
|
||||
root.classList.add(tootStyle.compact);
|
||||
} else {
|
||||
root.classList.remove(tootStyle.compact);
|
||||
}
|
||||
});
|
||||
|
||||
const onImgLoad = (event: Event & { currentTarget: HTMLImageElement }) => {
|
||||
// TODO: better extraction algorithm
|
||||
// I'd like to use a pattern panel and match one in the panel from the extracted color
|
||||
const fac = new FastAverageColor();
|
||||
const result = fac.getColor(event.currentTarget);
|
||||
if (result.error) {
|
||||
console.error(result.error);
|
||||
fac.destroy();
|
||||
return;
|
||||
}
|
||||
root.style.setProperty("--tutu-color-surface", result.hex);
|
||||
const focusSurface = result.isDark
|
||||
? new Color(result.hex).darken(0.2)
|
||||
: new Color(result.hex).lighten(0.2);
|
||||
root.style.setProperty("--tutu-color-surface-d", focusSurface.toString());
|
||||
const textColor = result.isDark ? "white" : "black";
|
||||
const secondaryTextColor = new Color(textColor);
|
||||
secondaryTextColor.alpha = 0.75;
|
||||
root.style.setProperty("--tutu-color-on-surface", textColor);
|
||||
root.style.setProperty(
|
||||
"--tutu-color-secondary-text-on-surface",
|
||||
secondaryTextColor.toString(),
|
||||
);
|
||||
fac.destroy();
|
||||
};
|
||||
|
||||
return (
|
||||
<a
|
||||
ref={root!}
|
||||
class={tootStyle.previewCard}
|
||||
href={props.src.url}
|
||||
target="_blank"
|
||||
referrerPolicy="unsafe-url"
|
||||
>
|
||||
<Show when={props.src.image}>
|
||||
<img
|
||||
crossOrigin="anonymous"
|
||||
src={props.src.image!}
|
||||
onLoad={onImgLoad}
|
||||
loading="lazy"
|
||||
/>
|
||||
</Show>
|
||||
<Title component="h1">{props.src.title}</Title>
|
||||
<Body1 component="p">{props.src.description}</Body1>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
const RegularToot: Component<TootCardProps> = (props) => {
|
||||
let rootRef: HTMLElement;
|
||||
const [managed, managedActionGroup, rest] = splitProps(
|
||||
|
@ -312,9 +241,6 @@ const RegularToot: Component<TootCardProps> = (props) => {
|
|||
emojis={toot().emojis}
|
||||
class={tootStyle.tootContent}
|
||||
/>
|
||||
<Show when={toot().card}>
|
||||
<TootPreviewCard src={toot().card!} />
|
||||
</Show>
|
||||
<Show when={toot().mediaAttachments.length > 0}>
|
||||
<MediaAttachmentGrid attachments={toot().mediaAttachments} />
|
||||
</Show>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
border-radius: 0;
|
||||
}
|
||||
|
||||
&>.toot {
|
||||
& > .toot {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@
|
|||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
|
||||
>* {
|
||||
> * {
|
||||
color: var(--tutu-color-secondary-text-on-surface);
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@
|
|||
grid-column: 1 /3;
|
||||
}
|
||||
|
||||
>time {
|
||||
> time {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
|
@ -104,64 +104,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.previewCard {
|
||||
composes: cardGutSkip from "../material/cards.module.css";
|
||||
display: block;
|
||||
border: 1px solid #eeeeee;
|
||||
background-color: var(--tutu-color-surface);
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1.5em;
|
||||
color: var(--tutu-color-secondary-text-on-surface);
|
||||
transition: color 220ms var(--tutu-anim-curve-std), background-color 220ms var(--tutu-anim-curve-std);
|
||||
padding-bottom: 8px;
|
||||
|
||||
>img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
background-color: var(--tutu-color-surface-d);
|
||||
color: var(--tutu-color-on-surface);
|
||||
|
||||
>h1 {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
>h1 {
|
||||
color: var(--tutu-color-on-surface);
|
||||
}
|
||||
|
||||
>h1,
|
||||
>p {
|
||||
margin-left: 16px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
&.compact {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(10%, 30%) 1fr;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
|
||||
>img:first-child {
|
||||
grid-row: 1 / 3;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
>h1,
|
||||
>p {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toot.compact {
|
||||
.compact {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 8px;
|
||||
|
@ -184,12 +127,12 @@
|
|||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
|
||||
>.compactAuthorUsername {
|
||||
> .compactAuthorUsername {
|
||||
color: var(--tutu-color-secondary-text-on-surface);
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
>time {
|
||||
> time {
|
||||
color: var(--tutu-color-secondary-text-on-surface);
|
||||
}
|
||||
}
|
||||
|
@ -234,11 +177,11 @@
|
|||
flex-flow: row wrap;
|
||||
justify-content: space-evenly;
|
||||
|
||||
>button {
|
||||
> button {
|
||||
color: var(--tutu-color-on-surface);
|
||||
padding: 10px 8px;
|
||||
|
||||
>svg {
|
||||
> svg {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue