diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b9088a8..0fc3abe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,9 +13,10 @@ build-linux: - yarnpkg tauri build - cp src-tauri/target/release/bundle/deb/*.deb . - cp src-tauri/target/release/bundle/rpm/*.rpm . + - cp src-tauri/target/release/bundle/appimage/*.AppImage . artifacts: paths: - - "*.{deb,rpm}" + - "*.{deb,rpm,AppImage}" build-windows: stage: build diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..4099407 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +23 diff --git a/README.md b/README.md index b0df333..903f4ca 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,19 @@ Drop app is the companion app for [Drop](https://github.com/Drop-OSS/drop). It uses a Tauri base with Nuxt 3 + TailwindCSS on top of it, so we can re-use components from the web UI. +## Running +Before setting up the drop app, be sure that you have a server set up. +The instructions for this can be found on the [Drop Wiki](https://wiki.droposs.org/guides/quickstart.html) + +## Current features +Currently supported are the following features: +- Signin (with custom server) +- Database registering & recovery +- Dynamic library fetching from server +- Installing & uninstalling games +- Download progress monitoring +- Launching / playing games + ## Development Install dependencies with `yarn` @@ -10,7 +23,7 @@ Run the app in development with `yarn tauri dev`. NVIDIA users on Linux, use she To manually specify the logging level, add the environment variable `RUST_LOG=[debug, info, warn, error]` to `yarn tauri dev`: -e.g. `RUST_LOG=debug yarn taudi dev` +e.g. `RUST_LOG=debug yarn tauri dev` ## Contributing Check the original [Drop repo](https://github.com/Drop-OSS/drop/blob/main/CONTRIBUTING.md) for contributing guidelines. \ No newline at end of file diff --git a/app.vue b/app.vue index b921045..b9011c6 100644 --- a/app.vue +++ b/app.vue @@ -1,12 +1,12 @@ diff --git a/components/InitiateAuthModule.vue b/components/InitiateAuthModule.vue index 5f7158c..1f9be6c 100644 --- a/components/InitiateAuthModule.vue +++ b/components/InitiateAuthModule.vue @@ -42,6 +42,31 @@ +
+

Having trouble?

+

+ You can manually enter the token from your web browser. +

+
+ + + Submit + +
+
+
@@ -101,6 +126,10 @@ import { invoke } from "@tauri-apps/api/core"; const loading = ref(false); const error = ref(); +const offerManual = ref(false); +const manualToken = ref(""); +const manualLoading = ref(false); + async function auth() { await invoke("auth_initiate"); } @@ -111,5 +140,23 @@ function authWrapper_wrapper() { loading.value = false; error.value = e; }); + setTimeout(() => { + offerManual.value = true; + }, 10000); +} + +async function continueManual() { + await invoke("manual_recieve_handshake", { token: manualToken.value }); +} + +function continueManual_wrapper() { + loading.value = true; + continueManual() + .catch((e) => { + error.value = e; + }) + .finally(() => { + loading.value = false; + }); } diff --git a/components/PageWidget.vue b/components/PageWidget.vue new file mode 100644 index 0000000..ad9428b --- /dev/null +++ b/components/PageWidget.vue @@ -0,0 +1,7 @@ + diff --git a/composables/downloads.ts b/composables/downloads.ts new file mode 100644 index 0000000..d75c46f --- /dev/null +++ b/composables/downloads.ts @@ -0,0 +1,34 @@ +import { listen } from "@tauri-apps/api/event"; +import type { DownloadableMetadata } from "~/types"; + +export type QueueState = { + queue: Array<{ + meta: DownloadableMetadata; + status: string; + progress: number | null; + current: number; + max: number; + }>; + status: string; +}; + +export type StatsState = { + speed: number; // Bytes per second + time: number; // Seconds, +}; + +export const useQueueState = () => + useState("queue", () => ({ queue: [], status: "Unknown" })); + +export const useStatsState = () => + useState("stats", () => ({ speed: 0, time: 0 })); + +listen("update_queue", (event) => { + const queue = useQueueState(); + queue.value = event.payload as QueueState; +}); + +listen("update_stats", (event) => { + const stats = useStatsState(); + stats.value = event.payload as StatsState; +}); diff --git a/composables/game.ts b/composables/game.ts index 7f28435..0335a7a 100644 --- a/composables/game.ts +++ b/composables/game.ts @@ -12,7 +12,8 @@ export type SerializedGameStatus = [ OptionGameStatus | null ]; -const parseStatus = (status: SerializedGameStatus): GameStatus => { +export const parseStatus = (status: SerializedGameStatus): GameStatus => { + console.log(status); if (status[0]) { return { type: status[0].type, @@ -28,28 +29,29 @@ const parseStatus = (status: SerializedGameStatus): GameStatus => { } }; -export const useGame = async (id: string) => { - if (!gameRegistry[id]) { +export const useGame = async (gameId: string) => { + if (!gameRegistry[gameId]) { const data: { game: Game; status: SerializedGameStatus } = await invoke( "fetch_game", { - id, + gameId, } ); - gameRegistry[id] = data.game; - if (!gameStatusRegistry[id]) { - gameStatusRegistry[id] = ref(parseStatus(data.status)); + gameRegistry[gameId] = data.game; + if (!gameStatusRegistry[gameId]) { + gameStatusRegistry[gameId] = ref(parseStatus(data.status)); - listen(`update_game/${id}`, (event) => { + listen(`update_game/${gameId}`, (event) => { const payload: { status: SerializedGameStatus; } = event.payload as any; - gameStatusRegistry[id].value = parseStatus(payload.status); + console.log(payload.status); + gameStatusRegistry[gameId].value = parseStatus(payload.status); }); } } - const game = gameRegistry[id]; - const status = gameStatusRegistry[id]; + const game = gameRegistry[gameId]; + const status = gameStatusRegistry[gameId]; return { game, status }; -}; +}; \ No newline at end of file diff --git a/composables/generateGameMeta.ts b/composables/generateGameMeta.ts new file mode 100644 index 0000000..fdfc4b7 --- /dev/null +++ b/composables/generateGameMeta.ts @@ -0,0 +1,9 @@ +import { type DownloadableMetadata, DownloadableType } from '~/types' + +export default function generateGameMeta(gameId: string, version: string): DownloadableMetadata { + return { + id: gameId, + version, + downloadType: DownloadableType.Game + } +} \ No newline at end of file diff --git a/composables/queue.ts b/composables/queue.ts deleted file mode 100644 index 0487260..0000000 --- a/composables/queue.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { listen } from "@tauri-apps/api/event"; - -export type QueueState = { - queue: Array<{ id: string; status: string, progress: number | null }>; -}; - -export const useQueueState = () => - useState("queue", () => ({ queue: [] })); - -listen("update_queue", (event) => { - const queue = useQueueState(); - queue.value = event.payload as QueueState; -}); diff --git a/composables/state-navigation.ts b/composables/state-navigation.ts index 790d258..46d9e2b 100644 --- a/composables/state-navigation.ts +++ b/composables/state-navigation.ts @@ -1,4 +1,5 @@ import { listen } from "@tauri-apps/api/event"; +import { data } from "autoprefixer"; import { AppStatus, type AppState } from "~/types"; export function setupHooks() { @@ -18,6 +19,20 @@ export function setupHooks() { router.push("/store"); }); + listen("download_error", (event) => { + createModal( + ModalType.Notification, + { + title: "Drop encountered an error while downloading", + description: `Drop encountered an error while downloading your game: "${( + event.payload as unknown as string + ).toString()}"`, + buttonText: "Close" + }, + (e, c) => c() + ); + }); + /* document.addEventListener("contextmenu", (event) => { @@ -33,9 +48,7 @@ export function initialNavigation(state: Ref) { switch (state.value.status) { case AppStatus.NotConfigured: - router.push({ path: "/setup" }).then(() => { - console.log("Pushed Setup"); - }); + router.push({ path: "/setup" }); break; case AppStatus.SignedOut: router.push("/auth"); diff --git a/layouts/default.vue b/layouts/default.vue index 89dd49b..025a7cf 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -1,7 +1,7 @@