From 487de9237b2eeebd90d4e8e1ff090f448b473619 Mon Sep 17 00:00:00 2001 From: thislight Date: Sat, 23 Nov 2024 13:00:36 +0800 Subject: [PATCH 1/5] Masonry: use MutationObserver instead - originally tricks with the reactive system --- src/platform/Masonry.tsx | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/platform/Masonry.tsx b/src/platform/Masonry.tsx index 7071cd8..969e5dd 100644 --- a/src/platform/Masonry.tsx +++ b/src/platform/Masonry.tsx @@ -5,10 +5,8 @@ import { type Ref, createRenderEffect, onCleanup, - children, createEffect, createSignal, - onMount, } from "solid-js"; import { Dynamic, type DynamicProps } from "solid-js/web"; import MasonryLayout from "masonry-layout"; @@ -20,7 +18,6 @@ type MasonryContainer = | Component<{ ref?: Ref; class?: string; - children?: JSX.Element; }>; type ElementOf = @@ -37,7 +34,10 @@ function forwardRef(value: T, ref?: Ref) { (ref as (value: T) => void)(value); } -function createMasonry(element: Element, options: () => MasonryLayout.Options) { +function createCompatMasonry( + element: Element, + options: () => MasonryLayout.Options, +) { const layout = new MasonryLayout(element, { initLayout: false, }); @@ -46,11 +46,21 @@ function createMasonry(element: Element, options: () => MasonryLayout.Options) { const size = createElementSize(element); + const treeMutObx = new MutationObserver(() => { + layout.reloadItems?.(); + }); + + onCleanup(() => treeMutObx.disconnect()); + createRenderEffect(() => { const opts = options(); layout.option?.(opts); }); + createRenderEffect(() => { + treeMutObx.observe(element, { childList: true }); + }); + createRenderEffect(() => { const width = size.width; // only tracking width layout.layout?.(); @@ -61,8 +71,6 @@ function createMasonry(element: Element, options: () => MasonryLayout.Options) { layout.layout?.(); }); } - - return layout; } const supportsCSSMasonryLayout = /* @__PURE__ */ CSS.supports( @@ -85,9 +93,7 @@ if (import.meta.env.VITE_PLATFROM_MASONRY_ALWAYS_COMPAT) { function MasonryCompat( oprops: DynamicProps & { class?: string }, ) { - const [props, rest] = splitProps(oprops, ["ref", "children", "class"]); - - const childrenComponents = children(() => props.children); + const [props, rest] = splitProps(oprops, ["ref", "class"]); return ( ( const [columnGap, setColumnGap] = createSignal(); - const layout = createMasonry(element, () => { + createCompatMasonry(element, () => { return { gutter: columnGap(), }; @@ -115,18 +121,9 @@ function MasonryCompat( setColumnGap(Number(colGap.slice(0, colGap.length - 2))); } }); - - createRenderEffect(() => { - childrenComponents(); // just tracks - setTimeout(() => { - layout.reloadItems?.(); - layout.layout?.(); - }, 0); - }); }} class={`Masonry CompatMasonry ${props.class || ""}`} {...rest} - children={childrenComponents} /> ); } From fbbac36b4a934dda36fa4fb5fc61a505a3deca84 Mon Sep 17 00:00:00 2001 From: thislight Date: Sat, 23 Nov 2024 13:51:53 +0800 Subject: [PATCH 2/5] StackedRouter: minor changes --- src/platform/StackedRouter.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/platform/StackedRouter.css b/src/platform/StackedRouter.css index a946a2d..dc787bb 100644 --- a/src/platform/StackedRouter.css +++ b/src/platform/StackedRouter.css @@ -1,10 +1,9 @@ .StackedPage { + contain: layout style; container: StackedPage / size; display: contents; max-width: 100vw; max-width: 100dvw; - - contain: layout; } dialog.StackedPage { From bb3ba32dc5e66680d56b07a2d99a42b4699d385d Mon Sep 17 00:00:00 2001 From: thislight Date: Sat, 23 Nov 2024 13:53:10 +0800 Subject: [PATCH 3/5] Masonry: remove built-in column number condition --- src/platform/Masonry.css | 7 +------ src/platform/Masonry.tsx | 7 +++++++ src/timelines/toots/MediaAttachmentGrid.css | 8 ++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/platform/Masonry.css b/src/platform/Masonry.css index ed6264f..0c452aa 100644 --- a/src/platform/Masonry.css +++ b/src/platform/Masonry.css @@ -5,12 +5,7 @@ @supports (grid-template-rows: masonry) { .NativeMasonry { display: grid; - grid-template-columns: repeat(auto-fit, minmax(44px, min-content)); + grid-template-columns: repeat(auto-fit, minmax(33%, min-content)); grid-template-rows: masonry; - - &:has(> :last-child:nth-child(2n)) { - grid-template-columns: repeat(2, minmax(auto, min-content)); - } } } - diff --git a/src/platform/Masonry.tsx b/src/platform/Masonry.tsx index 969e5dd..bd461b9 100644 --- a/src/platform/Masonry.tsx +++ b/src/platform/Masonry.tsx @@ -144,6 +144,13 @@ function MasonryNative( * and fallback to masonry-layout if not supported. The children * must have specified width and height. * + * Testing native behaviour: + * - Firefox: in `about:config`, search for `layout.css.grid-template-masonry-value.enabled` + * + * Class `NativeMasonry` will be added to the element if it's under the + * css masonry layout, otherwise it's `CompatMasonry`. `Masonry` is always + * added. + * * **Children Changes** As the children changed, reflow will be triggered, * and there is might be a blink (or transition) for user. If it's not your * intention, don't remove/add the direct children. Instead wraps them under diff --git a/src/timelines/toots/MediaAttachmentGrid.css b/src/timelines/toots/MediaAttachmentGrid.css index 8fd667a..0043007 100644 --- a/src/timelines/toots/MediaAttachmentGrid.css +++ b/src/timelines/toots/MediaAttachmentGrid.css @@ -6,7 +6,7 @@ contain: layout style; gap: 4px; - > * { + >* { max-height: 35vh; min-height: 40px; min-width: 40px; @@ -26,16 +26,16 @@ } } - > * > * { + >*>* { width: 100%; height: 100%; } - > * > :where(img, video) { + >*> :where(img, video) { object-fit: contain; } - > * >.sensitive-placeholder { + >*>.sensitive-placeholder { display: inline-flex; display: inline flex; align-items: center; From 66d0bc8d84c38f48036099d2c0b512796ea0194c Mon Sep 17 00:00:00 2001 From: thislight Date: Sat, 23 Nov 2024 16:10:48 +0800 Subject: [PATCH 4/5] Profile: support wide page --- src/platform/StackedRouter.css | 11 +- src/profiles/Profile.css | 38 +++ src/profiles/Profile.tsx | 600 +++++++++++++++++---------------- 3 files changed, 347 insertions(+), 302 deletions(-) diff --git a/src/platform/StackedRouter.css b/src/platform/StackedRouter.css index dc787bb..320dfe7 100644 --- a/src/platform/StackedRouter.css +++ b/src/platform/StackedRouter.css @@ -1,9 +1,10 @@ .StackedPage { - contain: layout style; - container: StackedPage / size; - display: contents; - max-width: 100vw; - max-width: 100dvw; + contain: strict; + container: StackedPage / inline-size; + width: 100vw; + width: 100dvw; + height: 100vh; + height: 100dvh; } dialog.StackedPage { diff --git a/src/profiles/Profile.css b/src/profiles/Profile.css index 994a278..7dcfa70 100644 --- a/src/profiles/Profile.css +++ b/src/profiles/Profile.css @@ -115,6 +115,44 @@ } } +@container StackedPage (inline-size >=960px) { + .Profile { + display: grid; + grid-template-columns: auto 560px; + grid-template-rows: min-content 1fr; + height: 100cqh; + + >.topbar { + grid-column: 1 / 3; + grid-row: 1 /2; + + .MuiToolbar-root { + padding-right: calc(560px + 24px); + } + } + + > .details { + height: 100%; + display: flex; + flex-flow: column nowrap; + + > .intro { + flex-grow: 1; + } + } + + >.recent-toots { + overflow-y: auto; + margin-top: calc(-1 * var(--scaffold-topbar-height)); + z-index: calc(var(--tutu-zidx-nav, 1) + 1); + + >.toot-list-toolbar { + top: 0; + } + } + } +} + .Profile__page-title { flex-grow: 1; white-space: nowrap; diff --git a/src/profiles/Profile.tsx b/src/profiles/Profile.tsx index 04aba5f..f795c7c 100644 --- a/src/profiles/Profile.tsx +++ b/src/profiles/Profile.tsx @@ -237,315 +237,321 @@ const Profile: Component = () => { } class="Profile" > - - document.getElementById(menuButId)!.getBoundingClientRect() - } - aria-label="Options for the Profile" - > - - - - - - - - - {/* // for future */} - - - - { - const { left, right, top } = - event.currentTarget.getBoundingClientRect(); - openSubscribeMenu({ - left, - right, - top, - e: 1, - }); - }} - > - - - - Subscribe... - - } - > - - - - - Edit... +
+ + document.getElementById(menuButId)!.getBoundingClientRect() + } + aria-label="Options for the Profile" + > + + + + + + + + + {/* // for future */} - - - - - - - Followers - - - {profile()?.followersCount ?? ""} - - - - - - - - Following - - - {profile()?.followingCount ?? ""} - - - - - - - - Blocklist - - - - - - Mention in... - - - - - - - Open in browser... - - share({ url: profile()?.url })}> - - - - Share... - - - - - - - - - - - - 's Home - - - - - - -
-
- -
-
- - - - - - - - createRenderEffect(() => (e.innerHTML = displayName())) - } - aria-label="Display name" - > -
- {fullUsername()} -
-
- - - {<>} - - - - - - - - - - -
-
-
- createRenderEffect(() => (e.innerHTML = description() || "")) - } - >
- - - - - {(item, index) => { - return ( - - - - - - ); - }} - - -
{item.name} - - - - { - createRenderEffect(() => (e.innerHTML = item.value)); - }} - >
-
- -
- -
- - - 0}> - + + + + Subscribe... + + } + > + + + + + Edit... + + + + + + + + + Followers + + + {profile()?.followersCount ?? ""} + + + + + + + + Following + + + {profile()?.followingCount ?? ""} + + + + + + + + Blocklist + + + + + + Mention in... + - - - - - + + + + + Open in browser... + + share({ url: profile()?.url })}> + + + + Share... + +
+ + + + + + + + + 's Home + + + + + + +
- + +
+
+ + + + + + + + createRenderEffect(() => (e.innerHTML = displayName())) + } + aria-label="Display name" + > +
+ + {fullUsername()} + +
+
+ + + {<>} + + + + + + + + + + +
+ +
+ createRenderEffect(() => (e.innerHTML = description() || "")) + } + >
+ + - }> - - - + + + {(item, index) => { + return ( + + + + + + ); + }} + + +
{item.name} + + + + { + createRenderEffect(() => (e.innerHTML = item.value)); + }} + >
- + + +
+
+ +
+ + + 0}> + + + + + + + +
+ + }> + + + +
+
+
); }; From 62aaaeee9ababa3c82fda1c98e369b5bad5e78c2 Mon Sep 17 00:00:00 2001 From: thislight Date: Sat, 23 Nov 2024 16:13:42 +0800 Subject: [PATCH 5/5] Profile: check container query supports --- src/profiles/Profile.css | 52 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/profiles/Profile.css b/src/profiles/Profile.css index 7dcfa70..a8ce070 100644 --- a/src/profiles/Profile.css +++ b/src/profiles/Profile.css @@ -115,39 +115,41 @@ } } -@container StackedPage (inline-size >=960px) { - .Profile { - display: grid; - grid-template-columns: auto 560px; - grid-template-rows: min-content 1fr; - height: 100cqh; +@supports (container-type: inline-size) { + @container StackedPage (inline-size >=960px) { + .Profile { + display: grid; + grid-template-columns: auto 560px; + grid-template-rows: min-content 1fr; + height: 100cqh; - >.topbar { - grid-column: 1 / 3; - grid-row: 1 /2; + >.topbar { + grid-column: 1 / 3; + grid-row: 1 /2; - .MuiToolbar-root { - padding-right: calc(560px + 24px); + .MuiToolbar-root { + padding-right: calc(560px + 24px); + } } - } - > .details { - height: 100%; - display: flex; - flex-flow: column nowrap; + >.details { + height: 100%; + display: flex; + flex-flow: column nowrap; - > .intro { - flex-grow: 1; + >.intro { + flex-grow: 1; + } } - } - >.recent-toots { - overflow-y: auto; - margin-top: calc(-1 * var(--scaffold-topbar-height)); - z-index: calc(var(--tutu-zidx-nav, 1) + 1); + >.recent-toots { + overflow-y: auto; + margin-top: calc(-1 * var(--scaffold-topbar-height)); + z-index: calc(var(--tutu-zidx-nav, 1) + 1); - >.toot-list-toolbar { - top: 0; + >.toot-list-toolbar { + top: 0; + } } } }