Add file assosiation for Tauri
This commit is contained in:
@@ -420,6 +420,47 @@ async fn streamed_fetch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
fn handle_file_associations(app: AppHandle, files: Vec<PathBuf>) {
|
||||||
|
// -- Scope handling start --
|
||||||
|
|
||||||
|
// You can remove this block if you only want to know about the paths, but not actually "use" them in the frontend.
|
||||||
|
|
||||||
|
// This requires the `fs` tauri plugin and is required to make the plugin's frontend work:
|
||||||
|
// use tauri_plugin_fs::FsExt;
|
||||||
|
// let fs_scope = app.fs_scope();
|
||||||
|
|
||||||
|
// This is for the `asset:` protocol to work:
|
||||||
|
let asset_protocol_scope = app.asset_protocol_scope();
|
||||||
|
|
||||||
|
for file in &files {
|
||||||
|
// This requires the `fs` plugin:
|
||||||
|
// let _ = fs_scope.allow_file(file);
|
||||||
|
|
||||||
|
// This is for the `asset:` protocol:
|
||||||
|
let _ = asset_protocol_scope.allow_file(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Scope handling end --
|
||||||
|
|
||||||
|
let files = files
|
||||||
|
.into_iter()
|
||||||
|
.map(|f| {
|
||||||
|
let file = f.to_string_lossy().replace("\\", "\\\\"); // escape backslash
|
||||||
|
format!("\"{file}\"",) // wrap in quotes for JS array
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(",");
|
||||||
|
|
||||||
|
tauri::WebviewWindowBuilder::new(&app, "main", Default::default())
|
||||||
|
.initialization_script(&format!("window.tauriOpenedFiles = [{files}]"))
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(tauri_plugin_http::init())
|
.plugin(tauri_plugin_http::init())
|
||||||
@@ -429,6 +470,35 @@ fn main() {
|
|||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
.plugin(tauri_plugin_os::init())
|
.plugin(tauri_plugin_os::init())
|
||||||
.plugin(tauri_plugin_fs::init())
|
.plugin(tauri_plugin_fs::init())
|
||||||
|
.setup(|#[allow(unused_variables)] app| {
|
||||||
|
#[cfg(any(windows, target_os = "linux"))]
|
||||||
|
{
|
||||||
|
let mut files = Vec::new();
|
||||||
|
|
||||||
|
// NOTICE: `args` may include URL protocol (`your-app-protocol://`)
|
||||||
|
// or arguments (`--`) if your app supports them.
|
||||||
|
// files may aslo be passed as `file://path/to/file`
|
||||||
|
for maybe_file in std::env::args().skip(1) {
|
||||||
|
// skip flags like -f or --flag
|
||||||
|
if maybe_file.starts_with("-") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle `file://` path urls and skip other urls
|
||||||
|
if let Ok(url) = url::Url::parse(&maybe_file) {
|
||||||
|
if let Ok(path) = url.to_file_path() {
|
||||||
|
files.push(path);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
files.push(PathBuf::from(maybe_file))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_file_associations(app.handle().clone(), files);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
greet,
|
greet,
|
||||||
native_request,
|
native_request,
|
||||||
@@ -441,8 +511,26 @@ fn main() {
|
|||||||
install_py_dependencies,
|
install_py_dependencies,
|
||||||
streamed_fetch,
|
streamed_fetch,
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.build(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application")
|
||||||
|
.run(
|
||||||
|
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
|app, event| {
|
||||||
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
|
if let tauri::RunEvent::Opened { urls } = event {
|
||||||
|
let files = urls
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|url| url.to_file_path().ok())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
handle_file_associations(app.clone(), files);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header_map_to_json(header_map: &HeaderMap) -> serde_json::Value {
|
fn header_map_to_json(header_map: &HeaderMap) -> serde_json::Value {
|
||||||
|
|||||||
@@ -18,7 +18,14 @@
|
|||||||
"src-python/*"
|
"src-python/*"
|
||||||
],
|
],
|
||||||
"targets": "all",
|
"targets": "all",
|
||||||
"createUpdaterArtifacts": "v1Compatible"
|
"createUpdaterArtifacts": "v1Compatible",
|
||||||
|
"fileAssociations": [
|
||||||
|
{
|
||||||
|
"ext": [
|
||||||
|
"risum", "risup", "charx"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"productName": "RisuAI",
|
"productName": "RisuAI",
|
||||||
"mainBinaryName": "RisuAI",
|
"mainBinaryName": "RisuAI",
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import type { OnnxModelFiles } from "./process/transformers"
|
|||||||
import { CharXReader, CharXWriter } from "./process/processzip"
|
import { CharXReader, CharXWriter } from "./process/processzip"
|
||||||
import { Capacitor } from "@capacitor/core"
|
import { Capacitor } from "@capacitor/core"
|
||||||
import { exportModule, readModule, type RisuModule } from "./process/modules"
|
import { exportModule, readModule, type RisuModule } from "./process/modules"
|
||||||
|
import { readFile } from "@tauri-apps/plugin-fs"
|
||||||
|
|
||||||
export const hubURL = "https://sv.risuai.xyz"
|
export const hubURL = "https://sv.risuai.xyz"
|
||||||
|
|
||||||
@@ -409,6 +410,41 @@ export async function characterURLImport() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if("tauriOpenedFiles" in window){
|
||||||
|
//@ts-ignore
|
||||||
|
const files:string[] = window.tauriOpenedFiles
|
||||||
|
if(files){
|
||||||
|
for(const file of files){
|
||||||
|
const data = await readFile(file)
|
||||||
|
if(file.endsWith('.charx')){
|
||||||
|
await importCharacterProcess({
|
||||||
|
name: file,
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(file.endsWith('.risupreset') || file.endsWith('.risup')){
|
||||||
|
await importPreset({
|
||||||
|
name: file,
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
SettingsMenuIndex.set(1)
|
||||||
|
settingsOpen.set(true)
|
||||||
|
alertNormal(language.successImport)
|
||||||
|
}
|
||||||
|
if(file.endsWith('risum')){
|
||||||
|
const md = await readModule(Buffer.from(data))
|
||||||
|
md.id = v4()
|
||||||
|
const db = get(DataBase)
|
||||||
|
db.modules.push(md)
|
||||||
|
setDatabase(db)
|
||||||
|
alertNormal(language.successImport)
|
||||||
|
SettingsMenuIndex.set(14)
|
||||||
|
settingsOpen.set(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ESNext",
|
"target": "ES2022",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"module": "ESNext",
|
"module": "ES2022",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user