Merge branch 'add-splash-screen'

This commit is contained in:
Youwen Wu 2024-03-11 22:37:30 -07:00
commit 4ff0b59cd7
Signed by: youwen5
GPG key ID: 865658ED1FE61EC3
39 changed files with 2071 additions and 23 deletions

View file

@ -69,8 +69,12 @@ to get the development build up and running.
### Installation steps ### Installation steps
1. Clone the repository. The `client` folder contains the vast majority of the 1. Clone the repository. The `client` directory contains the vast majority of
source code for the desktop app. the source code for the desktop app, while the `splash-screen` directory
contains the source code for the splash screen displayed before the app
loads. You don't have to touch anything in `splash-screen` unless you want to
modify it, in which case check the README in `splash-screen` for more
information.
2. `cd` into the `client` folder. The configuration files and `package.json`, 2. `cd` into the `client` folder. The configuration files and `package.json`,
This is where stuff like `package.json` and configuration files for our This is where stuff like `package.json` and configuration files for our
various tooling are housed. The `client/src-tauri` directory contains the various tooling are housed. The `client/src-tauri` directory contains the

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
client/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View file

@ -0,0 +1,45 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="212.000000pt" height="212.000000pt" viewBox="0 0 212.000000 212.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,212.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1159 2097 c-14 -13 -29 -37 -33 -53 -3 -16 -9 -40 -11 -54 -12 -53
-17 -59 -50 -66 -18 -3 -39 -3 -45 1 -6 4 -24 35 -40 69 -45 99 -104 122 -144
56 -14 -25 -17 -45 -13 -99 5 -78 3 -86 -37 -100 -33 -13 -39 -10 -93 50 -43
47 -90 67 -126 53 -32 -12 -35 -73 -8 -153 l25 -74 -30 -23 c-16 -13 -33 -24
-37 -24 -4 0 -34 17 -65 38 -59 39 -108 46 -138 21 -29 -24 -16 -82 32 -147
48 -64 50 -84 16 -115 -16 -15 -24 -15 -82 -1 -36 8 -79 12 -97 9 -84 -15 -70
-95 27 -161 64 -42 66 -45 49 -92 -12 -34 -20 -37 -103 -41 -96 -4 -133 -46
-93 -106 16 -25 37 -38 92 -57 l70 -24 0 -45 0 -44 -64 -21 c-65 -21 -111 -59
-111 -91 0 -8 14 -28 31 -44 29 -27 37 -29 109 -29 77 0 78 0 90 -30 16 -39
10 -52 -48 -97 -53 -41 -72 -69 -72 -109 0 -19 8 -29 37 -41 35 -14 44 -14
110 2 70 18 74 18 93 0 33 -30 34 -52 2 -93 -39 -49 -49 -71 -53 -108 -8 -76
65 -87 162 -24 64 41 76 42 111 3 16 -18 16 -23 -6 -92 -26 -83 -20 -127 21
-137 23 -6 93 12 93 24 0 4 24 33 53 65 29 31 52 58 51 60 -7 7 -15 113 -20
257 -8 223 18 410 73 540 56 131 122 213 205 254 28 14 53 24 55 22 2 -2 -6
-38 -18 -81 -28 -102 -23 -183 13 -253 l27 -51 -54 -83 c-55 -84 -64 -114 -45
-163 10 -26 56 -75 71 -75 4 0 24 24 45 53 21 28 41 54 44 57 3 3 21 28 39 55
41 58 53 69 63 52 14 -26 -22 -147 -45 -147 -6 0 -8 -3 -4 -6 3 -4 -10 -31
-29 -61 l-35 -55 21 -43 c25 -52 96 -128 113 -121 7 2 53 19 104 36 98 33 98
33 108 110 13 98 57 191 164 345 39 54 74 118 80 141 9 36 21 50 79 92 52 38
68 55 70 76 1 15 11 78 21 140 18 104 19 117 5 171 l-15 58 50 51 c50 52 72
106 52 135 -5 7 -27 17 -49 21 -33 6 -53 2 -108 -22 l-67 -30 -29 30 -30 29
37 72 c38 76 40 116 10 141 -27 23 -94 1 -145 -46 -26 -24 -56 -44 -67 -44
-30 0 -66 38 -59 64 17 69 17 124 2 154 -30 58 -93 34 -152 -57 -31 -48 -44
-61 -65 -61 -43 0 -60 20 -65 80 -8 81 -32 124 -69 127 -20 2 -39 -5 -56 -20z
m-29 -685 c0 -4 -28 -21 -62 -36 -304 -140 -494 -464 -515 -881 -3 -55 -7
-102 -10 -105 -2 -2 -18 11 -34 30 -17 19 -41 47 -54 63 -13 15 -21 27 -18 27
2 0 -5 13 -16 29 -31 43 -81 153 -81 177 0 59 119 292 199 391 27 33 46 65 43
69 -4 4 -2 4 4 1 6 -3 24 7 40 24 96 101 254 178 415 204 46 7 85 13 87 14 1
0 2 -3 2 -7z m554 -134 c-10 -45 -6 -96 10 -126 12 -23 9 -31 -33 -103 -25
-44 -49 -79 -53 -79 -10 0 -48 123 -50 161 -2 68 2 88 28 119 23 27 72 57 97
59 5 1 5 -14 1 -31z m-204 -828 c-14 -26 -68 -60 -96 -60 -16 0 -24 10 -32 39
-18 57 -16 61 17 45 26 -13 34 -13 64 0 19 7 38 20 43 27 14 22 17 -26 4 -51z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,14 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,17 @@
use tauri::{Manager, Window};
// Create the command:
// This command must be async so that it doesn't run on the main thread.
#[tauri::command]
pub async fn close_splashscreen(window: Window) {
tracing::info!("Closing splashscreen");
// Close splashscreen
match window.get_window("splashscreen") {
Some(window) => window.close().unwrap(),
None => tracing::info!("Couldn't find splashscreen window"),
}
match window.get_window("main") {
Some(window) => window.show().unwrap(),
None => tracing::info!("Couldn't find main window"),
}
}

View file

@ -4,6 +4,8 @@
use tauri::Manager; use tauri::Manager;
mod telemetry; mod telemetry;
use tracing_subscriber::FmtSubscriber; use tracing_subscriber::FmtSubscriber;
mod close_splashscreen;
use close_splashscreen::close_splashscreen;
#[derive(Clone, serde::Serialize)] #[derive(Clone, serde::Serialize)]
struct Payload { struct Payload {
@ -34,6 +36,7 @@ fn main() {
Ok(()) Ok(())
}) })
.invoke_handler(tauri::generate_handler![close_splashscreen])
.run(tauri::generate_context!()) .run(tauri::generate_context!())
.expect("failed to run app") .expect("failed to run app")
}) })

View file

@ -1,8 +1,8 @@
{ {
"$schema": "../node_modules/@tauri-apps/cli/schema.json", "$schema": "../node_modules/@tauri-apps/cli/schema.json",
"build": { "build": {
"beforeBuildCommand": "npm run build", "beforeBuildCommand": "pnpm build",
"beforeDevCommand": "npm run dev", "beforeDevCommand": "pnpm dev",
"devPath": "http://localhost:5173", "devPath": "http://localhost:5173",
"distDir": "../dist" "distDir": "../dist"
}, },
@ -62,7 +62,21 @@
"height": 600, "height": 600,
"resizable": true, "resizable": true,
"title": "Jankboard 2", "title": "Jankboard 2",
"width": 800 "width": 800,
"visible": false,
"label": "main"
},
{
"fullscreen": false,
"maximized": true,
"decorations": false,
"titleBarStyle": "Transparent",
"height": 600,
"resizable": true,
"width": 800,
"url": "splashscreen.html",
"label": "splashscreen",
"visible": true
} }
] ]
} }

View file

@ -9,13 +9,17 @@
import { onDestroy, onMount } from 'svelte' import { onDestroy, onMount } from 'svelte'
import { Toaster } from 'svelte-french-toast' import { Toaster } from 'svelte-french-toast'
import { initializationSequence } from './lib/Sequences/sequences' import { initializationSequence } from './lib/Sequences/sequences'
import Loading from './lib/Loading/Loading.svelte'
import { settingsStore } from './lib/stores/settingsStore' import { settingsStore } from './lib/stores/settingsStore'
import getSettings from './lib/utils/getSettings' import getSettings from './lib/utils/getSettings'
import hideSplashscreen from './lib/utils/hideSplashscreen'
let activeApp: App = 'camera' let activeApp: App = 'camera'
// fake loading splash screen to look cool if the model loads too fast
let fakeLoadingDone = false
// and the real one, to wait for massive robot model to load if it's slow
let realLoadingDone = false
let started = false
let loading = $settingsStore.fastStartup ? false : true
let unlistenAll: () => void let unlistenAll: () => void
onMount(() => { onMount(() => {
@ -28,28 +32,39 @@
initializeTelemetry().then((unsubFunction: () => void) => { initializeTelemetry().then((unsubFunction: () => void) => {
unlistenAll = unsubFunction unlistenAll = unsubFunction
}) })
setTimeout(() => {
loading = false
initializationSequence()
}, 3000)
settingsStore.subscribe((value) => { settingsStore.subscribe((value) => {
localStorage.setItem('settings', JSON.stringify(value)) localStorage.setItem('settings', JSON.stringify(value))
}) })
setTimeout(() => {
fakeLoadingDone = true
}, 3000)
}) })
onDestroy(() => { onDestroy(() => {
unlistenAll && unlistenAll() unlistenAll && unlistenAll()
}) })
const start = () => {
hideSplashscreen()
initializationSequence()
}
const onVisualizationLoaded = () => {
realLoadingDone = true
}
$: if (realLoadingDone && fakeLoadingDone && !started) {
started = true
start()
}
</script> </script>
<main <main class="select-none transition-opacity duration-300">
class="select-none transition-opacity duration-300"
class:opacity-0={loading}
>
<!-- driver dashboard --> <!-- driver dashboard -->
<div class="h-screen w-[35vw] fixed shadow-lg shadow-slate-800 z-10"> <div class="h-screen w-[35vw] fixed shadow-lg shadow-slate-800 z-10">
<Dashboard /> <Dashboard on:loaded={onVisualizationLoaded} />
</div> </div>
<!-- the infotainment system --> <!-- the infotainment system -->
<div class="min-h-screen w-[65vw] right-0 absolute infotainment-container"> <div class="min-h-screen w-[65vw] right-0 absolute infotainment-container">
@ -63,10 +78,6 @@
</div> </div>
</main> </main>
{#if loading}
<Loading />
{/if}
<!-- toast service --> <!-- toast service -->
<Toaster /> <Toaster />

View file

@ -45,7 +45,7 @@
</div> </div>
<div class="left-0 mt-2 h-[475px] w-[35vw]"> <div class="left-0 mt-2 h-[475px] w-[35vw]">
<Visualization /> <Visualization on:loaded />
</div> </div>
<Bottom> <Bottom>

View file

@ -11,6 +11,9 @@
import RobotDecimated from './models/RobotDecimated.svelte' import RobotDecimated from './models/RobotDecimated.svelte'
import { telemetryReadonlyStore } from '../../stores/telemetryStore' import { telemetryReadonlyStore } from '../../stores/telemetryStore'
import { DEG2RAD } from 'three/src/math/MathUtils.js' import { DEG2RAD } from 'three/src/math/MathUtils.js'
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
const SPEED_MULTIPLIER = 4 const SPEED_MULTIPLIER = 4
const axis = new Vector3(0, 1, 0) const axis = new Vector3(0, 1, 0)
@ -137,6 +140,7 @@
on:create={({ ref }) => { on:create={({ ref }) => {
// @ts-expect-error // @ts-expect-error
mesh.set(ref) mesh.set(ref)
dispatch('loaded')
}} }}
/> />

View file

@ -4,5 +4,5 @@
</script> </script>
<Canvas> <Canvas>
<Scene /> <Scene on:loaded />
</Canvas> </Canvas>

View file

@ -0,0 +1,6 @@
import { invoke } from '@tauri-apps/api/tauri'
export default async () => {
console.log('hiding')
await invoke('close_splashscreen')
}

24
splash-screen/.gitignore vendored Normal file
View file

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

46
splash-screen/README.md Normal file
View file

@ -0,0 +1,46 @@
# Jankboard 2 Splash Screen
This directory contains the source code for the splash screen used by the Tauri
app. It's a standalone Svelte + Vite project, with its own separate
dependencies. In most cases, you won't ever have to touch the code in this
directory unless you want to modify the loading screen. However, if you do
decide to modify the files in this directory, keep in mind that **_they will not
be reflected in the app until you compile and replace the_** `splashscreen.html`
**_file in_** `/client/public`. Read more below to figure out how to do that.
## How it works
Tauri allows you to add a splash screen to display before your app loads by
adding a file to the output directory called `splashscreen.html`. This is done
in Jankboard 2 by adding the `splashscreen.html` file to the `public` directory,
as recommended by Tauri's docs. However, since it's just one HTML file, we can't
typically use a framework like Svelte, which outputs a CSS and JS bundle. While
we can definitely write a simple splash screen in a raw HTML file, we miss out
on nice Svelte features like easy to write animations. The Vite project in this
directory solves that by using
[vite-plugin-singlefile](https://github.com/richardtallent/vite-plugin-singlefile)
to inline all CSS and JS outputted by Svelte's compiler into the HTML, resulting
in a nice single `index.html` output in `./dist`, which can then be renamed as
`splashscreen.html` and moved into the main Jankboard 2 project to be used as
the loading splash screen. The best part about this is that since Svelte is
meant to be compiled into such a small bundle size, there are virtually zero
downsides to doing this versus writing the splash screen in raw HTML. We can
easily write a nice looking splash screen using the same techniques as our
existing codebase without having to deal with raw HTML and CSS. If you don't
need to modify the splash screen, you **don't need to touch this project!**
`splashscreen.html` is already included in the main project and you don't have
to build it yourself here. If you do want to modify this splash screen, continue
to the instructions below.
## Installation and development instructions
**Again, you don't need to do this if you don't want to modify the splash
screen!**
1. Install dependencies via `pnpm install`.
2. Run `pnpm dev` to start the development server.
3. After you're done making your changes, run `pnpm build`. This will output a
single `index.html` file to `./dist`, which contains all of the JS and CSS
inlined.
4. Rename this outputted `index.html` to `splashscreen.html`, and then move it
into `/client/public`, replacing the existing `splashscreen.html`.

12
splash-screen/index.html Normal file
View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Jankboard 2</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View file

@ -0,0 +1,25 @@
{
"name": "splash-screen",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.json"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^3.0.2",
"@tsconfig/svelte": "^5.0.2",
"autoprefixer": "^10.4.18",
"postcss": "^8.4.35",
"svelte": "^4.2.11",
"svelte-check": "^3.6.4",
"tailwindcss": "^3.4.1",
"tslib": "^2.6.2",
"typescript": "^5.2.2",
"vite": "^5.1.4",
"vite-plugin-singlefile": "^2.0.1"
}
}

1678
splash-screen/pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View file

@ -0,0 +1,15 @@
<script lang="ts">
import Loading from './lib/Loading.svelte'
</script>
<svelte:head>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5" />
<meta name="msapplication-TileColor" content="#da532c" />
<meta name="theme-color" content="#ffffff" />
</svelte:head>
<Loading />

12
splash-screen/src/app.css Normal file
View file

@ -0,0 +1,12 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
background-image: url('./assets/background.jpg');
background-repeat: no-repeat;
background-size: cover;
overflow: hidden;
overscroll-behavior: none;
user-select: none;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

View file

@ -1,7 +1,16 @@
<script lang="ts"> <script lang="ts">
import { blur } from 'svelte/transition' import { blur, fade } from 'svelte/transition'
import SvelteLogo from './SvelteLogo.svelte' import SvelteLogo from './SvelteLogo.svelte'
import { onMount } from 'svelte'
let loadingStuck = false
onMount(() => {
setTimeout(() => {
loadingStuck = true
}, 3000)
})
</script> </script>
<div <div
@ -11,6 +20,14 @@
<div class="max-w-64"> <div class="max-w-64">
<SvelteLogo /> <SvelteLogo />
</div> </div>
{#if loadingStuck}
<p
class="text-5xl text-slate-300 absolute bottom-20 animate-pulse"
transition:fade={{ duration: 300 }}
>
Loading 3D assets...please wait
</p>
{/if}
</div> </div>
<style lang="postcss"> <style lang="postcss">

View file

@ -0,0 +1,8 @@
import './app.css'
import App from './App.svelte'
const app = new App({
target: document.getElementById('app'),
})
export default app

2
splash-screen/src/vite-env.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
/// <reference types="svelte" />
/// <reference types="vite/client" />

View file

@ -0,0 +1,7 @@
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
export default {
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
// for more information about preprocessors
preprocess: vitePreprocess(),
}

View file

@ -0,0 +1,8 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {},
},
plugins: [],
}

View file

@ -0,0 +1,20 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"resolveJsonModule": true,
/**
* Typecheck JS in `.svelte` and `.js` files by default.
* Disable checkJs if you'd like to use dynamic types in JS.
* Note that setting allowJs false does not prevent the use
* of JS in `.svelte` files.
*/
"allowJs": true,
"checkJs": true,
"isolatedModules": true
},
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View file

@ -0,0 +1,10 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true
},
"include": ["vite.config.ts"]
}

View file

@ -0,0 +1,8 @@
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import { viteSingleFile } from 'vite-plugin-singlefile'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [svelte(), viteSingleFile()],
})