mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-18 02:31:24 +10:00
* chore(process manager): refactor for generic way to implement cross platform launchers * feat(game): game uninstalling & partial compat * chore(metadata): update metadata * feat(errors): better download manager errors + modal * feat(process): better process management, including running state * feat(downloads): lockless tracking of downloaded chunks * fix(sign on): add message about nonce expiration * feat(download ui): add speed and time remaining information closes #7 Co-authored-by: AdenMGB <140392385+AdenMGB@users.noreply.github.com> * chore: Ran cargo clippy Signed-off-by: quexeky <git@quexeky.dev> * fix(auth initiate): add better error message * feat(auth): offer manual signin * feat(install modal): add note about more install dirs * fix(install flow): clear stale data before requesting new * Delete pages/library.vue * Add files via upload * adds nvm rc! * feat(install modal): add note about more install dirs * fix(install flow): clear stale data before requesting new * Delete pages/library.vue * Add files via upload * fix(library page): fix install button * fix(process): fix poorly designed parsing for executables with spaces * fix(scrollbars): fix ugly scrollbars on edge webview * feat(Compat): Implemented spawning with umu (using umu-wrapper-lib) Signed-off-by: quexeky <git@quexeky.dev> * feat(process manager): Game kill tauri command Signed-off-by: quexeky <git@quexeky.dev> * fix(deep links): Re-enabled deep links Signed-off-by: quexeky <git@quexeky.dev> * feat(process): shared child with stop command * squash(autostart): added adenmgb's autostart feature Squashed commit of the following: commit085cd9481dAuthor: Aden Lindsay <140392385+AdenMGB@users.noreply.github.com> Date: Mon Dec 30 16:29:41 2024 +1030 Update lib.rs for the DB sync of autostart commit86f2fb19bdAuthor: Aden Lindsay <140392385+AdenMGB@users.noreply.github.com> Date: Mon Dec 30 16:29:13 2024 +1030 Update db.rs to accomidate the settings sync commitece11e7581Author: Aden Lindsay <140392385+AdenMGB@users.noreply.github.com> Date: Mon Dec 30 16:27:48 2024 +1030 Update autostart.rs to include DB commit7ea8a24fdcAuthor: Aden Lindsay <140392385+AdenMGB@users.noreply.github.com> Date: Mon Dec 30 15:17:38 2024 +1030 Add files via upload commitaf2f232d94Author: Aden Lindsay <140392385+AdenMGB@users.noreply.github.com> Date: Mon Dec 30 15:17:09 2024 +1030 Delete src-tauri/Cargo.toml commit5d27b65612Author: Aden Lindsay <140392385+AdenMGB@users.noreply.github.com> Date: Mon Dec 30 15:15:42 2024 +1030 Add files via upload commit2eea7b97a8Author: Aden Lindsay <140392385+AdenMGB@users.noreply.github.com> Date: Mon Dec 30 15:15:31 2024 +1030 Delete src-tauri/src/lib.rs commit9a635a10d1Author: Aden Lindsay <140392385+AdenMGB@users.noreply.github.com> Date: Mon Dec 30 15:14:49 2024 +1030 Add files via upload commit2fb049531aAuthor: Aden Lindsay <140392385+AdenMGB@users.noreply.github.com> Date: Mon Dec 30 15:13:37 2024 +1030 Add files via upload commitea1be4d750Author: Aden Lindsay <140392385+AdenMGB@users.noreply.github.com> Date: Mon Dec 30 15:13:20 2024 +1030 Delete pages/settings/index.vue * fix(download manager): fix incorrect error assumptions & update types * feat(account settings): Add signout functionality (#16) * Create account.vue with logout button * Update auth.rs to add signout command * Update lib.rs to pass sign_out command to frontend * feat(settings): add debug page * Create debug.rs * Update settings.vue to add tab for debug * Update main.scss to add light theme * Update interface.vue to add light mode * Create debug.vue * Update debug.vue too add open log button * Update lib.rs * Update debug.rs * Update debug.rs * Update lib.rs * Update lib.rs * Update debug.rs * Update debug.vue * fix(debug): refactor and cleanup * revert(theme): revert light theming --------- Co-authored-by: DecDuck <declanahofmeyr@gmail.com> * feat(library ui): add installed ui in the library menu * chore(tool manager): Progress on adding tools Going to try changing around the download manager to take a generic trait rather than specifically for game downloads Signed-off-by: quexeky <git@quexeky.dev> * refactor(download manager): Moved download manager to separate directory Signed-off-by: quexeky <git@quexeky.dev> * refactor(download manager): Added Downloadable trait and replaced references to GameDownloadAgent Signed-off-by: quexeky <git@quexeky.dev> * chore(download manager): Renamed most instances of "game" outside of actual game downloads Signed-off-by: quexeky <git@quexeky.dev> * refactor(download manager): Renamed GameDonwloadError to ApplicationDownloadError and moved Signed-off-by: quexeky <git@quexeky.dev> * chore(download manager): Some easy cleanup of the download manager Signed-off-by: quexeky <git@quexeky.dev> * chore(download manager): Ensure that Downloadable is also send and sync Signed-off-by: quexeky <git@quexeky.dev> * refactor(download manager): Moved manifest and stored_manifest to download_manager Signed-off-by: quexeky <git@quexeky.dev> * Revert "refactor(download manager): Moved manifest and stored_manifest to download_manager" This reverts commit8db2393346. * chore(tool manager): Added ToolDownloadAgent Signed-off-by: quexeky <git@quexeky.dev> * chore(download manager): Added manage_queue_signal Signed-off-by: quexeky <git@quexeky.dev> * chore(download manager): Added manage_go_signal command Signed-off-by: quexeky <git@quexeky.dev> * refactor(download manager): Removed all references to anything outside of the DownloadManager Signed-off-by: quexeky <git@quexeky.dev> * refactor(download manager): Fully separate & generic download manager Signed-off-by: quexeky <git@quexeky.dev> * refactor(download manager): Removed Arc requirement for DownloadableMetadata Signed-off-by: quexeky <git@quexeky.dev> * feat(download manager): Added generic download manager Signed-off-by: quexeky <git@quexeky.dev> * fix(game launcher): Renamed game_id to id Signed-off-by: quexeky <git@quexeky.dev> * fix(uninstalling): Re-enabled uninstalling apps Signed-off-by: quexeky <git@quexeky.dev> * refactor(downloads): Moved all files relevant to game downloads to their own directory Signed-off-by: quexeky <git@quexeky.dev> * fix(kill game): Re-enabled killing games Signed-off-by: quexeky <git@quexeky.dev> * feat(recovery): Added database recovery Signed-off-by: quexeky <git@quexeky.dev> * feat(database): Added database corruption dialog Signed-off-by: quexeky <git@quexeky.dev> * chore(README): Updated README.md Signed-off-by: quexeky <git@quexeky.dev> * perf(game downloads): Moved some variable declarations outside of the spawned download thread Signed-off-by: quexeky <git@quexeky.dev> * fix(game downloads): Accidentally was attempting to lock onto something that was already in scope Signed-off-by: quexeky <git@quexeky.dev> * fix(db): Added Settings component Signed-off-by: quexeky <git@quexeky.dev> * refactor: Ran cargo clippy & fmt Signed-off-by: quexeky <git@quexeky.dev> * chore: More cleanup after cargo clippy Also added some type efficiency improvements (using references where possible and added SliceDeque crate) Signed-off-by: quexeky <git@quexeky.dev> * feat(settings): Added max_download_threads setting and separated settings from db Signed-off-by: quexeky <git@quexeky.dev> * chore: Moved generateGameMeta.ts to composables, using PathBuf instead of String for install_dirs Signed-off-by: quexeky <git@quexeky.dev> * chore: General cleanup - Changed some info!() statements to debug!() and warn!() - Removed most Turbofish syntax cases - Removed InvalidCodeError and replaced it with InvalidResponse Signed-off-by: quexeky <git@quexeky.dev> * chore: Removed tests/ Signed-off-by: quexeky <git@quexeky.dev> * chore: Removed tools/ Signed-off-by: quexeky <git@quexeky.dev> * chore: More refining info!() statements Signed-off-by: quexeky <git@quexeky.dev> * feat(download manager): Added UI to change download threads Co-authored-by: AdenMGB <140392385+AdenMGB@users.noreply.github.com> Signed-off-by: quexeky <git@quexeky.dev> * fix(metadata): update routes for new server * fix(handle invalid database): use set_file_name instead of pushing to strings * refactor(compat): remove unnecessary compat code (#20) * Delete pages/settings/compatibility.vue * Update settings.vue * Update debug.vue * Update lib.rs * Update compat.rs * feat(debug): use shift or DEBUG RUST_LOG to show Debug Info * Update settings.vue to have a conditional debug page * Update debug.rs to add RUST_LOG status fetching * Implement better error system and segregate errors and commands (#23) * chore: Progress on amend_settings command Signed-off-by: quexeky <git@quexeky.dev> * chore(errors): Progress on better error handling with segragation of files * chore: Progress on amend_settings command Signed-off-by: quexeky <git@quexeky.dev> * chore(commands): Separated commands under each subdirectory into respective commands.rs files Signed-off-by: quexeky <git@quexeky.dev> * chore(errors): Almost all errors and commands have been segregated * chore(errors): Added drop server error Signed-off-by: quexeky <git@quexeky.dev> * feat(core): Update to using nightly compiler Signed-off-by: quexeky <git@quexeky.dev> * chore(errors): More progress on error handling Signed-off-by: quexeky <git@quexeky.dev> * chore(errors): Implementing Try and FromResidual for UserValue Signed-off-by: quexeky <git@quexeky.dev> * refactor(errors): Segregated errors and commands from code, and made commands return UserValue struct Signed-off-by: quexeky <git@quexeky.dev> * fix(errors): Added missing files * chore(errors): Convert match statement to map_err * feat(settings): Implemented settings editing from UI * feat(errors): Clarified return values from retry_connect command * chore(errors): Moved autostart commands to autostart.rs * chore(process manager): Converted launch_process function for games to use game_id --------- Signed-off-by: quexeky <git@quexeky.dev> * fix(settings): Broken command invoke logic in settings/downloads.vue * feat(logging): Added line numbers to file logging and highlighting to console * chore(progress): Added rolling_progress_updates.rs Signed-off-by: quexeky <git@quexeky.dev> * chore(exit): Progress on cleanup and exit * chore(downloads): Progress on terminator * chore: Progress on rolling progress window * feat(progress): Added rolling progress window Still needs tweaks on specific timings, as well as cleanup * refactor(remote): Created separate function to generate requests * fix(install ui): stop loading on error * fix: fix other metadata endpoints * feat(errors): Using SerializeDisplay for better error management with Result * chore: Update .gitlab-ci.yml * refactor(logging): Using more appropriate logging statements Still probably needs some work, but that's enough for now * chore(logging): Imported appropriate logging macros * Revert "chore: Update .gitlab-ci.yml" This reverts commitfc6bab9381. * feat(settings): Allow settings to update UI using fetch_settings command * style(logging): Ensured that all logs start with lowercase capital and have no trailing punctuation * fix(download manager): don't crash download manager if multiple errors come in * feat(downloads): re-enable checksums * fix(logs): add file & line to console logs * fix(ui): modal stack doesn't cover whole app * feat(database): Ensure that any database issues are resolved by standalone functions Functions are as follows: - save_db() - borrow_db_checked() - borrow_db_mut_checked() * chore: Ran cargo clippy & cargo fmt * fix: assorted fixes * fix(download agent): fixed completed indexes * fix: Adding usize to completed_contexts_lock instead of &usize * fix(game downloads): Added error handling for chunk request errors * chore: Apply stashed changes * feat(games): Added multi-argument game launch and setup support * fix: Games not launching due to string semantics * build: Version bump & appimage build * chore: Update .gitlab-ci.yml * Update .gitlab-ci.yml * Update .gitlab-ci.yml with artifacts * feat(settings): Made save button include user feedback & only allow numeric characters * fix(library): Added "LIbrary Failed to Update" content to recover from library load fail * fix(logging): Restored RUST_LOG env functionality * Update changelog.md --------- Signed-off-by: quexeky <git@quexeky.dev> Signed-off-by: DecDuck <declanahofmeyr@gmail.com> Co-authored-by: DecDuck <declanahofmeyr@gmail.com> Co-authored-by: AdenMGB <140392385+AdenMGB@users.noreply.github.com> Co-authored-by: seethruhead <shane.keulen@gmail.com>
208 lines
6.4 KiB
Vue
208 lines
6.4 KiB
Vue
<template>
|
|
<div class="bg-zinc-950 p-4 min-h-full space-y-4">
|
|
<div
|
|
class="h-16 overflow-hidden relative rounded-xl flex flex-row border border-zinc-900"
|
|
>
|
|
<div
|
|
class="bg-zinc-900 z-10 w-32 flex flex-col gap-x-2 text-blue-400 font-display items-left justify-center pl-2"
|
|
>
|
|
<span class="font-semibold">{{ formatKilobytes(stats.speed) }}/s</span>
|
|
<span v-if="stats.time > 0" class="text-sm"
|
|
>{{ formatTime(stats.time) }} left</span
|
|
>
|
|
</div>
|
|
<div class="absolute inset-0 h-full flex flex-row items-end justify-end">
|
|
<div
|
|
v-for="bar in speedHistory"
|
|
:style="{ height: `${(bar / speedMax) * 100}%` }"
|
|
class="w-[8px] bg-blue-600/40"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<draggable v-model="queue.queue" @end="onEnd">
|
|
<template #item="{ element }: { element: (typeof queue.value.queue)[0] }">
|
|
<li
|
|
v-if="games[element.meta.id]"
|
|
:key="element.meta.id"
|
|
class="mb-4 bg-zinc-900 rounded-lg flex flex-row justify-between gap-x-6 py-5 px-4"
|
|
>
|
|
<div class="w-full flex items-center max-w-md gap-x-4 relative">
|
|
<img
|
|
class="size-24 flex-none bg-zinc-800 object-cover rounded"
|
|
:src="games[element.meta.id].cover"
|
|
alt=""
|
|
/>
|
|
<div class="min-w-0 flex-auto">
|
|
<p class="text-xl font-semibold text-zinc-100">
|
|
<NuxtLink :href="`/library/${element.meta.id}`" class="">
|
|
<span class="absolute inset-x-0 -top-px bottom-0" />
|
|
{{ games[element.meta.id].game.mName }}
|
|
</NuxtLink>
|
|
</p>
|
|
<p class="mt-1 flex text-xs/5 text-gray-500">
|
|
{{ games[element.meta.id].game.mShortDescription }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex shrink-0 items-center gap-x-4">
|
|
<div class="hidden sm:flex sm:flex-col sm:items-end">
|
|
<p class="text-md text-zinc-500 uppercase font-display font-bold">
|
|
{{ element.status }}
|
|
</p>
|
|
<div
|
|
v-if="element.progress"
|
|
class="mt-1 w-96 bg-zinc-800 rounded-lg overflow-hidden"
|
|
>
|
|
<div
|
|
class="h-2 bg-blue-600"
|
|
:style="{ width: `${element.progress * 100}%` }"
|
|
/>
|
|
</div>
|
|
<span
|
|
class="mt-2 inline-flex items-center gap-x-1 text-zinc-400 text-sm font-display"
|
|
><span class="text-zinc-300">{{
|
|
formatKilobytes(element.current / 1000)
|
|
}}</span>
|
|
/
|
|
<span class="">{{ formatKilobytes(element.max / 1000) }}</span
|
|
><ServerIcon class="size-5"
|
|
/></span>
|
|
</div>
|
|
<button @click="() => cancelGame(element.meta)" class="group">
|
|
<XMarkIcon
|
|
class="transition size-8 flex-none text-zinc-600 group-hover:text-zinc-300"
|
|
aria-hidden="true"
|
|
/>
|
|
</button>
|
|
</div>
|
|
</li>
|
|
<p v-else>Loading...</p>
|
|
</template>
|
|
</draggable>
|
|
<div
|
|
class="text-zinc-600 uppercase font-semibold font-display w-full text-center"
|
|
v-if="queue.queue.length == 0"
|
|
>
|
|
No items in the queue
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ServerIcon, XMarkIcon } from "@heroicons/vue/20/solid";
|
|
import { invoke } from "@tauri-apps/api/core";
|
|
import type { DownloadableMetadata, Game, GameStatus } from "~/types";
|
|
|
|
const windowWidth = ref(window.innerWidth);
|
|
window.addEventListener("resize", (event) => {
|
|
windowWidth.value = window.innerWidth;
|
|
});
|
|
|
|
const queue = useQueueState();
|
|
const stats = useStatsState();
|
|
const speedHistory = useState<Array<number>>(() => []);
|
|
const speedHistoryMax = computed(() => windowWidth.value / 8);
|
|
const speedMax = computed(
|
|
() => speedHistory.value.reduce((a, b) => (a > b ? a : b)) * 1.3
|
|
);
|
|
const previousGameId = ref<string | undefined>();
|
|
|
|
const games: Ref<{
|
|
[key: string]: { game: Game; status: Ref<GameStatus>; cover: string };
|
|
}> = ref({});
|
|
|
|
function resetHistoryGraph() {
|
|
speedHistory.value = [];
|
|
stats.value = { time: 0, speed: 0 };
|
|
}
|
|
function checkReset(v: QueueState) {
|
|
const currentGame = v.queue.at(0)?.meta.id;
|
|
// If we're finished
|
|
if (!currentGame && previousGameId.value) {
|
|
previousGameId.value = undefined;
|
|
resetHistoryGraph();
|
|
return;
|
|
}
|
|
// If we don't have a game
|
|
if (!currentGame) return;
|
|
// If we started a new download
|
|
if (currentGame && !previousGameId.value) {
|
|
previousGameId.value = currentGame;
|
|
resetHistoryGraph();
|
|
return;
|
|
}
|
|
// If it's a different game now
|
|
if (currentGame != previousGameId.value) {
|
|
previousGameId.value = currentGame;
|
|
resetHistoryGraph();
|
|
return;
|
|
}
|
|
}
|
|
watch(queue, (v) => {
|
|
loadGamesForQueue(v);
|
|
checkReset(v);
|
|
});
|
|
|
|
watch(stats, (v) => {
|
|
const newLength = speedHistory.value.push(v.speed);
|
|
if (newLength > speedHistoryMax.value) {
|
|
speedHistory.value.splice(0, 1);
|
|
}
|
|
checkReset(queue.value);
|
|
});
|
|
|
|
function loadGamesForQueue(v: typeof queue.value) {
|
|
for (const {
|
|
meta: { id },
|
|
} of v.queue) {
|
|
if (games.value[id]) return;
|
|
(async () => {
|
|
const gameData = await useGame(id);
|
|
const cover = await useObject(gameData.game.mCoverId);
|
|
games.value[id] = { ...gameData, cover };
|
|
})();
|
|
}
|
|
}
|
|
|
|
loadGamesForQueue(queue.value);
|
|
|
|
async function onEnd(event: { oldIndex: number; newIndex: number }) {
|
|
await invoke("move_game_in_queue", {
|
|
oldIndex: event.oldIndex,
|
|
newIndex: event.newIndex,
|
|
});
|
|
}
|
|
|
|
async function cancelGame(meta: DownloadableMetadata) {
|
|
await invoke("cancel_game", { meta });
|
|
}
|
|
|
|
function formatKilobytes(bytes: number): string {
|
|
const units = ["KB", "MB", "GB", "TB", "PB"];
|
|
let value = bytes;
|
|
let unitIndex = 0;
|
|
const scalar = 1000;
|
|
|
|
while (value >= scalar && unitIndex < units.length - 1) {
|
|
value /= scalar;
|
|
unitIndex++;
|
|
}
|
|
|
|
return `${value.toFixed(1)} ${units[unitIndex]}`;
|
|
}
|
|
|
|
function formatTime(seconds: number): string {
|
|
if (seconds < 60) {
|
|
return `${Math.round(seconds)}s`;
|
|
}
|
|
|
|
const minutes = Math.floor(seconds / 60);
|
|
if (minutes < 60) {
|
|
return `${minutes}m ${Math.round(seconds % 60)}s`;
|
|
}
|
|
|
|
const hours = Math.floor(minutes / 60);
|
|
return `${hours}h ${minutes % 60}m`;
|
|
}
|
|
</script>
|