Inital Commit

This commit is contained in:
2026-01-24 02:32:25 +00:00
commit a4b7c82b1a
54 changed files with 888 additions and 0 deletions

13
frontend/src/app.html Normal file
View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Tauri + SvelteKit + Typescript App</title>
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

View File

@@ -0,0 +1,78 @@
<script>
import { onMount } from "svelte";
import { isTauri } from "@tauri-apps/api/core";
import WebNavbar from "$lib/components/WebNavbar.svelte";
import WebFooter from "$lib/components/WebFooter.svelte";
import MobileTabBar from "$lib/components/MobileTabBar.svelte";
let { children } = $props();
// State to track if we are in the Tauri App
let isApp = $state(false);
onMount(() => {
// Strategy 2: Determine mode
isApp = isTauri();
// Strategy 1: Add platform class to body for global styling
if (isApp) {
document.body.classList.add("platform-native");
} else {
document.body.classList.add("platform-web");
}
});
</script>
<!-- Strategy 2: Layout Splitting -->
{#if isApp}
<main class="app-container">
{@render children()}
</main>
<MobileTabBar />
{:else}
<WebNavbar />
<main class="web-container">
{@render children()}
</main>
<WebFooter />
{/if}
<style>
/* Base styles */
:global(body) {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
/* Web specific container */
.web-container {
min-height: 80vh; /* Ensure footer pushes down */
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* App specific container - Full height, no body scroll usually handled here or in global css */
.app-container {
height: 100vh;
overflow-y: auto;
padding: 10px;
padding-bottom: 70px; /* Space for TabBar */
box-sizing: border-box;
}
/* Strategy 1 Example: Global Style Overrides based on class */
/* Web Buttons: Boxy */
:global(.platform-web button) {
border-radius: 4px;
padding: 8px 16px;
}
/* Native Buttons: Rounder and larger touch targets */
:global(.platform-native button) {
border-radius: 20px;
padding: 12px 24px;
font-size: 1.1rem;
}
</style>

View File

@@ -0,0 +1,5 @@
// Tauri doesn't have a Node.js server to do proper SSR
// so we use adapter-static with a fallback to index.html to put the site in SPA mode
// See: https://svelte.dev/docs/kit/single-page-apps
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
export const ssr = false;

View File

@@ -0,0 +1,232 @@
<script lang="ts">
import { invoke, isTauri } from "@tauri-apps/api/core";
import { onMount } from "svelte";
import OnlyWeb from "$lib/components/OnlyWeb.svelte";
import OnlyMobile from "$lib/components/OnlyMobile.svelte";
let name = $state("");
let greetMsg = $state("");
let isNative = $state(false);
onMount(() => {
isNative = isTauri();
});
async function greet(event: Event) {
event.preventDefault();
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
greetMsg = await invoke("greet", { name });
}
</script>
<main class="container">
<h1>Welcome to Tauri + Svelte</h1>
<OnlyWeb>
<div class="download-banner">
<h2>Get the App</h2>
<p>
Experience the full power of our platform with the native app.
</p>
<a
href="https://play.google.com/store/apps"
target="_blank"
class="download-btn">Download for Android</a
>
</div>
</OnlyWeb>
<OnlyMobile>
<div class="mobile-highlight">
<p>📱 You are using the Native App!</p>
</div>
</OnlyMobile>
<div class="row">
<a href="https://vite.dev" target="_blank">
<img src="/vite.svg" class="logo vite" alt="Vite Logo" />
</a>
<a href="https://tauri.app" target="_blank">
<img src="/tauri.svg" class="logo tauri" alt="Tauri Logo" />
</a>
<a href="https://svelte.dev" target="_blank">
<img
src="/svelte.svg"
class="logo svelte-kit"
alt="SvelteKit Logo"
/>
</a>
</div>
<p>Click on the Tauri, Vite, and SvelteKit logos to learn more.</p>
<form class="row" onsubmit={greet}>
<input
id="greet-input"
placeholder="Enter a name..."
bind:value={name}
/>
<button type="submit">Greet</button>
</form>
<p>{greetMsg}</p>
</main>
<style>
.download-banner {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 2rem;
border-radius: 12px;
margin-bottom: 2rem;
text-align: center;
box-shadow:
0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.download-banner h2 {
margin-top: 0;
margin-bottom: 0.5rem;
}
.download-banner p {
margin-bottom: 1.5rem;
opacity: 0.9;
}
.download-btn {
display: inline-block;
background-color: white;
color: #764ba2;
padding: 0.8rem 1.5rem;
border-radius: 8px;
font-weight: bold;
text-decoration: none;
transition:
transform 0.2s,
box-shadow 0.2s;
}
.download-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
color: #667eea;
}
.logo.vite:hover {
filter: drop-shadow(0 0 2em #747bff);
}
.logo.svelte-kit:hover {
filter: drop-shadow(0 0 2em #ff3e00);
}
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color: #0f0f0f;
background-color: #f6f6f6;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
.container {
margin: 0;
padding-top: 10vh;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: 0.75s;
}
.logo.tauri:hover {
filter: drop-shadow(0 0 2em #24c8db);
}
.row {
display: flex;
justify-content: center;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
h1 {
text-align: center;
}
input,
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
color: #0f0f0f;
background-color: #ffffff;
transition: border-color 0.25s;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
}
button {
cursor: pointer;
}
button:hover {
border-color: #396cd8;
}
button:active {
border-color: #396cd8;
background-color: #e8e8e8;
}
input,
button {
outline: none;
}
#greet-input {
margin-right: 5px;
}
@media (prefers-color-scheme: dark) {
:root {
color: #f6f6f6;
background-color: #2f2f2f;
}
a:hover {
color: #24c8db;
}
input,
button {
color: #ffffff;
background-color: #0f0f0f98;
}
button:active {
background-color: #0f0f0f69;
}
}
</style>