diff --git a/components/Header.vue b/components/Header.vue
index e91edf5..75537eb 100644
--- a/components/Header.vue
+++ b/components/Header.vue
@@ -29,7 +29,6 @@
-
diff --git a/components/HeaderQueueWidget.vue b/components/HeaderQueueWidget.vue
index 105d14e..23c5ad5 100644
--- a/components/HeaderQueueWidget.vue
+++ b/components/HeaderQueueWidget.vue
@@ -1,17 +1,26 @@
-
+
+
diff --git a/composables/game.ts b/composables/game.ts
new file mode 100644
index 0000000..5eba1d9
--- /dev/null
+++ b/composables/game.ts
@@ -0,0 +1,31 @@
+import { invoke } from "@tauri-apps/api/core";
+import { listen } from "@tauri-apps/api/event";
+import type { Game, GameStatus } from "~/types";
+
+const gameRegistry: { [key: string]: Game } = {};
+
+const gameStatusRegistry: { [key: string]: Ref } = {};
+
+export const useGame = async (id: string) => {
+ if (!gameRegistry[id]) {
+ const data: { game: Game; status: GameStatus } = await invoke(
+ "fetch_game",
+ {
+ id,
+ }
+ );
+ gameRegistry[id] = data.game;
+ if (!gameStatusRegistry[id]) {
+ gameStatusRegistry[id] = ref(data.status);
+
+ listen(`update_game/${id}`, (event) => {
+ const payload: { status: GameStatus } = event.payload as any;
+ gameStatusRegistry[id].value = payload.status;
+ });
+ }
+ }
+
+ const game = gameRegistry[id];
+ const status = gameStatusRegistry[id];
+ return { game, status };
+};
diff --git a/composables/queue.ts b/composables/queue.ts
index f684852..0487260 100644
--- a/composables/queue.ts
+++ b/composables/queue.ts
@@ -1,7 +1,7 @@
import { listen } from "@tauri-apps/api/event";
export type QueueState = {
- queue: Array<{ id: string; status: string, progress: number }>;
+ queue: Array<{ id: string; status: string, progress: number | null }>;
};
export const useQueueState = () =>
diff --git a/package.json b/package.json
index 49c2009..c93e9a4 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,6 @@
"dependencies": {
"@headlessui/vue": "^1.7.23",
"@heroicons/vue": "^2.1.5",
- "@prisma/client": "5.20.0",
"@tauri-apps/api": ">=2.0.0",
"@tauri-apps/plugin-deep-link": "~2",
"@tauri-apps/plugin-dialog": "^2.0.1",
@@ -22,14 +21,14 @@
"nuxt": "^3.13.0",
"scss": "^0.2.4",
"vue": "latest",
- "vue-router": "latest"
+ "vue-router": "latest",
+ "vuedraggable": "^4.1.0"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.9",
"@tauri-apps/cli": ">=2.0.0",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.47",
- "prisma": "^5.20.0",
"sass-embedded": "^1.79.4",
"tailwindcss": "^3.4.13"
},
diff --git a/pages/library.vue b/pages/library.vue
index c91ea64..ac7e24f 100644
--- a/pages/library.vue
+++ b/pages/library.vue
@@ -40,12 +40,10 @@
diff --git a/plugins/vuedraggable.ts b/plugins/vuedraggable.ts
new file mode 100644
index 0000000..58d50a0
--- /dev/null
+++ b/plugins/vuedraggable.ts
@@ -0,0 +1,5 @@
+import draggable from "vuedraggable";
+
+export default defineNuxtPlugin((nuxtApp) => {
+ nuxtApp.vueApp.component("draggable", draggable);
+});
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
deleted file mode 100644
index 1ca51a1..0000000
--- a/prisma/schema.prisma
+++ /dev/null
@@ -1,150 +0,0 @@
-// This should be copied from the main Drop repo
-// TODO: do this automatically
-
-generator client {
- provider = "prisma-client-js"
-}
-
-datasource db {
- provider = "postgresql"
- url = env("DATABASE_URL")
-}
-
-model User {
- id String @id @default(uuid())
- username String @unique
- admin Boolean @default(false)
-
- email String
- displayName String
- profilePicture String // Object
-
- authMecs LinkedAuthMec[]
- clients Client[]
-}
-
-enum AuthMec {
- Simple
-}
-
-model LinkedAuthMec {
- userId String
- mec AuthMec
-
- credentials Json
-
- user User @relation(fields: [userId], references: [id])
-
- @@id([userId, mec])
-}
-
-enum ClientCapabilities {
- DownloadAggregation
-}
-
-enum Platform {
- Windows @map("windows")
- Linux @map("linux")
-}
-
-// References a device
-model Client {
- id String @id @default(uuid())
- userId String
- user User @relation(fields: [userId], references: [id])
-
- endpoint String
- capabilities ClientCapabilities[]
-
- name String
- platform Platform
- lastConnected DateTime
-}
-
-enum MetadataSource {
- Custom
- GiantBomb
-}
-
-model Game {
- id String @id @default(uuid())
-
- metadataSource MetadataSource
- metadataId String
-
- // Any field prefixed with m is filled in from metadata
- // Acts as a cache so we can search and filter it
- mName String // Name of game
- mShortDescription String // Short description
- mDescription String // Supports markdown
- mDevelopers Developer[]
- mPublishers Publisher[]
-
- mReviewCount Int
- mReviewRating Float
-
- mIconId String // linked to objects in s3
- mBannerId String // linked to objects in s3
- mCoverId String
- mImageLibrary String[] // linked to objects in s3
-
- versions GameVersion[]
- libraryBasePath String @unique // Base dir for all the game versions
-
- @@unique([metadataSource, metadataId], name: "metadataKey")
-}
-
-// A particular set of files that relate to the version
-model GameVersion {
- gameId String
- game Game @relation(fields: [gameId], references: [id])
- versionName String // Sub directory for the game files
-
- platform Platform
- launchCommand String // Command to run to start. Platform-specific. Windows games on Linux will wrap this command in Proton/Wine
- setupCommand String // Command to setup game (dependencies and such)
- dropletManifest Json // Results from droplet
-
- versionIndex Int
- delta Boolean @default(false)
-
- @@id([gameId, versionName])
-}
-
-model Developer {
- id String @id @default(uuid())
-
- metadataSource MetadataSource
- metadataId String
- metadataOriginalQuery String
-
- mName String
- mShortDescription String
- mDescription String
- mLogo String
- mBanner String
- mWebsite String
-
- games Game[]
-
- @@unique([metadataSource, metadataId, metadataOriginalQuery], name: "metadataKey")
-}
-
-model Publisher {
- id String @id @default(uuid())
-
- metadataSource MetadataSource
- metadataId String
- metadataOriginalQuery String
-
- mName String
- mShortDescription String
- mDescription String
- mLogo String
- mBanner String
- mWebsite String
-
- games Game[]
-
- @@unique([metadataSource, metadataId, metadataOriginalQuery], name: "metadataKey")
-}
diff --git a/src-tauri/src/downloads/download_commands.rs b/src-tauri/src/downloads/download_commands.rs
index 044a067..d5ef686 100644
--- a/src-tauri/src/downloads/download_commands.rs
+++ b/src-tauri/src/downloads/download_commands.rs
@@ -19,21 +19,6 @@ pub fn download_game(
.map_err(|_| "An error occurred while communicating with the download manager.".to_string())
}
-#[tauri::command]
-pub fn get_current_game_download_progress(
- state: tauri::State<'_, Mutex>,
-) -> Result {
- match state
- .lock()
- .unwrap()
- .download_manager
- .get_current_game_download_progress()
- {
- Some(progress) => Ok(progress),
- None => Err("Game does not exist".to_string()),
- }
-}
-
#[tauri::command]
pub fn cancel_game_download(state: tauri::State<'_, Mutex>, game_id: String) {
info!("Cancelling game download {}", game_id);
@@ -54,6 +39,19 @@ pub fn resume_game_downloads(state: tauri::State<'_, Mutex>) {
state.lock().unwrap().download_manager.resume_downloads()
}
+#[tauri::command]
+pub fn move_game_in_queue(
+ state: tauri::State<'_, Mutex>,
+ old_index: usize,
+ new_index: usize,
+) {
+ state
+ .lock()
+ .unwrap()
+ .download_manager
+ .rearrange(old_index, new_index)
+}
+
#[tauri::command]
pub fn get_current_write_speed(state: tauri::State<'_, Mutex>) {}
diff --git a/src-tauri/src/downloads/download_manager.rs b/src-tauri/src/downloads/download_manager.rs
index e70d53d..79c1006 100644
--- a/src-tauri/src/downloads/download_manager.rs
+++ b/src-tauri/src/downloads/download_manager.rs
@@ -132,19 +132,23 @@ impl DownloadManager {
let current_index = get_index_from_id(&mut queue, id).unwrap();
let to_move = queue.remove(current_index).unwrap();
queue.insert(new_index, to_move);
+ self.command_sender.send(DownloadManagerSignal::Update);
}
pub fn rearrange(&self, current_index: usize, new_index: usize) {
let mut queue = self.edit();
let to_move = queue.remove(current_index).unwrap();
queue.insert(new_index, to_move);
+ self.command_sender.send(DownloadManagerSignal::Update);
}
pub fn remove_from_queue(&self, index: usize) {
self.edit().remove(index);
+ self.command_sender.send(DownloadManagerSignal::Update);
}
pub fn remove_from_queue_string(&self, id: String) {
let mut queue = self.edit();
let current_index = get_index_from_id(&mut queue, id).unwrap();
queue.remove(current_index);
+ self.command_sender.send(DownloadManagerSignal::Update);
}
pub fn pause_downloads(&self) {
self.command_sender
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index 0d9a505..8785007 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -134,7 +134,7 @@ pub fn run() {
fetch_game_verion_options,
// Downloads
download_game,
- get_current_game_download_progress,
+ move_game_in_queue,
cancel_game_download,
pause_game_downloads,
resume_game_downloads,
diff --git a/src-tauri/src/library.rs b/src-tauri/src/library.rs
index 9b38c5d..139b04c 100644
--- a/src-tauri/src/library.rs
+++ b/src-tauri/src/library.rs
@@ -17,7 +17,7 @@ use crate::remote::RemoteAccessError;
use crate::{auth::generate_authorization_header, AppState, DB};
#[derive(serde::Serialize)]
-struct FetchGameStruct {
+pub struct FetchGameStruct {
game: Game,
status: DatabaseGameStatus,
}
@@ -67,7 +67,7 @@ pub struct GameVersionOption {
// total_size: usize,
}
-fn fetch_library_logic(app: AppHandle) -> Result {
+fn fetch_library_logic(app: AppHandle) -> Result, RemoteAccessError> {
let base_url = DB.fetch_base_url();
let library_url = base_url.join("/api/v1/client/user/library")?;
@@ -102,15 +102,18 @@ fn fetch_library_logic(app: AppHandle) -> Result {
drop(handle);
- Ok(json!(games.clone()).to_string())
+ Ok(games)
}
#[tauri::command]
-pub fn fetch_library(app: AppHandle) -> Result {
+pub fn fetch_library(app: AppHandle) -> Result, String> {
fetch_library_logic(app).map_err(|e| e.to_string())
}
-fn fetch_game_logic(id: String, app: tauri::AppHandle) -> Result {
+fn fetch_game_logic(
+ id: String,
+ app: tauri::AppHandle,
+) -> Result {
let state = app.state::>();
let mut state_handle = state.lock().unwrap();
@@ -128,7 +131,7 @@ fn fetch_game_logic(id: String, app: tauri::AppHandle) -> Result Result Result {
+pub fn fetch_game(id: String, app: tauri::AppHandle) -> Result {
let result = fetch_game_logic(id, app);
if result.is_err() {
diff --git a/types.ts b/types.ts
index 3a6e3f4..5702594 100644
--- a/types.ts
+++ b/types.ts
@@ -1,4 +1,3 @@
-import type { User } from "@prisma/client";
import type { Component } from "vue";
export type NavigationItem = {
@@ -12,11 +11,31 @@ export type QuickActionNav = {
notifications?: number;
action: () => Promise;
};
+
+export type User = {
+ id: string;
+ username: string;
+ admin: boolean;
+ displayName: string;
+ profilePicture: string;
+};
+
export type AppState = {
status: AppStatus;
user?: User;
};
+export type Game = {
+ id: string;
+ mName: string;
+ mShortDescription: string;
+ mDescription: string;
+ mIconId: string;
+ mBannerId: string;
+ mCoverId: string;
+ mImageLibrary: string[];
+};
+
export enum AppStatus {
NotConfigured = "NotConfigured",
SignedOut = "SignedOut",
diff --git a/yarn.lock b/yarn.lock
index af475d7..a4fa8b8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1075,47 +1075,6 @@
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.28.tgz#d45e01c4a56f143ee69c54dd6b12eade9e270a73"
integrity sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==
-"@prisma/client@5.20.0":
- version "5.20.0"
- resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.20.0.tgz#4fc9f2b2341c9c997c139df4445688dd6b39663b"
- integrity sha512-CLv55ZuMuUawMsxoqxGtLT3bEZoa2W8L3Qnp6rDIFWy+ZBrUcOFKdoeGPSnbBqxc3SkdxJrF+D1veN/WNynZYA==
-
-"@prisma/debug@5.20.0":
- version "5.20.0"
- resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.20.0.tgz#c6d1cf6e3c6e9dba150347f13ca200b1d66cc9fc"
- integrity sha512-oCx79MJ4HSujokA8S1g0xgZUGybD4SyIOydoHMngFYiwEwYDQ5tBQkK5XoEHuwOYDKUOKRn/J0MEymckc4IgsQ==
-
-"@prisma/engines-version@5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284":
- version "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284"
- resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284.tgz#9a53b13cdcfd706ae54198111000f33c63655c39"
- integrity sha512-Lg8AS5lpi0auZe2Mn4gjuCg081UZf88k3cn0RCwHgR+6cyHHpttPZBElJTHf83ZGsRNAmVCZCfUGA57WB4u4JA==
-
-"@prisma/engines@5.20.0":
- version "5.20.0"
- resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.20.0.tgz#86fe407e55219d33d03ebc26dc829a422faed545"
- integrity sha512-DtqkP+hcZvPEbj8t8dK5df2b7d3B8GNauKqaddRRqQBBlgkbdhJkxhoJTrOowlS3vaRt2iMCkU0+CSNn0KhqAQ==
- dependencies:
- "@prisma/debug" "5.20.0"
- "@prisma/engines-version" "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284"
- "@prisma/fetch-engine" "5.20.0"
- "@prisma/get-platform" "5.20.0"
-
-"@prisma/fetch-engine@5.20.0":
- version "5.20.0"
- resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.20.0.tgz#b917880fb08f654981f14ca49923031b39683586"
- integrity sha512-JVcaPXC940wOGpCOwuqQRTz6I9SaBK0c1BAyC1pcz9xBi+dzFgUu3G/p9GV1FhFs9OKpfSpIhQfUJE9y00zhqw==
- dependencies:
- "@prisma/debug" "5.20.0"
- "@prisma/engines-version" "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284"
- "@prisma/get-platform" "5.20.0"
-
-"@prisma/get-platform@5.20.0":
- version "5.20.0"
- resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.20.0.tgz#c1a53a8d8af67f2b4a6b97dd4d25b1c603236804"
- integrity sha512-8/+CehTZZNzJlvuryRgc77hZCWrUDYd/PmlZ7p2yNXtmf2Una4BWnTbak3us6WVdqoz5wmptk6IhsXdG2v5fmA==
- dependencies:
- "@prisma/debug" "5.20.0"
-
"@rollup/plugin-alias@^5.1.0":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-5.1.1.tgz#53601d88cda8b1577aa130b4a6e452283605bf26"
@@ -2816,7 +2775,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
-fsevents@2.3.3, fsevents@~2.3.2, fsevents@~2.3.3:
+fsevents@~2.3.2, fsevents@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
@@ -4345,15 +4304,6 @@ pretty-bytes@^6.1.1:
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-6.1.1.tgz#38cd6bb46f47afbf667c202cfc754bffd2016a3b"
integrity sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==
-prisma@^5.20.0:
- version "5.20.0"
- resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.20.0.tgz#f2ab266a0d59383506886e7acbff0dbf322f4c7e"
- integrity sha512-6obb3ucKgAnsGS9x9gLOe8qa51XxvJ3vLQtmyf52CTey1Qcez3A6W6ROH5HIz5Q5bW+0VpmZb8WBohieMFGpig==
- dependencies:
- "@prisma/engines" "5.20.0"
- optionalDependencies:
- fsevents "2.3.3"
-
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@@ -4847,6 +4797,11 @@ smob@^1.0.0:
resolved "https://registry.yarnpkg.com/smob/-/smob-1.5.0.tgz#85d79a1403abf128d24d3ebc1cdc5e1a9548d3ab"
integrity sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==
+sortablejs@1.14.0:
+ version "1.14.0"
+ resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.14.0.tgz#6d2e17ccbdb25f464734df621d4f35d4ab35b3d8"
+ integrity sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==
+
source-map-js@^1.0.1, source-map-js@^1.2.0, source-map-js@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
@@ -5553,6 +5508,13 @@ vue@^3.5.5, vue@latest:
"@vue/server-renderer" "3.5.11"
"@vue/shared" "3.5.11"
+vuedraggable@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/vuedraggable/-/vuedraggable-4.1.0.tgz#edece68adb8a4d9e06accff9dfc9040e66852270"
+ integrity sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==
+ dependencies:
+ sortablejs "1.14.0"
+
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"