Compare commits
	
		
			4 commits
		
	
	
		
			f31a4c33ad
			...
			c41a8e31d1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | c41a8e31d1 | ||
|  | 8f7d28d525 | ||
|  | 44a69c8517 | ||
|  | 9a307d640a | 
					 9 changed files with 188 additions and 7 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -3,3 +3,4 @@ dist/ | ||||||
| dev-dist/ | dev-dist/ | ||||||
| .env.local | .env.local | ||||||
| .env.*.local | .env.*.local | ||||||
|  | .DS_Store | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								bun.lockb
									
										
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bun.lockb
									
										
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -52,6 +52,7 @@ | ||||||
|     "@solid-primitives/map": "^0.4.13", |     "@solid-primitives/map": "^0.4.13", | ||||||
|     "@solid-primitives/page-visibility": "^2.0.17", |     "@solid-primitives/page-visibility": "^2.0.17", | ||||||
|     "@solid-primitives/resize-observer": "^2.0.26", |     "@solid-primitives/resize-observer": "^2.0.26", | ||||||
|  |     "@solid-primitives/static-store": "^0.1.0", | ||||||
|     "@solidjs/router": "^0.15.2", |     "@solidjs/router": "^0.15.2", | ||||||
|     "@suid/icons-material": "^0.8.1", |     "@suid/icons-material": "^0.8.1", | ||||||
|     "@suid/material": "^0.18.0", |     "@suid/material": "^0.18.0", | ||||||
|  | @ -73,5 +74,11 @@ | ||||||
|     "workbox-core": "^7.3.0", |     "workbox-core": "^7.3.0", | ||||||
|     "workbox-precaching": "^7.3.0" |     "workbox-precaching": "^7.3.0" | ||||||
|   }, |   }, | ||||||
|   "packageManager": "bun@1.1.34" |   "packageManager": "bun@1.1.34", | ||||||
|  |   "trustedDependencies": [ | ||||||
|  |     "edgedriver" | ||||||
|  |   ], | ||||||
|  |   "patchedDependencies": { | ||||||
|  |     "@suid/vite-plugin@0.3.1": "patches/@suid%2Fvite-plugin@0.3.1.patch" | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								patches/@suid%2Fvite-plugin@0.3.1.patch
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								patches/@suid%2Fvite-plugin@0.3.1.patch
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | diff --git a/index.mjs b/index.mjs
 | ||||||
|  | index 2cf42b9506e130fcc9c1ca166d03d3d8b9b5781c..7dc283602ff09b94c6300f45eac223125eebeb46 100644
 | ||||||
|  | --- a/index.mjs
 | ||||||
|  | +++ b/index.mjs
 | ||||||
|  | @@ -2,8 +2,8 @@ import $generate from "@babel/generator";
 | ||||||
|  |  import { parse } from "@babel/parser"; | ||||||
|  |  import $traverse from "@babel/traverse"; | ||||||
|  |  import * as types from "@babel/types"; | ||||||
|  | -const traverse = $traverse.default;
 | ||||||
|  | -const generate = $generate.default;
 | ||||||
|  | +const traverse = $traverse.default ?? $traverse;
 | ||||||
|  | +const generate = $generate.default ?? $generate;
 | ||||||
|  |  const defaultOptions = { | ||||||
|  |    disableOptimizeDeps: [ | ||||||
|  |      "@suid/base", | ||||||
|  | @ -33,6 +33,7 @@ import { Service } from "./serviceworker/services.js"; | ||||||
| import { makeEventListener } from "@solid-primitives/event-listener"; | import { makeEventListener } from "@solid-primitives/event-listener"; | ||||||
| import { ServiceWorkerProvider } from "./platform/host.js"; | import { ServiceWorkerProvider } from "./platform/host.js"; | ||||||
| import StackedRouter from "./platform/StackedRouter.js"; | import StackedRouter from "./platform/StackedRouter.js"; | ||||||
|  | import {ResizeObserverBoundary} from "~platform/resize-observer.jsx"; | ||||||
| 
 | 
 | ||||||
| const AccountSignIn = lazy(() => import("./accounts/SignIn.js")); | const AccountSignIn = lazy(() => import("./accounts/SignIn.js")); | ||||||
| const AccountMastodonOAuth2Callback = lazy( | const AccountMastodonOAuth2Callback = lazy( | ||||||
|  | @ -157,6 +158,7 @@ const App: Component = () => { | ||||||
|       }} |       }} | ||||||
|     > |     > | ||||||
|       <ThemeProvider theme={theme}> |       <ThemeProvider theme={theme}> | ||||||
|  |         <ResizeObserverBoundary> | ||||||
|         <AppLocaleProvider |         <AppLocaleProvider | ||||||
|           value={{ |           value={{ | ||||||
|             language: lang, |             language: lang, | ||||||
|  | @ -176,6 +178,7 @@ const App: Component = () => { | ||||||
|             </ServiceWorkerProvider> |             </ServiceWorkerProvider> | ||||||
|           </ClientProvider> |           </ClientProvider> | ||||||
|         </AppLocaleProvider> |         </AppLocaleProvider> | ||||||
|  |         </ResizeObserverBoundary> | ||||||
|       </ThemeProvider> |       </ThemeProvider> | ||||||
|     </ErrorBoundary> |     </ErrorBoundary> | ||||||
|   ); |   ); | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import { createElementSize } from "@solid-primitives/resize-observer"; | import { createElementSize } from "~platform/resize-observer"; | ||||||
| import { | import { | ||||||
|   JSX, |   JSX, | ||||||
|   Show, |   Show, | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ import { | ||||||
| } from "solid-js"; | } from "solid-js"; | ||||||
| import { Dynamic, type DynamicProps } from "solid-js/web"; | import { Dynamic, type DynamicProps } from "solid-js/web"; | ||||||
| import MasonryLayout from "masonry-layout"; | import MasonryLayout from "masonry-layout"; | ||||||
| import { createElementSize } from "@solid-primitives/resize-observer"; | import { createElementSize } from "~platform/resize-observer"; | ||||||
| import "./Masonry.css"; | import "./Masonry.css"; | ||||||
| 
 | 
 | ||||||
| type MasonryContainer = | type MasonryContainer = | ||||||
|  |  | ||||||
							
								
								
									
										158
									
								
								src/platform/resize-observer.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								src/platform/resize-observer.tsx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,158 @@ | ||||||
|  | import { | ||||||
|  |   createContext, | ||||||
|  |   createEffect, | ||||||
|  |   onCleanup, | ||||||
|  |   sharedConfig, | ||||||
|  |   useContext, | ||||||
|  |   type JSX, | ||||||
|  | } from "solid-js"; | ||||||
|  | import { isDev, isServer } from "solid-js/web"; | ||||||
|  | import { createStaticStore } from "@solid-primitives/static-store"; | ||||||
|  | 
 | ||||||
|  | export type ObserveCallback<E extends Element> = ( | ||||||
|  |   entry: ResizeObserverEntry & { readonly target: E }, | ||||||
|  | ) => void; | ||||||
|  | export type ObserveElement = <E extends Element = Element>( | ||||||
|  |   element: E, | ||||||
|  |   callback: ObserveCallback<E>, | ||||||
|  | ) => () => void; | ||||||
|  | 
 | ||||||
|  | const ResizeObserverContext = /* @__PURE__ */ createContext<ObserveElement>(); | ||||||
|  | 
 | ||||||
|  | export function useResizeObserver() { | ||||||
|  |   const observe = useContext(ResizeObserverContext); | ||||||
|  | 
 | ||||||
|  |   if (isDev && !observe) { | ||||||
|  |     throw new TypeError( | ||||||
|  |       "ObserverElement is not found, this function must be called in <ResizeOberserBoundary />", | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return observe!; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function ResizeObserverBoundaryClient(props: { children: JSX.Element }) { | ||||||
|  |   const map = new Map< | ||||||
|  |     Element, | ||||||
|  |     ObserveCallback<Element> | ObserveCallback<Element>[] | ||||||
|  |   >(); | ||||||
|  | 
 | ||||||
|  |   const observer = new ResizeObserver((entries) => { | ||||||
|  |     for (const entry of entries) { | ||||||
|  |       const callback = map.get(entry.target); | ||||||
|  |       if (!callback) return; | ||||||
|  |       if (Array.isArray(callback)) { | ||||||
|  |         for (const f of callback) { | ||||||
|  |           f(entry); | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         callback(entry); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   onCleanup(() => { | ||||||
|  |     observer.disconnect(); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   const observe: ObserveElement = ( | ||||||
|  |     element: Element, | ||||||
|  |     callback: ObserveCallback<any>, | ||||||
|  |   ) => { | ||||||
|  |     const callbacks = map.get(element); | ||||||
|  |     if (!callbacks) { | ||||||
|  |       map.set(element, callback); | ||||||
|  |       observer.observe(element); | ||||||
|  |     } else if (Array.isArray(callbacks)) { | ||||||
|  |       callbacks.push(callback); | ||||||
|  |     } else { | ||||||
|  |       map.set(element, [callbacks, callback]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return () => { | ||||||
|  |       const callbacks = map.get(element); | ||||||
|  |       if (callbacks === null) { | ||||||
|  |         observer.unobserve(element); | ||||||
|  |       } else if (Array.isArray(callbacks)) { | ||||||
|  |         const idx = callbacks.indexOf(callback); | ||||||
|  |         if (idx !== -1) { | ||||||
|  |           callbacks.splice(idx, 1); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (callbacks.length === 0) { | ||||||
|  |           observer.unobserve(element); | ||||||
|  |           map.delete(element); | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         observer.unobserve(element); | ||||||
|  |         map.delete(element); | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <ResizeObserverContext.Provider value={observe}> | ||||||
|  |       {props.children} | ||||||
|  |     </ResizeObserverContext.Provider> | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function ResizeObserverBoundaryServer(props: { children: JSX.Element }) { | ||||||
|  |   return ( | ||||||
|  |     <ResizeObserverContext.Provider | ||||||
|  |       value={(() => {}) as unknown as ObserveElement} | ||||||
|  |     > | ||||||
|  |       {props.children} | ||||||
|  |     </ResizeObserverContext.Provider> | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const ResizeObserverBoundary = isServer | ||||||
|  |   ? ResizeObserverBoundaryServer | ||||||
|  |   : ResizeObserverBoundaryClient; | ||||||
|  | 
 | ||||||
|  | const ELEMENT_SIZE_FALLBACK = { width: null, height: null }; | ||||||
|  | 
 | ||||||
|  | function getElementSize(target: Element) { | ||||||
|  |   if (isServer || !target) { | ||||||
|  |     return { ...ELEMENT_SIZE_FALLBACK }; | ||||||
|  |   } | ||||||
|  |   const { width, height } = target.getBoundingClientRect(); | ||||||
|  |   return { width, height }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export type NullableSize = {width: number | null, height: number | null} | ||||||
|  | 
 | ||||||
|  | export function createElementSize( | ||||||
|  |   target: Element | (() => Element | undefined | null | false), | ||||||
|  | ): Readonly<NullableSize> { | ||||||
|  |   if (isServer) { | ||||||
|  |     return ELEMENT_SIZE_FALLBACK; | ||||||
|  |   } | ||||||
|  |   const isFn = typeof target === "function"; | ||||||
|  |   const [size, setSize] = createStaticStore( | ||||||
|  |     sharedConfig.context || isFn | ||||||
|  |       ? ELEMENT_SIZE_FALLBACK | ||||||
|  |       : getElementSize(target), | ||||||
|  |   ); | ||||||
|  |   const callback: ObserveCallback<Element> = (entry) => { | ||||||
|  |     setSize(getElementSize(entry.target)); | ||||||
|  |   }; | ||||||
|  |   const observe = useResizeObserver(); | ||||||
|  |   if (isFn) { | ||||||
|  |     createEffect(() => { | ||||||
|  |       const el = target(); | ||||||
|  |       if (el) { | ||||||
|  |         setSize(getElementSize(el)); | ||||||
|  |         const unobserve = observe(el, callback); | ||||||
|  |         onCleanup(unobserve); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   } else { | ||||||
|  |     const unobserve = observe(target, callback); | ||||||
|  |     onCleanup(unobserve); | ||||||
|  |   } | ||||||
|  |   return size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export { useWindowSize } from "@solid-primitives/resize-observer"; | ||||||
|  | @ -12,10 +12,7 @@ import { | ||||||
| } from "solid-js"; | } from "solid-js"; | ||||||
| import MediaViewer from "../MediaViewer"; | import MediaViewer from "../MediaViewer"; | ||||||
| import { render } from "solid-js/web"; | import { render } from "solid-js/web"; | ||||||
| import { | import { createElementSize, useWindowSize } from "~platform/resize-observer"; | ||||||
|   createElementSize, |  | ||||||
|   useWindowSize, |  | ||||||
| } from "@solid-primitives/resize-observer"; |  | ||||||
| import { useStore } from "@nanostores/solid"; | import { useStore } from "@nanostores/solid"; | ||||||
| import { $settings } from "../../settings/stores"; | import { $settings } from "../../settings/stores"; | ||||||
| import { averageColorHex } from "~platform/blurhash"; | import { averageColorHex } from "~platform/blurhash"; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue