feat: use sets etc.
This commit is contained in:
96
package.json
96
package.json
@ -1,50 +1,50 @@
|
|||||||
{
|
{
|
||||||
"name": "startliner",
|
"name": "startliner",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vue-tsc --noEmit && vite build",
|
"build": "vue-tsc --noEmit && vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"tauri": "tauri"
|
"tauri": "tauri"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "7.4.47",
|
"@mdi/font": "7.4.47",
|
||||||
"@primevue/forms": "^4.2.5",
|
"@primevue/forms": "^4.3.1",
|
||||||
"@primevue/themes": "^4.2.5",
|
"@primevue/themes": "^4.3.1",
|
||||||
"@tailwindcss/vite": "^4.0.6",
|
"@tailwindcss/vite": "^4.0.9",
|
||||||
"@tauri-apps/api": "^2",
|
"@tauri-apps/api": "^2.3.0",
|
||||||
"@tauri-apps/plugin-deep-link": "~2",
|
"@tauri-apps/plugin-deep-link": "~2.2.0",
|
||||||
"@tauri-apps/plugin-dialog": "~2",
|
"@tauri-apps/plugin-dialog": "~2.2.0",
|
||||||
"@tauri-apps/plugin-fs": "~2",
|
"@tauri-apps/plugin-fs": "~2.2.0",
|
||||||
"@tauri-apps/plugin-opener": "^2",
|
"@tauri-apps/plugin-opener": "^2.2.5",
|
||||||
"@tauri-apps/plugin-shell": "~2",
|
"@tauri-apps/plugin-shell": "~2.2.0",
|
||||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||||
"pinia": "^3.0.1",
|
"pinia": "^3.0.1",
|
||||||
"primeicons": "^7.0.0",
|
"primeicons": "^7.0.0",
|
||||||
"primevue": "^4.2.5",
|
"primevue": "^4.3.1",
|
||||||
"roboto-fontface": "*",
|
"roboto-fontface": "^0.10.0",
|
||||||
"tailwindcss": "^4.0.6",
|
"tailwindcss": "^4.0.9",
|
||||||
"tailwindcss-primeui": "^0.4.0",
|
"tailwindcss-primeui": "^0.4.0",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vuetify": "^3.7.6"
|
"vuetify": "^3.7.14"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^2",
|
"@tauri-apps/cli": "^2.3.0",
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
"sass-embedded": "^1.83.1",
|
"sass-embedded": "^1.85.1",
|
||||||
"typescript": "^5.8.0-dev.20250209",
|
"typescript": "^5.8.0-dev.20250218",
|
||||||
"vite": "^6.0.3",
|
"vite": "^6.2.0",
|
||||||
"vue-tsc": "^2.1.10",
|
"vue-tsc": "^2.2.4",
|
||||||
"@tsconfig/node22": "^22.0.0",
|
"@tsconfig/node22": "^22.0.0",
|
||||||
"@types/node": "^22.9.0",
|
"@types/node": "^22.13.5",
|
||||||
"@vue/eslint-config-typescript": "^14.1.3",
|
"@vue/eslint-config-typescript": "^14.4.0",
|
||||||
"@vue/tsconfig": "^0.5.1",
|
"@vue/tsconfig": "^0.5.1",
|
||||||
"npm-run-all2": "^7.0.1",
|
"npm-run-all2": "^7.0.2",
|
||||||
"sass": "1.77.8",
|
"sass": "1.77.8",
|
||||||
"unplugin-fonts": "^1.1.1",
|
"unplugin-fonts": "^1.3.1",
|
||||||
"unplugin-vue-components": "^0.27.2",
|
"unplugin-vue-components": "^0.27.5",
|
||||||
"vite-plugin-vuetify": "^2.0.3"
|
"vite-plugin-vuetify": "^2.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
941
rust/Cargo.lock
generated
941
rust/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -147,16 +147,50 @@ pub async fn init_profile(
|
|||||||
Ok(new_profile)
|
Ok(new_profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[tauri::command]
|
||||||
|
// pub async fn profile_dir(
|
||||||
|
// state: State<'_, Mutex<AppData>>
|
||||||
|
// ) -> Result<PathBuf, &str> {
|
||||||
|
// let appd = state.lock().await;
|
||||||
|
|
||||||
|
// if let Some(p) = &appd.profile {
|
||||||
|
// Ok(p.dir())
|
||||||
|
// } else {
|
||||||
|
// Err("No profile loaded")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// the tauri fs plugin doesn't fucking work
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn profile_dir(
|
pub async fn read_profile_data(
|
||||||
state: State<'_, Mutex<AppData>>
|
state: State<'_, Mutex<AppData>>,
|
||||||
) -> Result<PathBuf, &str> {
|
path: PathBuf
|
||||||
|
) -> Result<String, String> {
|
||||||
let appd = state.lock().await;
|
let appd = state.lock().await;
|
||||||
|
|
||||||
if let Some(p) = &appd.profile {
|
if let Some(p) = &appd.profile {
|
||||||
Ok(p.dir())
|
let res = fs::read_to_string(p.dir().join(&path)).await
|
||||||
|
.map_err(|e| format!("Unable to open {:?}: {}", path, e))?;
|
||||||
|
Ok(res)
|
||||||
} else {
|
} else {
|
||||||
Err("No profile loaded")
|
Err("No profile loaded".to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn write_profile_data(
|
||||||
|
state: State<'_, Mutex<AppData>>,
|
||||||
|
path: PathBuf,
|
||||||
|
content: String
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let appd = state.lock().await;
|
||||||
|
|
||||||
|
if let Some(p) = &appd.profile {
|
||||||
|
fs::write(p.dir().join(&path), content).await
|
||||||
|
.map_err(|e| format!("Unable to write to {:?}: {}", path, e))?;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err("No profile loaded".to_owned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,8 @@ pub async fn run(_args: Vec<String>) {
|
|||||||
cmd::get_current_profile,
|
cmd::get_current_profile,
|
||||||
cmd::init_profile,
|
cmd::init_profile,
|
||||||
cmd::save_profile,
|
cmd::save_profile,
|
||||||
cmd::profile_dir,
|
cmd::read_profile_data,
|
||||||
|
cmd::write_profile_data,
|
||||||
cmd::startline,
|
cmd::startline,
|
||||||
cmd::kill,
|
cmd::kill,
|
||||||
cmd::set_cfg,
|
cmd::set_cfg,
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use tokio::task::JoinSet;
|
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -18,6 +17,14 @@ async fn symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> std::io::Resul
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn line_up(p: &Profile, pkg_hash: String) -> Result<()> {
|
pub async fn line_up(p: &Profile, pkg_hash: String) -> Result<()> {
|
||||||
|
let dir_out = p.dir();
|
||||||
|
|
||||||
|
if dir_out.join("option").exists() {
|
||||||
|
fs::remove_dir_all(dir_out.join("option")).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::create_dir_all(dir_out.join("option")).await?;
|
||||||
|
|
||||||
let hash_path = p.dir().join(".sl-state");
|
let hash_path = p.dir().join(".sl-state");
|
||||||
let prev_hash = fs::read_to_string(&hash_path).await.unwrap_or_default();
|
let prev_hash = fs::read_to_string(&hash_path).await.unwrap_or_default();
|
||||||
if prev_hash != pkg_hash {
|
if prev_hash != pkg_hash {
|
||||||
@ -35,21 +42,14 @@ pub async fn line_up(p: &Profile, pkg_hash: String) -> Result<()> {
|
|||||||
async fn prepare_packages(p: &Profile) -> Result<()> {
|
async fn prepare_packages(p: &Profile) -> Result<()> {
|
||||||
let dir_out = p.dir();
|
let dir_out = p.dir();
|
||||||
|
|
||||||
let mut futures = JoinSet::new();
|
|
||||||
if dir_out.join("BepInEx").exists() {
|
if dir_out.join("BepInEx").exists() {
|
||||||
futures.spawn(fs::remove_dir_all(dir_out.join("BepInEx")));
|
fs::remove_dir_all(dir_out.join("BepInEx")).await?;
|
||||||
}
|
}
|
||||||
if dir_out.join("option").exists() {
|
|
||||||
futures.spawn(fs::remove_dir_all(dir_out.join("option")));
|
|
||||||
}
|
|
||||||
while let Some(_) = futures.join_next().await {}
|
|
||||||
|
|
||||||
fs::create_dir_all(dir_out.join("option")).await?;
|
|
||||||
|
|
||||||
for m in &p.mods {
|
for m in &p.mods {
|
||||||
log::debug!("Preparing {}", m);
|
log::debug!("Preparing {}", m);
|
||||||
let (namespace, name) = m.0.split_at(m.0.find("-").expect("Invalid mod definition"));
|
let (namespace, name) = m.0.split_at(m.0.find("-").expect("Invalid mod definition"));
|
||||||
let bpx_dir = util::pkg_dir_of(namespace, &name[1..])
|
let bpx_dir = util::pkg_dir_of(namespace, &name[1..]) // cut the hyphen
|
||||||
.join("app")
|
.join("app")
|
||||||
.join("BepInEx");
|
.join("BepInEx");
|
||||||
if bpx_dir.exists() {
|
if bpx_dir.exists() {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use std::collections::BTreeSet;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use crate::pkg::PkgKeyVersion;
|
use crate::pkg::PkgKeyVersion;
|
||||||
|
|
||||||
@ -9,5 +10,5 @@ pub struct PackageManifest {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub version_number: String,
|
pub version_number: String,
|
||||||
pub description: String,
|
pub description: String,
|
||||||
pub dependencies: Vec<PkgKeyVersion>
|
pub dependencies: BTreeSet<PkgKeyVersion>
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use std::collections::BTreeSet;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use crate::pkg::PkgKeyVersion;
|
use crate::pkg::PkgKeyVersion;
|
||||||
|
|
||||||
@ -19,6 +20,6 @@ pub struct V1Version {
|
|||||||
pub description: String,
|
pub description: String,
|
||||||
pub version_number: String,
|
pub version_number: String,
|
||||||
pub icon: String,
|
pub icon: String,
|
||||||
pub dependencies: Vec<PkgKeyVersion>,
|
pub dependencies: BTreeSet<PkgKeyVersion>,
|
||||||
pub download_url: String,
|
pub download_url: String,
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
use anyhow::{Result, anyhow, bail};
|
use anyhow::{Result, anyhow, bail};
|
||||||
use derive_more::Display;
|
use derive_more::Display;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::{Path, PathBuf};
|
use std::{collections::BTreeSet, path::{Path, PathBuf}};
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
use crate::{model::{local, rainy}, util};
|
use crate::{model::{local, rainy}, util};
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ use crate::{model::{local, rainy}, util};
|
|||||||
pub struct PkgKey(pub String);
|
pub struct PkgKey(pub String);
|
||||||
|
|
||||||
// {namespace}-{name}-{version}
|
// {namespace}-{name}-{version}
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Eq, Hash, PartialEq, PartialOrd, Ord, Clone, Serialize, Deserialize, Display)]
|
||||||
pub struct PkgKeyVersion(String);
|
pub struct PkgKeyVersion(String);
|
||||||
|
|
||||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||||
@ -36,7 +36,7 @@ pub enum Kind {
|
|||||||
pub struct Local {
|
pub struct Local {
|
||||||
pub version: String,
|
pub version: String,
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
pub dependencies: Vec<PkgKey>,
|
pub dependencies: BTreeSet<PkgKey>,
|
||||||
pub kind: Kind
|
pub kind: Kind
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ pub struct Remote {
|
|||||||
pub package_url: String,
|
pub package_url: String,
|
||||||
pub download_url: String,
|
pub download_url: String,
|
||||||
pub deprecated: bool,
|
pub deprecated: bool,
|
||||||
pub dependencies: Vec<PkgKey>
|
pub dependencies: BTreeSet<PkgKey>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Package {
|
impl Package {
|
||||||
@ -154,16 +154,16 @@ impl Package {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sanitize_deps(mut deps: Vec<PkgKeyVersion>) -> Vec<PkgKey> {
|
fn sanitize_deps(src: BTreeSet<PkgKeyVersion>) -> BTreeSet<PkgKey> {
|
||||||
let regex = regex::Regex::new(r"([A-Za-z0-9_]+)-([A-Za-z0-9_]+)-[0-9\.]+$")
|
let regex = regex::Regex::new(r"([A-Za-z0-9_]+)-([A-Za-z0-9_]+)-[0-9\.]+$")
|
||||||
.expect("Invalid regex");
|
.expect("Invalid regex");
|
||||||
|
let mut res = BTreeSet::<PkgKey>::new();
|
||||||
|
|
||||||
for i in 0..deps.len() {
|
for dep in src {
|
||||||
let caps = regex.captures(&deps[i].0)
|
let caps = regex.captures(&dep.0)
|
||||||
.expect("Invalid dependency");
|
.expect("Invalid dependency");
|
||||||
deps[i] = PkgKeyVersion(format!("{}-{}", caps.get(1).unwrap().as_str(), caps.get(2).unwrap().as_str()));
|
res.insert(PkgKey(format!("{}-{}", caps.get(1).unwrap().as_str(), caps.get(2).unwrap().as_str())));
|
||||||
}
|
}
|
||||||
let rv: Vec<PkgKey> = unsafe { std::mem::transmute(deps) };
|
res
|
||||||
rv
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -73,6 +73,7 @@ impl Profile {
|
|||||||
log::info!("Written to {}", path.to_string_lossy());
|
log::info!("Written to {}", path.to_string_lossy());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn get_cfg(&self, key: &str) -> Result<&serde_json::Value> {
|
pub fn get_cfg(&self, key: &str) -> Result<&serde_json::Value> {
|
||||||
self.cfg.get(key)
|
self.cfg.get(key)
|
||||||
.ok_or_else(|| anyhow::anyhow!("Invalid config entry {}", key))
|
.ok_or_else(|| anyhow::anyhow!("Invalid config entry {}", key))
|
||||||
|
@ -7,7 +7,7 @@ import RadioButton from 'primevue/radiobutton';
|
|||||||
import Toggle from 'primevue/toggleswitch';
|
import Toggle from 'primevue/toggleswitch';
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
import * as path from '@tauri-apps/api/path';
|
import * as path from '@tauri-apps/api/path';
|
||||||
import { mkdir, readTextFile, writeTextFile } from '@tauri-apps/plugin-fs';
|
import { readTextFile, writeTextFile } from '@tauri-apps/plugin-fs';
|
||||||
import { usePkgStore } from '../stores';
|
import { usePkgStore } from '../stores';
|
||||||
|
|
||||||
const store = usePkgStore();
|
const store = usePkgStore();
|
||||||
@ -28,16 +28,13 @@ const cfgDisplayMode = _cfg('display-mode', 'borderless');
|
|||||||
const cfgAime = _cfg('aime', false);
|
const cfgAime = _cfg('aime', false);
|
||||||
|
|
||||||
const aimeCode = ref('');
|
const aimeCode = ref('');
|
||||||
// temp
|
|
||||||
let profilePath = '';
|
|
||||||
let aimePath = '';
|
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
profilePath = await invoke('profile_dir');
|
|
||||||
try {
|
try {
|
||||||
aimePath = await path.join(profilePath, 'aime.txt');
|
aimeCode.value = await invoke('read_profile_data', {
|
||||||
aimeCode.value = await readTextFile(aimePath);
|
path: 'aime.txt',
|
||||||
} catch (_) {
|
});
|
||||||
|
} catch (e) {
|
||||||
aimeCode.value = '';
|
aimeCode.value = '';
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
@ -49,8 +46,10 @@ const aimeCodeModel = computed({
|
|||||||
async set(value: string) {
|
async set(value: string) {
|
||||||
aimeCode.value = value;
|
aimeCode.value = value;
|
||||||
if (value.match(/^[0-9]{20}$/)) {
|
if (value.match(/^[0-9]{20}$/)) {
|
||||||
await mkdir(profilePath);
|
await invoke('write_profile_data', {
|
||||||
await writeTextFile(aimePath, aimeCode.value);
|
path: 'aime.txt',
|
||||||
|
content: aimeCode.value,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user