mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-14 16:51:18 +10:00
Merge branch 'main' into download-manager
This commit is contained in:
37
app.vue
37
app.vue
@ -11,7 +11,10 @@ import { invoke } from "@tauri-apps/api/core";
|
|||||||
import { AppStatus } from "~/types";
|
import { AppStatus } from "~/types";
|
||||||
import { listen } from "@tauri-apps/api/event";
|
import { listen } from "@tauri-apps/api/event";
|
||||||
import { useAppState } from "./composables/app-state.js";
|
import { useAppState } from "./composables/app-state.js";
|
||||||
import { useRouter } from "#vue-router";
|
import {
|
||||||
|
initialNavigation,
|
||||||
|
setupHooks,
|
||||||
|
} from "./composables/state-navigation.js";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@ -22,36 +25,8 @@ router.beforeEach(async () => {
|
|||||||
state.value = await invoke("fetch_state");
|
state.value = await invoke("fetch_state");
|
||||||
});
|
});
|
||||||
|
|
||||||
switch (state.value.status) {
|
setupHooks();
|
||||||
case AppStatus.NotConfigured:
|
initialNavigation(state);
|
||||||
router.push({ path: "/setup" }).then(() => {
|
|
||||||
console.log("Pushed Setup");
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case AppStatus.SignedOut:
|
|
||||||
router.push("/auth");
|
|
||||||
break;
|
|
||||||
case AppStatus.SignedInNeedsReauth:
|
|
||||||
router.push("/auth/signedout");
|
|
||||||
break;
|
|
||||||
case AppStatus.ServerUnavailable:
|
|
||||||
router.push("/error/serverunavailable");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
router.push("/store");
|
|
||||||
}
|
|
||||||
|
|
||||||
listen("auth/processing", () => {
|
|
||||||
router.push("/auth/processing");
|
|
||||||
});
|
|
||||||
|
|
||||||
listen("auth/failed", () => {
|
|
||||||
router.push("/auth/failed");
|
|
||||||
});
|
|
||||||
|
|
||||||
listen("auth/finished", () => {
|
|
||||||
router.push("/store");
|
|
||||||
});
|
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Drop",
|
title: "Drop",
|
||||||
|
|||||||
48
composables/state-navigation.ts
Normal file
48
composables/state-navigation.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { listen } from "@tauri-apps/api/event";
|
||||||
|
import { AppStatus, type AppState } from "~/types";
|
||||||
|
|
||||||
|
export function setupHooks() {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
listen("auth/processing", (event) => {
|
||||||
|
router.push("/auth/processing");
|
||||||
|
});
|
||||||
|
|
||||||
|
listen("auth/failed", (event) => {
|
||||||
|
router.push(
|
||||||
|
`/auth/failed?error=${encodeURIComponent(event.payload as string)}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
listen("auth/finished", (event) => {
|
||||||
|
router.push("/store");
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("contextmenu", (event) => {
|
||||||
|
event.target?.dispatchEvent(new Event("contextmenu"));
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initialNavigation(state: Ref<AppState>) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
switch (state.value.status) {
|
||||||
|
case AppStatus.NotConfigured:
|
||||||
|
router.push({ path: "/setup" }).then(() => {
|
||||||
|
console.log("Pushed Setup");
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case AppStatus.SignedOut:
|
||||||
|
router.push("/auth");
|
||||||
|
break;
|
||||||
|
case AppStatus.SignedInNeedsReauth:
|
||||||
|
router.push("/auth/signedout");
|
||||||
|
break;
|
||||||
|
case AppStatus.ServerUnavailable:
|
||||||
|
router.push("/error/serverunavailable");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
router.push("/store");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,11 +4,12 @@
|
|||||||
<XCircleIcon class="h-12 w-12 text-red-600" aria-hidden="true" />
|
<XCircleIcon class="h-12 w-12 text-red-600" aria-hidden="true" />
|
||||||
<div class="mt-3 text-center sm:mt-5">
|
<div class="mt-3 text-center sm:mt-5">
|
||||||
<h1 class="text-3xl font-semibold font-display leading-6 text-zinc-100">
|
<h1 class="text-3xl font-semibold font-display leading-6 text-zinc-100">
|
||||||
Connection failed
|
Authentication failed
|
||||||
</h1>
|
</h1>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<p class="text-sm text-zinc-400 max-w-sm">
|
<p class="text-sm text-zinc-400 max-w-sm">
|
||||||
Drop encountered an error while connecting to your instance.
|
Drop encountered an error while connecting to your instance. Error:
|
||||||
|
{{ message }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-10 flex items-center justify-center gap-x-6">
|
<div class="mt-10 flex items-center justify-center gap-x-6">
|
||||||
@ -24,6 +25,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { XCircleIcon } from "@heroicons/vue/16/solid";
|
import { XCircleIcon } from "@heroicons/vue/16/solid";
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const message = route.query.error ?? "An unknown error occurred.";
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: "mini",
|
layout: "mini",
|
||||||
});
|
});
|
||||||
|
|||||||
1485
src-tauri/Cargo.lock
generated
1485
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -37,15 +37,18 @@ tauri-plugin-deep-link = "2"
|
|||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
tauri-plugin-dialog = "2"
|
tauri-plugin-dialog = "2"
|
||||||
env_logger = "0.11.5"
|
|
||||||
http = "1.1.0"
|
http = "1.1.0"
|
||||||
urlencoding = "2.1.3"
|
urlencoding = "2.1.3"
|
||||||
md5 = "0.7.0"
|
md5 = "0.7.0"
|
||||||
|
chrono = "0.4.38"
|
||||||
|
|
||||||
[dependencies.tokio]
|
[dependencies.tokio]
|
||||||
version = "1.40.0"
|
version = "1.40.0"
|
||||||
features = ["rt", "tokio-macros", "signal"]
|
features = ["rt", "tokio-macros", "signal"]
|
||||||
|
|
||||||
|
[dependencies.log4rs]
|
||||||
|
version = "1.3.0"
|
||||||
|
features = ["console_appender", "file_appender"]
|
||||||
|
|
||||||
[dependencies.rustix]
|
[dependencies.rustix]
|
||||||
version = "0.38.37"
|
version = "0.38.37"
|
||||||
@ -61,6 +64,7 @@ features = [
|
|||||||
|
|
||||||
[dependencies.openssl]
|
[dependencies.openssl]
|
||||||
version = "0.10.66"
|
version = "0.10.66"
|
||||||
|
features = ["vendored"]
|
||||||
|
|
||||||
[dependencies.rustbreak]
|
[dependencies.rustbreak]
|
||||||
version = "2"
|
version = "2"
|
||||||
|
|||||||
@ -4,6 +4,7 @@ use std::{
|
|||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use chrono::Utc;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use openssl::{ec::EcKey, hash::MessageDigest, pkey::PKey, sign::Signer};
|
use openssl::{ec::EcKey, hash::MessageDigest, pkey::PKey, sign::Signer};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -57,11 +58,7 @@ pub fn generate_authorization_header() -> String {
|
|||||||
db.auth.clone().unwrap()
|
db.auth.clone().unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let start = SystemTime::now();
|
let nonce = Utc::now().timestamp_millis().to_string();
|
||||||
let timestamp = start
|
|
||||||
.duration_since(UNIX_EPOCH)
|
|
||||||
.expect("Time went backwards");
|
|
||||||
let nonce = timestamp.as_millis().to_string();
|
|
||||||
|
|
||||||
let signature = sign_nonce(certs.private, nonce.clone()).unwrap();
|
let signature = sign_nonce(certs.private, nonce.clone()).unwrap();
|
||||||
|
|
||||||
@ -139,8 +136,9 @@ pub fn recieve_handshake(app: AppHandle, path: String) {
|
|||||||
app.emit("auth/processing", ()).unwrap();
|
app.emit("auth/processing", ()).unwrap();
|
||||||
|
|
||||||
let handshake_result = recieve_handshake_logic(&app, path);
|
let handshake_result = recieve_handshake_logic(&app, path);
|
||||||
if handshake_result.is_err() {
|
if let Err(e) = handshake_result {
|
||||||
app.emit("auth/failed", ()).unwrap();
|
warn!("error with authentication: {}", e);
|
||||||
|
app.emit("auth/failed", e.to_string()).unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +198,6 @@ pub fn retry_connect(state: tauri::State<'_, Mutex<AppState>>) -> Result<(), ()>
|
|||||||
pub fn setup() -> Result<(AppStatus, Option<User>), ()> {
|
pub fn setup() -> Result<(AppStatus, Option<User>), ()> {
|
||||||
let data = DB.borrow_data().unwrap();
|
let data = DB.borrow_data().unwrap();
|
||||||
|
|
||||||
// If we have certs, exit for now
|
|
||||||
if data.auth.is_some() {
|
if data.auth.is_some() {
|
||||||
let user_result = fetch_user();
|
let user_result = fetch_user();
|
||||||
if user_result.is_err() {
|
if user_result.is_err() {
|
||||||
|
|||||||
@ -205,15 +205,15 @@ impl GameDownloadAgent {
|
|||||||
let file = File::create(path.clone()).unwrap();
|
let file = File::create(path.clone()).unwrap();
|
||||||
let mut running_offset = 0;
|
let mut running_offset = 0;
|
||||||
|
|
||||||
for (i, length) in chunk.lengths.iter().enumerate() {
|
for (index, length) in chunk.lengths.iter().enumerate() {
|
||||||
contexts.push(DropDownloadContext {
|
contexts.push(DropDownloadContext {
|
||||||
file_name: raw_path.to_string(),
|
file_name: raw_path.to_string(),
|
||||||
version: chunk.version_name.to_string(),
|
version: chunk.version_name.to_string(),
|
||||||
offset: running_offset,
|
offset: running_offset,
|
||||||
index: i,
|
index,
|
||||||
game_id: game_id.to_string(),
|
game_id: game_id.to_string(),
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
checksum: chunk.checksums[i].clone(),
|
checksum: chunk.checksums[index].clone(),
|
||||||
length: *length,
|
length: *length,
|
||||||
});
|
});
|
||||||
running_offset += *length as u64;
|
running_offset += *length as u64;
|
||||||
|
|||||||
@ -8,14 +8,18 @@ pub enum DownloadThreadControlFlag {
|
|||||||
Stop,
|
Stop,
|
||||||
Go,
|
Go,
|
||||||
}
|
}
|
||||||
|
/// Go => true
|
||||||
|
/// Stop => false
|
||||||
impl From<DownloadThreadControlFlag> for bool {
|
impl From<DownloadThreadControlFlag> for bool {
|
||||||
fn from(value: DownloadThreadControlFlag) -> Self {
|
fn from(value: DownloadThreadControlFlag) -> Self {
|
||||||
match value {
|
match value {
|
||||||
DownloadThreadControlFlag::Stop => false,
|
|
||||||
DownloadThreadControlFlag::Go => true,
|
DownloadThreadControlFlag::Go => true,
|
||||||
|
DownloadThreadControlFlag::Stop => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// true => Go
|
||||||
|
/// false => Stop
|
||||||
impl From<bool> for DownloadThreadControlFlag {
|
impl From<bool> for DownloadThreadControlFlag {
|
||||||
fn from(value: bool) -> Self {
|
fn from(value: bool) -> Self {
|
||||||
match value {
|
match value {
|
||||||
|
|||||||
@ -17,10 +17,14 @@ use db::{
|
|||||||
use downloads::download_commands::*;
|
use downloads::download_commands::*;
|
||||||
use downloads::download_manager::DownloadManager;
|
use downloads::download_manager::DownloadManager;
|
||||||
use downloads::download_manager_builder::DownloadManagerBuilder;
|
use downloads::download_manager_builder::DownloadManagerBuilder;
|
||||||
use env_logger::Env;
|
|
||||||
use http::{header::*, response::Builder as ResponseBuilder};
|
use http::{header::*, response::Builder as ResponseBuilder};
|
||||||
use library::{fetch_game, fetch_game_status, fetch_game_verion_options, fetch_library, Game};
|
use library::{fetch_game, fetch_game_status, fetch_game_verion_options, fetch_library, Game};
|
||||||
use log::{debug, info};
|
use log::{debug, info, LevelFilter};
|
||||||
|
use log4rs::append::console::ConsoleAppender;
|
||||||
|
use log4rs::append::file::FileAppender;
|
||||||
|
use log4rs::config::{Appender, Root};
|
||||||
|
use log4rs::encode::pattern::PatternEncoder;
|
||||||
|
use log4rs::Config;
|
||||||
use remote::{gen_drop_url, use_remote};
|
use remote::{gen_drop_url, use_remote};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -71,8 +75,28 @@ fn fetch_state(state: tauri::State<'_, Mutex<AppState>>) -> Result<AppState, Str
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn setup(handle: AppHandle) -> AppState {
|
fn setup(handle: AppHandle) -> AppState {
|
||||||
debug!("Starting env");
|
let logfile = FileAppender::builder()
|
||||||
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
.encoder(Box::new(PatternEncoder::new("{t}|{l}|{f} - {m}{n}")))
|
||||||
|
.build(DATA_ROOT_DIR.lock().unwrap().join("./drop.log"))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let console = ConsoleAppender::builder()
|
||||||
|
.encoder(Box::new(PatternEncoder::new("{t}|{l}|{f} - {m}{n}\n")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let config = Config::builder()
|
||||||
|
.appenders(vec![
|
||||||
|
Appender::builder().build("logfile", Box::new(logfile)),
|
||||||
|
Appender::builder().build("console", Box::new(console)),
|
||||||
|
])
|
||||||
|
.build(
|
||||||
|
Root::builder()
|
||||||
|
.appenders(vec!["logfile", "console"])
|
||||||
|
.build(LevelFilter::Info),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
log4rs::init_config(config).unwrap();
|
||||||
|
|
||||||
let games = HashMap::new();
|
let games = HashMap::new();
|
||||||
let download_manager = Arc::new(DownloadManagerBuilder::build(handle));
|
let download_manager = Arc::new(DownloadManagerBuilder::build(handle));
|
||||||
|
|||||||
Reference in New Issue
Block a user