Improve frontpage performance (#929)
* initial commit * merge with origin/main * fix package-lock.json * fix tiptap mentions * remove flutter * update package-lock.json * disable tailwindcss/typography until https://github.com/tailwindlabs/tailwindcss/issues/19946 is fixed * reactivate tailwind/typography after fix --------- Co-authored-by: Christian Beutel <> Co-authored-by: slothful-vassal <89943360+slothful-vassal@users.noreply.github.com>
This commit is contained in:
3007
web/package-lock.json
generated
3007
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -16,28 +16,28 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.58.2",
|
"@playwright/test": "^1.58.2",
|
||||||
"@sveltejs/adapter-auto": "^7.0.1",
|
"@sveltejs/adapter-auto": "^7.0.1",
|
||||||
|
"@sveltejs/enhanced-img": "^0.10.4",
|
||||||
"@sveltejs/kit": "^2.57.1",
|
"@sveltejs/kit": "^2.57.1",
|
||||||
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
||||||
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@types/canvas-confetti": "^1.9.0",
|
"@types/canvas-confetti": "^1.9.0",
|
||||||
"@types/node": "^25.3.3",
|
"@types/node": "^25.3.3",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"svelte": "^5.53.6",
|
"svelte": "^5.53.6",
|
||||||
"svelte-check": "^4.3.6",
|
"svelte-check": "^4.3.6",
|
||||||
"sveltekit-openapi-generator": "^0.1.5",
|
"sveltekit-openapi-generator": "^0.1.5",
|
||||||
"tailwindcss": "^4.0.0",
|
|
||||||
"tslib": "^2.4.1",
|
"tslib": "^2.4.1",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"vite": "^8.0.8"
|
"vite": "^8.0.9"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@felte/validator-zod": "^1.0.18",
|
"@felte/validator-zod": "^1.0.18",
|
||||||
"@fortawesome/fontawesome-free": "^7.1.0",
|
"@fortawesome/fontawesome-free": "^7.1.0",
|
||||||
"@sveltejs/adapter-node": "^5.5.2",
|
"@sveltejs/adapter-node": "^5.5.2",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/vite": "^4.2.4",
|
||||||
"@tailwindcss/vite": "^4.2.2",
|
"@threlte/core": "^8.5.9",
|
||||||
"@threlte/core": "^8.3.1",
|
"@threlte/extras": "^9.14.6",
|
||||||
"@threlte/extras": "^9.7.1",
|
|
||||||
"@tiptap/core": "^2.14.0",
|
"@tiptap/core": "^2.14.0",
|
||||||
"@tiptap/extension-heading": "^2.14.0",
|
"@tiptap/extension-heading": "^2.14.0",
|
||||||
"@tiptap/extension-link": "^2.14.0",
|
"@tiptap/extension-link": "^2.14.0",
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
"@turf/destination": "^7.3.3",
|
"@turf/destination": "^7.3.3",
|
||||||
"@turf/distance": "^7.3.3",
|
"@turf/distance": "^7.3.3",
|
||||||
"@types/chart.js": "^4.0.1",
|
"@types/chart.js": "^4.0.1",
|
||||||
"@types/three": "^0.182.0",
|
"@types/three": "^0.183.1",
|
||||||
"@xmldom/xmldom": "^0.8.12",
|
"@xmldom/xmldom": "^0.8.12",
|
||||||
"activitypub-types": "^1.1.0",
|
"activitypub-types": "^1.1.0",
|
||||||
"autoprefixer": "^10.4.24",
|
"autoprefixer": "^10.4.24",
|
||||||
@@ -78,7 +78,8 @@
|
|||||||
"pocketbase": "^0.26.8",
|
"pocketbase": "^0.26.8",
|
||||||
"qrcode": "^1.4.4",
|
"qrcode": "^1.4.4",
|
||||||
"svelte-i18n": "^4.0.0",
|
"svelte-i18n": "^4.0.0",
|
||||||
"three": "^0.182.0",
|
"tailwindcss": "^4.2.4",
|
||||||
|
"three": "^0.183.1",
|
||||||
"vitest": "^4.1.4",
|
"vitest": "^4.1.4",
|
||||||
"zod": "^3.24.1"
|
"zod": "^3.24.1"
|
||||||
},
|
},
|
||||||
@@ -87,4 +88,4 @@
|
|||||||
"vite": "$vite"
|
"vite": "$vite"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
59
web/src/lib/components/3D/marker.svelte
Normal file
59
web/src/lib/components/3D/marker.svelte
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<!--
|
||||||
|
Auto-generated by: https://github.com/threlte/threlte/tree/main/packages/gltf
|
||||||
|
Command: npx @threlte/gltf@3.0.7 ../../../../static/models/marker.glb -T
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { T } from "@threlte/core";
|
||||||
|
import { useGltf, useDraco } from "@threlte/extras";
|
||||||
|
import type { Snippet } from "svelte";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
fallback?: Snippet;
|
||||||
|
error?: Snippet<[any]>;
|
||||||
|
children?: Snippet<[any]>;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
fallback,
|
||||||
|
error,
|
||||||
|
children,
|
||||||
|
ref = $bindable(),
|
||||||
|
...props
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
|
const gltf = useGltf("/models/marker.glb", { dracoLoader: useDraco() });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<T.Group bind:ref dispose={false} {...props}>
|
||||||
|
{#await gltf}
|
||||||
|
{@render fallback?.()}
|
||||||
|
{:then gltf}
|
||||||
|
<T.Group>
|
||||||
|
<T.Mesh
|
||||||
|
geometry={gltf.nodes["Node-Mesh003"].geometry}
|
||||||
|
material={gltf.materials.mat8}
|
||||||
|
/>
|
||||||
|
<T.Mesh
|
||||||
|
geometry={gltf.nodes["Node-Mesh003_1"].geometry}
|
||||||
|
material={gltf.materials.mat23}
|
||||||
|
>
|
||||||
|
<T.PointLight
|
||||||
|
position={[-1, 0.8, 0]}
|
||||||
|
color="#ffffff"
|
||||||
|
intensity={3}
|
||||||
|
></T.PointLight>
|
||||||
|
<T.PointLight
|
||||||
|
position={[1, 0.8, 0]}
|
||||||
|
color="#ffffff"
|
||||||
|
intensity={3}
|
||||||
|
></T.PointLight></T.Mesh
|
||||||
|
>
|
||||||
|
</T.Group>
|
||||||
|
{:catch err}
|
||||||
|
{@render error?.({ error: err })}
|
||||||
|
{/await}
|
||||||
|
|
||||||
|
{@render children?.({ ref })}
|
||||||
|
</T.Group>
|
||||||
42
web/src/lib/components/3D/moon.svelte
Normal file
42
web/src/lib/components/3D/moon.svelte
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<!--
|
||||||
|
Auto-generated by: https://github.com/threlte/threlte/tree/main/packages/gltf
|
||||||
|
Command: npx @threlte/gltf@3.0.7 ../../../../static/models/moon.glb -T
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { T } from "@threlte/core";
|
||||||
|
import { useGltf, useDraco } from "@threlte/extras";
|
||||||
|
import type { Snippet } from "svelte";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
fallback?: Snippet;
|
||||||
|
error?: Snippet<[any]>;
|
||||||
|
children?: Snippet<[any]>;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
fallback,
|
||||||
|
error,
|
||||||
|
children,
|
||||||
|
ref = $bindable(),
|
||||||
|
...props
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
|
const gltf = useGltf("/models/moon.glb", { dracoLoader: useDraco() });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<T.Group bind:ref dispose={false} {...props}>
|
||||||
|
{#await gltf}
|
||||||
|
{@render fallback?.()}
|
||||||
|
{:then gltf}
|
||||||
|
<T.Mesh geometry={gltf.nodes.Moon.geometry} material={gltf.materials.DD9944}
|
||||||
|
><T.PointLight position={[0.5, 5, 0.5]} color="#a2cbf5" intensity={7}
|
||||||
|
></T.PointLight>
|
||||||
|
</T.Mesh>
|
||||||
|
{:catch err}
|
||||||
|
{@render error?.({ error: err })}
|
||||||
|
{/await}
|
||||||
|
|
||||||
|
{@render children?.({ ref })}
|
||||||
|
</T.Group>
|
||||||
117
web/src/lib/components/3D/scene.svelte
Normal file
117
web/src/lib/components/3D/scene.svelte
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { theme } from "$lib/stores/theme_store";
|
||||||
|
import { T, useTask } from "@threlte/core";
|
||||||
|
import { backInOut } from "svelte/easing";
|
||||||
|
import { Tween } from "svelte/motion";
|
||||||
|
import Marker from "./marker.svelte";
|
||||||
|
import Moon from "./moon.svelte";
|
||||||
|
import Sun from "./sun.svelte";
|
||||||
|
import { useViewport } from "@threlte/extras";
|
||||||
|
import { innerHeight, innerWidth } from "svelte/reactivity/window";
|
||||||
|
|
||||||
|
const viewport = useViewport();
|
||||||
|
|
||||||
|
const canvasHeight = $derived((innerHeight.current ?? 0) - 112);
|
||||||
|
const canvasWidth = $derived((innerWidth.current ?? 0) * 0.6);
|
||||||
|
const dioramaImageMaxHeight = 0.75;
|
||||||
|
|
||||||
|
const imgWidth = $derived(
|
||||||
|
Math.min(
|
||||||
|
((dioramaImageMaxHeight * canvasHeight) / 9) * 16,
|
||||||
|
canvasWidth,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const imgHeight = $derived((imgWidth / 16) * 9);
|
||||||
|
|
||||||
|
const imgWorldWidth = $derived((imgWidth / canvasWidth) * $viewport.width);
|
||||||
|
const imgWorldHeight = $derived(
|
||||||
|
(imgHeight / canvasHeight) * $viewport.height,
|
||||||
|
);
|
||||||
|
|
||||||
|
const peak1PositionRelativeToImage = [-0.195, 0.7];
|
||||||
|
const peak1Position = $derived([
|
||||||
|
peak1PositionRelativeToImage[0] * (imgWorldWidth / 2),
|
||||||
|
peak1PositionRelativeToImage[1] * (imgWorldHeight / 2),
|
||||||
|
20,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const peak2PositionRelativeToImage = [0.05, 1];
|
||||||
|
const peak2Position = $derived([
|
||||||
|
peak2PositionRelativeToImage[0] * (imgWorldWidth / 2),
|
||||||
|
peak2PositionRelativeToImage[1] * (imgWorldHeight / 2),
|
||||||
|
20,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const peak3PositionRelativeToImage = [0.55, 0.37];
|
||||||
|
const peak3Position = $derived([
|
||||||
|
peak3PositionRelativeToImage[0] * (imgWorldWidth / 2),
|
||||||
|
peak3PositionRelativeToImage[1] * (imgWorldHeight / 2),
|
||||||
|
20,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const sunUpPosition = $derived(($viewport.height / 2) * 0.6);
|
||||||
|
|
||||||
|
let rotation = $state(0);
|
||||||
|
useTask((delta) => {
|
||||||
|
rotation += delta / 2;
|
||||||
|
});
|
||||||
|
|
||||||
|
const sunZPosition = new Tween($theme == "light" ? sunUpPosition : 0, {
|
||||||
|
duration: 1000,
|
||||||
|
easing: backInOut,
|
||||||
|
});
|
||||||
|
$effect(() => {
|
||||||
|
sunZPosition.set($theme == "light" ? sunUpPosition : 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const sunLightIntensity = new Tween($theme == "light" ? 4 : 0, {
|
||||||
|
duration: 400,
|
||||||
|
});
|
||||||
|
$effect(() => {
|
||||||
|
sunLightIntensity.set($theme == "light" ? 4 : 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const moonZPosition = new Tween($theme == "dark" ? sunUpPosition : 0, {
|
||||||
|
duration: 1000,
|
||||||
|
easing: backInOut,
|
||||||
|
});
|
||||||
|
$effect(() => {
|
||||||
|
moonZPosition.set($theme == "dark" ? sunUpPosition : 0);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<T.OrthographicCamera
|
||||||
|
makeDefault
|
||||||
|
zoom={14}
|
||||||
|
position={[0, 0, 30]}
|
||||||
|
oncreate={(c) => {
|
||||||
|
c.lookAt(0, 0, 0);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- <Earth {rotation}></Earth> -->
|
||||||
|
|
||||||
|
<!-- <Mountain {rotation}></Mountain> -->
|
||||||
|
|
||||||
|
<Sun
|
||||||
|
position={[7.5, sunZPosition.current, 0]}
|
||||||
|
rotation={[0, 0, 0]}
|
||||||
|
scale={0.11}
|
||||||
|
lightIntesity={sunLightIntensity.current}
|
||||||
|
/>
|
||||||
|
<Moon
|
||||||
|
position={[-5, moonZPosition.current, 0]}
|
||||||
|
rotation={[0, -Math.PI / 2, 0]}
|
||||||
|
scale={0.53}
|
||||||
|
></Moon>
|
||||||
|
|
||||||
|
<Marker position={peak1Position} rotation={[0, rotation, 0]} scale={1}></Marker>
|
||||||
|
|
||||||
|
<Marker position={peak2Position} rotation={[0, rotation - 1, 0]} scale={1}
|
||||||
|
></Marker>
|
||||||
|
|
||||||
|
<Marker
|
||||||
|
position={peak3Position}
|
||||||
|
rotation={[0, rotation + 1, 0]}
|
||||||
|
scale={1}
|
||||||
|
></Marker>
|
||||||
1508
web/src/lib/components/3D/star_postions.json
Normal file
1508
web/src/lib/components/3D/star_postions.json
Normal file
File diff suppressed because it is too large
Load Diff
139
web/src/lib/components/3D/star_sky.svelte
Normal file
139
web/src/lib/components/3D/star_sky.svelte
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import starLayers from "./star_postions.json";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="stars-wrapper">
|
||||||
|
{#each starLayers as layer, i}
|
||||||
|
<svg
|
||||||
|
class="stars layer-{i}"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
preserveAspectRatio="none"
|
||||||
|
>
|
||||||
|
{#each layer as star}
|
||||||
|
<circle cx="{star.x}%" cy="{star.y}%" r={star.r} fill="white" />
|
||||||
|
{/each}
|
||||||
|
</svg>
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
<svg class="extras" width="100%" height="100%" preserveAspectRatio="none">
|
||||||
|
<defs>
|
||||||
|
<radialGradient id="comet-gradient" cx="0" cy=".5" r="0.5">
|
||||||
|
<stop offset="0%" stop-color="rgba(255,255,255,.8)" />
|
||||||
|
<stop offset="100%" stop-color="rgba(255,255,255,0)" />
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<g transform="rotate(-135)">
|
||||||
|
<ellipse
|
||||||
|
class="comet comet-a"
|
||||||
|
fill="url(#comet-gradient)"
|
||||||
|
cx="0"
|
||||||
|
cy="0"
|
||||||
|
rx="150"
|
||||||
|
ry="2"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g transform="rotate(20)">
|
||||||
|
<ellipse
|
||||||
|
class="comet comet-b"
|
||||||
|
fill="url(#comet-gradient)"
|
||||||
|
cx="100%"
|
||||||
|
cy="0"
|
||||||
|
rx="150"
|
||||||
|
ry="2"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g transform="rotate(300)">
|
||||||
|
<ellipse
|
||||||
|
class="comet comet-c"
|
||||||
|
fill="url(#comet-gradient)"
|
||||||
|
cx="40%"
|
||||||
|
cy="100%"
|
||||||
|
rx="150"
|
||||||
|
ry="2"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.stars-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
|
transition:
|
||||||
|
opacity 1.5s ease-in-out,
|
||||||
|
visibility 1.5s;
|
||||||
|
will-change: opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visible {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stars {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
/* Force GPU to handle the transparency fade */
|
||||||
|
transform: translateZ(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Your working twinkle animation from before */
|
||||||
|
.layer-0 {
|
||||||
|
animation: twinkle 4s infinite -0s;
|
||||||
|
}
|
||||||
|
.layer-1 {
|
||||||
|
animation: twinkle 4s infinite -1.3s;
|
||||||
|
}
|
||||||
|
.layer-2 {
|
||||||
|
animation: twinkle 4s infinite -2.6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes twinkle {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.comet {
|
||||||
|
animation: comet 10s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes comet {
|
||||||
|
0% {
|
||||||
|
transform: translateX(0);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
1% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
20% {
|
||||||
|
transform: translateX(-2000px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(-2000px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.comet-b {
|
||||||
|
animation-delay: -3.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comet-c {
|
||||||
|
animation-delay: -5s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
72
web/src/lib/components/3D/sun.svelte
Normal file
72
web/src/lib/components/3D/sun.svelte
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<!--
|
||||||
|
Auto-generated by: https://github.com/threlte/threlte/tree/main/packages/gltf
|
||||||
|
Command: npx @threlte/gltf@3.0.7 ../../../../static/models/sun.glb -T
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { T } from "@threlte/core";
|
||||||
|
import { useDraco, useGltf } from "@threlte/extras";
|
||||||
|
import type { Snippet } from "svelte";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
lightIntesity?: number;
|
||||||
|
fallback?: Snippet;
|
||||||
|
error?: Snippet<[any]>;
|
||||||
|
children?: Snippet<[any]>;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
lightIntesity = 7,
|
||||||
|
fallback,
|
||||||
|
error,
|
||||||
|
children,
|
||||||
|
ref = $bindable(),
|
||||||
|
...props
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
|
const gltf = useGltf("/models/sun.glb", { dracoLoader: useDraco() });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<T.Group bind:ref dispose={false} {...props}>
|
||||||
|
{#await gltf}
|
||||||
|
{@render fallback?.()}
|
||||||
|
{:then gltf}
|
||||||
|
<T.Mesh
|
||||||
|
geometry={gltf.nodes.GeoSphere003_1.geometry}
|
||||||
|
material={gltf.materials._Sol02___Default}
|
||||||
|
/>
|
||||||
|
<T.Mesh
|
||||||
|
geometry={gltf.nodes.GeoSphere003_1_1.geometry}
|
||||||
|
material={gltf.materials._Sol01___Default}
|
||||||
|
></T.Mesh>
|
||||||
|
<T.SpotLight
|
||||||
|
decay={0}
|
||||||
|
position={[20, 45, 80]}
|
||||||
|
target={ref}
|
||||||
|
intensity={lightIntesity}
|
||||||
|
></T.SpotLight>
|
||||||
|
<T.SpotLight
|
||||||
|
decay={0}
|
||||||
|
position={[0, 65, 80]}
|
||||||
|
target={ref}
|
||||||
|
intensity={lightIntesity}
|
||||||
|
></T.SpotLight>
|
||||||
|
<T.SpotLight
|
||||||
|
decay={0}
|
||||||
|
position={[-20, 45, 80]}
|
||||||
|
target={ref}
|
||||||
|
intensity={lightIntesity}
|
||||||
|
></T.SpotLight>
|
||||||
|
<T.SpotLight
|
||||||
|
decay={0}
|
||||||
|
position={[0, 25, 80]}
|
||||||
|
target={ref}
|
||||||
|
intensity={lightIntesity}
|
||||||
|
></T.SpotLight>
|
||||||
|
{:catch err}
|
||||||
|
{@render error?.({ error: err })}
|
||||||
|
{/await}
|
||||||
|
|
||||||
|
{@render children?.({ ref })}
|
||||||
|
</T.Group>
|
||||||
@@ -91,6 +91,7 @@
|
|||||||
options.HTMLAttributes,
|
options.HTMLAttributes,
|
||||||
),
|
),
|
||||||
options.renderText?.({
|
options.renderText?.({
|
||||||
|
suggestion: {...options.suggestion, editor: editor!},
|
||||||
options: options,
|
options: options,
|
||||||
node,
|
node,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { theme } from "$lib/stores/theme_store";
|
|
||||||
import { T, useTask } from "@threlte/core";
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
import { Tween } from "svelte/motion";
|
|
||||||
import * as THREE from "three";
|
|
||||||
import Mountain from "./mountain.svelte";
|
|
||||||
|
|
||||||
let rotation = $state(0);
|
|
||||||
useTask((delta) => {
|
|
||||||
rotation += delta / 2;
|
|
||||||
});
|
|
||||||
|
|
||||||
const ambientIntensity = new Tween($theme == "light" ? 3 : 0, {
|
|
||||||
duration: 500,
|
|
||||||
});
|
|
||||||
|
|
||||||
let ambientColor = $derived($theme == "light" ? "#ffffff" : "#4c7fe6");
|
|
||||||
$effect(() => {
|
|
||||||
ambientIntensity.set($theme == "light" ? 3 : 0.1);
|
|
||||||
});
|
|
||||||
|
|
||||||
let starsGeometry: THREE.BufferGeometry | undefined = $state();
|
|
||||||
let starsMaterial: THREE.PointsMaterial | undefined = $state();
|
|
||||||
onMount(() => {
|
|
||||||
const stars = new Array(0);
|
|
||||||
for (var i = 0; i < 500; i++) {
|
|
||||||
let x = THREE.MathUtils.randFloatSpread(500);
|
|
||||||
let y = THREE.MathUtils.randFloatSpread(500);
|
|
||||||
let z = THREE.MathUtils.randFloatSpread(500);
|
|
||||||
stars.push(x, y, z);
|
|
||||||
}
|
|
||||||
starsGeometry = new THREE.BufferGeometry();
|
|
||||||
starsGeometry.setAttribute(
|
|
||||||
"position",
|
|
||||||
new THREE.Float32BufferAttribute(stars, 3),
|
|
||||||
);
|
|
||||||
starsMaterial = new THREE.PointsMaterial({ color: 0xffffff });
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<T.PerspectiveCamera
|
|
||||||
makeDefault
|
|
||||||
position={[35.5, 28, 35.5]}
|
|
||||||
oncreate={(c) => {
|
|
||||||
c.lookAt(-17, 0, 12);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{#if starsGeometry && starsMaterial}
|
|
||||||
<T.Points geometry={starsGeometry} material={starsMaterial}></T.Points>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- <Earth {rotation}></Earth> -->
|
|
||||||
<Mountain {rotation}></Mountain>
|
|
||||||
|
|
||||||
<T.HemisphereLight
|
|
||||||
skyColor={ambientColor}
|
|
||||||
groundColor="#242734"
|
|
||||||
intensity={ambientIntensity.current}
|
|
||||||
/>
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
} from "$lib/components/base/search.svelte";
|
} from "$lib/components/base/search.svelte";
|
||||||
import EmptyStateFeed from "$lib/components/empty_states/empty_state_feed.svelte";
|
import EmptyStateFeed from "$lib/components/empty_states/empty_state_feed.svelte";
|
||||||
import FeedCard from "$lib/components/profile/feed_card.svelte";
|
import FeedCard from "$lib/components/profile/feed_card.svelte";
|
||||||
import Scene from "$lib/components/scene.svelte";
|
import Scene from "$lib/components/3D/scene.svelte";
|
||||||
import TrailCard from "$lib/components/trail/trail_card.svelte";
|
import TrailCard from "$lib/components/trail/trail_card.svelte";
|
||||||
import {
|
import {
|
||||||
defaultTrailSearchAttributes,
|
defaultTrailSearchAttributes,
|
||||||
@@ -27,6 +27,8 @@
|
|||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
import { onMount, untrack } from "svelte";
|
import { onMount, untrack } from "svelte";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
|
import StarSky from "$lib/components/3D/star_sky.svelte";
|
||||||
|
import { fade } from "svelte/transition";
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
|
|
||||||
@@ -153,14 +155,14 @@
|
|||||||
<svelte:window onscroll={onScroll} />
|
<svelte:window onscroll={onScroll} />
|
||||||
|
|
||||||
<section
|
<section
|
||||||
class="hero grid grid-cols-1 lg:grid-cols-2 md:px-8 gap-4 md:gap-8"
|
class="hero grid grid-cols-1 lg:grid-cols-2 lg:px-8 gap-4 lg:gap-8"
|
||||||
style="min-height: calc(100vh - 112px)"
|
style="min-height: calc(100vh - 112px)"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="flex flex-col justify-center gap-8 px-8 md:px-24 mt-0 lg:sticky"
|
class="flex flex-col justify-center gap-8 px-8 lg:px-24 mt-0 lg:sticky"
|
||||||
style="max-height: calc(100vh - 112px); top: 112px;"
|
style="max-height: calc(100vh - 112px); top: 112px;"
|
||||||
>
|
>
|
||||||
<h2 class="text-5xl sm:text-6xl md:text-7xl font-bold">
|
<h2 class="text-5xl sm:text-6xl lg:text-7xl font-bold">
|
||||||
{$_("welcome_to")} <span class="-tracking-[0.075em]">wanderer</span>
|
{$_("welcome_to")} <span class="-tracking-[0.075em]">wanderer</span>
|
||||||
</h2>
|
</h2>
|
||||||
<h5>
|
<h5>
|
||||||
@@ -190,16 +192,34 @@
|
|||||||
</section>
|
</section>
|
||||||
{#if !page.data.user}
|
{#if !page.data.user}
|
||||||
<div
|
<div
|
||||||
class="hidden md:block w-full fixed top-[112px] -z-10"
|
class="hidden lg:block w-full fixed top-[112px] -z-10"
|
||||||
style="min-height: calc(100vh - 112px)"
|
style="min-height: calc(100vh - 112px)"
|
||||||
>
|
>
|
||||||
<Canvas toneMapping={0}>
|
<div class="invisible dark:visible">
|
||||||
<Scene></Scene>
|
<StarSky></StarSky>
|
||||||
</Canvas>
|
</div>
|
||||||
|
<div class="absolute h-full w-[60%] left-[40%]">
|
||||||
|
<Canvas toneMapping={0}>
|
||||||
|
<Scene></Scene>
|
||||||
|
</Canvas>
|
||||||
|
{#if $theme === "light"}
|
||||||
|
<enhanced:img
|
||||||
|
class="absolute top-1/2 -translate-y-1/2 left-1/2 -translate-x-1/2 max-h-3/4"
|
||||||
|
src="/static/models/wanderer_diorama_light.png"
|
||||||
|
alt="wanderer Diorama"
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<enhanced:img
|
||||||
|
class="absolute top-1/2 -translate-y-1/2 left-1/2 -translate-x-1/2 max-h-3/4"
|
||||||
|
src="/static/models/wanderer_diorama_dark.png"
|
||||||
|
alt="wanderer Diorama"
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<section class="md:px-8 md:max-w-1/2 mb-24" id="about">
|
<section class="lg:px-8 lg:max-w-1/2 mb-24" id="about">
|
||||||
<div class="px-8 md:px-24">
|
<div class="px-8 lg:px-24">
|
||||||
<h2 class="text-4xl md:text-5xl font-bold mt-1 mb-8">
|
<h2 class="text-4xl lg:text-5xl font-bold mt-1 mb-8">
|
||||||
{$_("about")}
|
{$_("about")}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="prose dark:prose-invert">
|
<div class="prose dark:prose-invert">
|
||||||
@@ -207,9 +227,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="md:px-8 md:max-w-1/2 mb-24" id="trails">
|
<section class="lg:px-8 lg:max-w-1/2 mb-24" id="trails">
|
||||||
<div class="px-8 md:px-24 space-y-4">
|
<div class="px-8 lg:px-24 space-y-4">
|
||||||
<h2 class="text-4xl md:text-5xl font-bold">
|
<h2 class="text-4xl lg:text-5xl font-bold">
|
||||||
{$_("explore-some-trails")}
|
{$_("explore-some-trails")}
|
||||||
</h2>
|
</h2>
|
||||||
<h5>
|
<h5>
|
||||||
@@ -243,9 +263,9 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="get-started" class="md:px-8 md:max-w-1/2 mb-24">
|
<section id="get-started" class="lg:px-8 lg:max-w-1/2 mb-24">
|
||||||
<div class="px-8 md:px-24 space-y-4 text-center">
|
<div class="px-8 lg:px-24 space-y-4 text-center">
|
||||||
<h2 class="text-4xl md:text-5xl font-bold">{$_("get-started")}</h2>
|
<h2 class="text-4xl lg:text-5xl font-bold">{$_("get-started")}</h2>
|
||||||
<p>{$_("ready-to-join")}?</p>
|
<p>{$_("ready-to-join")}?</p>
|
||||||
<a
|
<a
|
||||||
class="inline-block btn-primary btn-large"
|
class="inline-block btn-primary btn-large"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"openapi": "3.0.3",
|
"openapi": "3.0.3",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Wanderer API",
|
"title": "Wanderer API",
|
||||||
"version": "v0.18.5",
|
"version": "0.18.5",
|
||||||
"description": "API documentation for wanderer backend"
|
"description": "API documentation for wanderer backend"
|
||||||
},
|
},
|
||||||
"servers": [],
|
"servers": [],
|
||||||
|
|||||||
BIN
web/static/models/marker.glb
Normal file
BIN
web/static/models/marker.glb
Normal file
Binary file not shown.
BIN
web/static/models/moon.glb
Normal file
BIN
web/static/models/moon.glb
Normal file
Binary file not shown.
Binary file not shown.
BIN
web/static/models/sun.glb
Normal file
BIN
web/static/models/sun.glb
Normal file
Binary file not shown.
BIN
web/static/models/wanderer_diorama_dark.png
Normal file
BIN
web/static/models/wanderer_diorama_dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 MiB |
BIN
web/static/models/wanderer_diorama_light.png
Normal file
BIN
web/static/models/wanderer_diorama_light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
@@ -1,13 +1,14 @@
|
|||||||
import tailwindcss from '@tailwindcss/vite';
|
import { enhancedImages } from '@sveltejs/enhanced-img';
|
||||||
import { sveltekit } from '@sveltejs/kit/vite';
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
import { defineConfig } from 'vitest/config';
|
import tailwindcss from '@tailwindcss/vite';
|
||||||
import openapiPlugin from 'sveltekit-openapi-generator';
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import openapiPlugin from 'sveltekit-openapi-generator';
|
||||||
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf-8'));
|
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf-8'));
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [openapiPlugin({
|
plugins: [enhancedImages(), openapiPlugin({
|
||||||
info: {
|
info: {
|
||||||
title: 'Wanderer API',
|
title: 'Wanderer API',
|
||||||
version: `${packageJson.version}`,
|
version: `${packageJson.version}`,
|
||||||
@@ -16,7 +17,7 @@ export default defineConfig({
|
|||||||
outputPath: 'static/docs/api/wanderer.openapi.json',
|
outputPath: 'static/docs/api/wanderer.openapi.json',
|
||||||
include: ['src/routes/api/v1/**/*.{js,ts}'],
|
include: ['src/routes/api/v1/**/*.{js,ts}'],
|
||||||
baseSchemasPath: 'src/lib/models/api/openapi_schemas.ts',
|
baseSchemasPath: 'src/lib/models/api/openapi_schemas.ts',
|
||||||
}),tailwindcss(), sveltekit()],
|
}), tailwindcss(), sveltekit()],
|
||||||
test: { include: ['src/**/*.{test,spec}.{js,ts}'] },
|
test: { include: ['src/**/*.{test,spec}.{js,ts}'] },
|
||||||
ssr: { noExternal: ['three'] },
|
ssr: { noExternal: ['three'] },
|
||||||
...(process.env.WANDERER_ENV == "dev" ? {
|
...(process.env.WANDERER_ENV == "dev" ? {
|
||||||
|
|||||||
Reference in New Issue
Block a user