Compare commits

..

6 Commits

Author SHA1 Message Date
31f7d5bcfa Merge branch 'develop' into bigpicturemode 2025-10-14 17:23:52 +11:00
87bbe1da49 156 refactor into workspaces (#157)
* chore: Major refactoring

Still needs a massive go-over because there shouldn't be anything referencing tauri in any of the workspaces except the original one. Process manager has been refactored as an example

Signed-off-by: quexeky <git@quexeky.dev>

* fix: Remote tauri dependency from process

Signed-off-by: quexeky <git@quexeky.dev>

* refactor: Improvements to src-tauri

Signed-off-by: quexeky <git@quexeky.dev>

* refactor: Builds, but some logic still left to move back

Signed-off-by: quexeky <git@quexeky.dev>

* refactor: Finish refactor

Signed-off-by: quexeky <git@quexeky.dev>

* chore: Run cargo clippy && cargo fmt

Signed-off-by: quexeky <git@quexeky.dev>

* refactor: Move everything into src-tauri

Signed-off-by: quexeky <git@quexeky.dev>

---------

Signed-off-by: quexeky <git@quexeky.dev>
2025-10-14 17:12:51 +11:00
ab9e06f6c4 feat: improvements to jump calculator 2025-09-24 07:38:37 +10:00
dbf9c8e8e5 feat: prototype big picture mode 2025-09-23 18:05:35 +10:00
864640d6ae feat: finish big picture navigation 2025-09-23 16:37:25 +10:00
e29d5c8ead partial: mutationobserver 2025-09-23 15:38:30 +10:00
147 changed files with 16838 additions and 9180 deletions

8290
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +0,0 @@
[workspace]
members = [
"client",
"database",
"src-tauri",
"process",
"remote",
"utils",
"cloud_saves",
"download_manager",
"games",
]
resolver = "3"

View File

@ -1,5 +1,5 @@
<template> <template>
<NuxtLoadingIndicator color="#2563eb" /> <NuxtLoadingIndicator color="#2563eb" />
<NuxtLayout class="select-none w-screen h-screen"> <NuxtLayout class="select-none w-screen h-screen">
<NuxtPage /> <NuxtPage />
<ModalStack /> <ModalStack />
@ -7,14 +7,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import "~/composables/downloads.js";
import { invoke } from "@tauri-apps/api/core"; import { invoke } from "@tauri-apps/api/core";
import { useAppState } from "./composables/app-state.js";
import {
initialNavigation,
setupHooks,
} from "./composables/state-navigation.js";
const router = useRouter(); const router = useRouter();

View File

@ -2,9 +2,7 @@
<div class="h-16 bg-zinc-950 flex flex-row justify-between"> <div class="h-16 bg-zinc-950 flex flex-row justify-between">
<div class="flex flex-row grow items-center pl-5 pr-2 py-3"> <div class="flex flex-row grow items-center pl-5 pr-2 py-3">
<div class="inline-flex items-center gap-x-10"> <div class="inline-flex items-center gap-x-10">
<NuxtLink to="/store"> <Wordmark class="h-8 mb-0.5" />
<Wordmark class="h-8 mb-0.5" />
</NuxtLink>
<nav class="inline-flex items-center mt-0.5"> <nav class="inline-flex items-center mt-0.5">
<ol class="inline-flex items-center gap-x-6"> <ol class="inline-flex items-center gap-x-6">
<NuxtLink <NuxtLink
@ -42,7 +40,7 @@
</ol> </ol>
</div> </div>
</div> </div>
<WindowControl /> <WindowControl />
</div> </div>
</template> </template>

View File

@ -76,7 +76,6 @@ import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/vue";
import { ChevronDownIcon } from "@heroicons/vue/16/solid"; import { ChevronDownIcon } from "@heroicons/vue/16/solid";
import type { NavigationItem } from "../types"; import type { NavigationItem } from "../types";
import HeaderWidget from "./HeaderWidget.vue"; import HeaderWidget from "./HeaderWidget.vue";
import { useAppState } from "~/composables/app-state";
import { invoke } from "@tauri-apps/api/core"; import { invoke } from "@tauri-apps/api/core";
const open = ref(false); const open = ref(false);

View File

@ -73,7 +73,7 @@
alt="" alt=""
/> />
</div> </div>
<div class="inline-flex items-center gap-x-2"> <div class="flex flex-col gap-x-2">
<p <p
class="text-sm whitespace-nowrap font-display font-semibold" class="text-sm whitespace-nowrap font-display font-semibold"
> >

View File

@ -1,7 +0,0 @@
<template>
<NuxtLink
class="inline-flex items-center gap-x-2 px-1 py-0.5 rounded bg-blue-900 text-zinc-100 hover:bg-blue-800"
>
<slot />
</NuxtLink>
</template>

View File

@ -9,13 +9,17 @@ export default defineNuxtConfig({
}, },
}, },
css: ["~/assets/main.scss"],
ssr: false, ssr: false,
extends: [["../libs/drop-base"]], extends: ["../shared", "../libs/drop-base"],
app: { app: {
baseURL: "/main", baseURL: "/main",
} },
devtools: {
enabled: false,
},
}); });

View File

@ -116,7 +116,7 @@ platformInfo.value = currentPlatform;
async function openDataDir() { async function openDataDir() {
if (!dataDir.value) return; if (!dataDir.value) return;
try { try {
await invoke("open_fs", { path: dataDir.value }); await open(dataDir.value);
} catch (error) { } catch (error) {
console.error("Failed to open data dir:", error); console.error("Failed to open data dir:", error);
} }
@ -126,7 +126,7 @@ async function openLogFile() {
if (!dataDir.value) return; if (!dataDir.value) return;
try { try {
const logPath = `${dataDir.value}/drop.log`; const logPath = `${dataDir.value}/drop.log`;
await invoke("open_fs", { path: logPath }); await open(logPath);
} catch (error) { } catch (error) {
console.error("Failed to open log file:", error); console.error("Failed to open log file:", error);
} }

View File

@ -7,6 +7,7 @@ export default {
"./plugins/**/*.{js,ts}", "./plugins/**/*.{js,ts}",
"./app.vue", "./app.vue",
"./error.vue", "./error.vue",
"../shared/components/**/*.vue"
], ],
theme: { theme: {
extend: { extend: {

50
shared/app.vue Normal file
View File

@ -0,0 +1,50 @@
<template>
<NuxtLoadingIndicator color="#2563eb" />
<NuxtLayout class="select-none w-screen h-screen">
<NuxtPage />
<ModalStack />
</NuxtLayout>
</template>
<script setup lang="ts">
import "~/composables/downloads.js";
import { invoke } from "@tauri-apps/api/core";
import { useAppState } from "./composables/app-state.js";
import {
initialNavigation,
setupHooks,
} from "./composables/state-navigation.js";
const router = useRouter();
const state = useAppState();
async function fetchState() {
try {
state.value = JSON.parse(await invoke("fetch_state"));
if (!state.value)
throw createError({
statusCode: 500,
statusMessage: `App state is: ${state.value}`,
fatal: true,
});
} catch (e) {
console.error("failed to parse state", e);
throw e;
}
}
await fetchState();
// This is inefficient but apparently we do it lol
router.beforeEach(async () => {
await fetchState();
});
setupHooks();
initialNavigation(state);
useHead({
title: "Drop",
});
</script>

84
shared/assets/main.scss Normal file
View File

@ -0,0 +1,84 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
html,
body {
-ms-overflow-style: none; /* IE and Edge /
scrollbar-width: none; / Firefox */
}
/* Hide scrollbar for Chrome, Safari and Opera */
html::-webkit-scrollbar {
display: none;
}
$motiva: (
("MotivaSansThin.ttf", "ttf", 100, normal),
("MotivaSansLight.woff.ttf", "woff", 300, normal),
("MotivaSansRegular.woff.ttf", "woff", 400, normal),
("MotivaSansMedium.woff.ttf", "woff", 500, normal),
("MotivaSansBold.woff.ttf", "woff", 600, normal),
("MotivaSansExtraBold.ttf", "woff", 700, normal),
("MotivaSansBlack.woff.ttf", "woff", 900, normal)
);
$helvetica: (
("Helvetica.woff", "woff", 400, normal),
("Helvetica-Oblique.woff", "woff", 400, italic),
("Helvetica-Bold.woff", "woff", 600, normal),
("Helvetica-BoldOblique.woff", "woff", 600, italic),
("helvetica-light-587ebe5a59211.woff2", "woff2", 300, normal)
);
@each $file, $format, $weight, $style in $motiva {
@font-face {
font-family: "Motiva Sans";
src: url("/fonts/motiva/#{$file}") format($format);
font-weight: $weight;
font-style: $style;
}
}
@each $file, $format, $weight, $style in $helvetica {
@font-face {
font-family: "Helvetica";
src: url("/fonts/helvetica/#{$file}") format($format);
font-weight: $weight;
font-style: $style;
}
}
@font-face {
font-family: "Inter";
src: url("/fonts/inter/InterVariable.ttf");
font-style: normal;
}
@font-face {
font-family: "Inter";
src: url("/fonts/inter/InterVariable-Italic.ttf");
font-style: italic;
}
/* ===== Scrollbar CSS ===== */
/* Firefox */
* {
scrollbar-width: 4px;
scrollbar-color: #52525b #00000000;
}
/* Chrome, Edge, and Safari */
*::-webkit-scrollbar {
width: 4px;
}
*::-webkit-scrollbar-track {
background: transparent;
}
*::-webkit-scrollbar-thumb {
background-color: #52525b;
border-radius: 10px;
border: 3px solid #52525b;
}

View File

@ -1,5 +1,5 @@
import { convertFileSrc } from "@tauri-apps/api/core"; import { convertFileSrc } from "@tauri-apps/api/core";
export const useObject = async (id: string) => { export const useObject = (id: string) => {
return convertFileSrc(id, "object"); return convertFileSrc(id, "object");
}; };

91
shared/error.vue Normal file
View File

@ -0,0 +1,91 @@
<template>
<NuxtLayout name="default">
<div
class="grid min-h-full grid-cols-1 grid-rows-[1fr,auto,1fr] lg:grid-cols-[max(50%,36rem),1fr]"
>
<header
class="mx-auto w-full max-w-7xl px-6 pt-6 sm:pt-10 lg:col-span-2 lg:col-start-1 lg:row-start-1 lg:px-8"
>
<Logo class="h-10 w-auto sm:h-12" />
</header>
<main
class="mx-auto w-full max-w-7xl px-6 py-24 sm:py-32 lg:col-span-2 lg:col-start-1 lg:row-start-2 lg:px-8"
>
<div class="max-w-lg">
<p class="text-base font-semibold leading-8 text-blue-600">
{{ error?.statusCode }}
</p>
<h1
class="mt-4 text-3xl font-bold font-display tracking-tight text-zinc-100 sm:text-5xl"
>
Oh no!
</h1>
<p
v-if="message"
class="mt-3 font-bold text-base leading-7 text-red-500"
>
{{ message }}
</p>
<p class="mt-6 text-base leading-7 text-zinc-400">
An error occurred while responding to your request. If you believe
this to be a bug, please report it. Try signing in and see if it
resolves the issue.
</p>
<div class="mt-10">
<!-- full app reload to fix errors -->
<a
href="/store"
class="text-sm font-semibold leading-7 text-blue-600"
><span aria-hidden="true">&larr;</span> Back to store</a
>
</div>
</div>
</main>
<footer class="self-end lg:col-span-2 lg:col-start-1 lg:row-start-3">
<div class="border-t border-zinc-700 bg-zinc-900 py-10">
<nav
class="mx-auto flex w-full max-w-7xl items-center gap-x-4 px-6 text-sm leading-7 text-zinc-400 lg:px-8"
>
<NuxtLink href="/docs">Documentation</NuxtLink>
<svg
viewBox="0 0 2 2"
aria-hidden="true"
class="h-0.5 w-0.5 fill-zinc-600"
>
<circle cx="1" cy="1" r="1" />
</svg>
<a href="https://discord.gg/NHx46XKJWA" target="_blank"
>Support Discord</a
>
</nav>
</div>
</footer>
<div
class="hidden lg:relative lg:col-start-2 lg:row-start-1 lg:row-end-4 lg:block"
>
<img
src="@/assets/wallpaper.jpg"
alt=""
class="absolute inset-0 h-full w-full object-cover"
/>
</div>
</div>
</NuxtLayout>
</template>
<script setup lang="ts">
import type { NuxtError } from "#app";
const props = defineProps({
error: Object as () => NuxtError,
});
const statusCode = props.error?.statusCode;
const message =
props.error?.statusMessage ||
props.error?.message ||
"An unknown error occurred.";
console.error(props.error);
</script>

25
shared/nuxt.config.ts Normal file
View File

@ -0,0 +1,25 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: "2024-04-03",
postcss: {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
},
css: ["~/assets/main.scss"],
ssr: false,
extends: [["../libs/drop-base"]],
app: {
baseURL: "/main",
},
devtools: {
enabled: false,
},
});

37
shared/package.json Normal file
View File

@ -0,0 +1,37 @@
{
"name": "view",
"private": true,
"version": "0.3.3",
"type": "module",
"scripts": {
"build": "nuxt generate",
"dev": "nuxt dev",
"postinstall": "nuxt prepare",
"tauri": "tauri"
},
"dependencies": {
"@headlessui/vue": "^1.7.23",
"@heroicons/vue": "^2.1.5",
"@nuxtjs/tailwindcss": "^6.12.2",
"@tauri-apps/api": "^2.7.0",
"koa": "^2.16.1",
"markdown-it": "^14.1.0",
"micromark": "^4.0.1",
"nuxt": "^3.16.0",
"scss": "^0.2.4",
"vue-router": "latest",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.9",
"@tailwindcss/typography": "^0.5.15",
"@types/markdown-it": "^14.1.2",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.47",
"sass-embedded": "^1.79.4",
"tailwindcss": "^3.4.13",
"typescript": "^5.8.3",
"vue-tsc": "^2.2.10"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}

20
shared/tailwind.config.js Normal file
View File

@ -0,0 +1,20 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./components/**/*.{js,vue,ts}",
"./layouts/**/*.vue",
"./pages/**/*.vue",
"./plugins/**/*.{js,ts}",
"./app.vue",
"./error.vue",
],
theme: {
extend: {
fontFamily: {
sans: ["Inter"],
display: ["Motiva Sans"],
},
},
},
plugins: [require("@tailwindcss/forms"), require('@tailwindcss/typography')],
};

5
shared/tsconfig.json Normal file
View File

@ -0,0 +1,5 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json",
"exclude": ["src-tauri/**/*"]
}

96
shared/types.ts Normal file
View File

@ -0,0 +1,96 @@
import type { Component } from "vue";
export type NavigationItem = {
prefix: string;
route: string;
label: string;
};
export type QuickActionNav = {
icon: Component;
notifications?: number;
action: () => Promise<void>;
};
export type User = {
id: string;
username: string;
admin: boolean;
displayName: string;
profilePictureObjectId: string;
};
export type AppState = {
status: AppStatus;
user?: User;
};
export type Game = {
id: string;
mName: string;
mShortDescription: string;
mDescription: string;
mIconObjectId: string;
mBannerObjectId: string;
mCoverObjectId: string;
mImageLibraryObjectIds: string[];
mImageCarouselObjectIds: string[];
};
export type Collection = {
id: string;
name: string;
isDefault: boolean;
entries: Array<{ gameId: string; game: Game }>;
};
export type GameVersion = {
launchCommandTemplate: string;
};
export enum AppStatus {
NotConfigured = "NotConfigured",
Offline = "Offline",
SignedOut = "SignedOut",
SignedIn = "SignedIn",
SignedInNeedsReauth = "SignedInNeedsReauth",
ServerUnavailable = "ServerUnavailable",
}
export enum GameStatusEnum {
Remote = "Remote",
Queued = "Queued",
Downloading = "Downloading",
Validating = "Validating",
Installed = "Installed",
Updating = "Updating",
Uninstalling = "Uninstalling",
SetupRequired = "SetupRequired",
Running = "Running",
PartiallyInstalled = "PartiallyInstalled",
}
export type GameStatus = {
type: GameStatusEnum;
version_name?: string;
install_dir?: string;
};
export enum DownloadableType {
Game = "Game",
Tool = "Tool",
DLC = "DLC",
Mod = "Mod",
}
export type DownloadableMetadata = {
id: string;
version: string;
downloadType: DownloadableType;
};
export type Settings = {
autostart: boolean;
maxDownloadThreads: number;
forceOffline: boolean;
};

8091
shared/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

2209
src-tauri/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -80,13 +80,13 @@ bytes = "1.10.1"
# Workspaces # Workspaces
client = { version = "0.1.0", path = "../client" } client = { version = "0.1.0", path = "./client" }
database = { path = "../database" } database = { path = "./database" }
process = { path = "../process" } process = { path = "./process" }
remote = { version = "0.1.0", path = "../remote" } remote = { version = "0.1.0", path = "./remote" }
utils = { path = "../utils" } utils = { path = "./utils" }
games = { version = "0.1.0", path = "../games" } games = { version = "0.1.0", path = "./games" }
download_manager = { version = "0.1.0", path = "../download_manager" } download_manager = { version = "0.1.0", path = "./download_manager" }
[dependencies.dynfmt] [dependencies.dynfmt]
version = "0.1.5" version = "0.1.5"
@ -137,3 +137,18 @@ features = ["derive", "rc"]
lto = true lto = true
codegen-units = 1 codegen-units = 1
panic = 'abort' panic = 'abort'
[workspace]
members = [
"client",
"database",
"process",
"remote",
"utils",
"cloud_saves",
"download_manager",
"games",
]
resolver = "3"

Some files were not shown because too many files have changed in this diff Show More