Migrate to Tauri v2

This commit is contained in:
ninjadev64 committed 2024-09-23 16:54:11 +01:00
1 parent a80e8abf3b
commit 5a93c76f9a
41 files changed
+1320 -1004

No files matched your search

+1 -1
View File
@@ -2,8 +2,8 @@
node_modules
/build
/.svelte-kit
/package
/src-tauri/target
/src-tauri/gen
.env
.env.*
!.env.example
Generated
+4 -6
View File
@@ -3,14 +3,12 @@
"packages": {
"specifiers": {
"npm:@sveltejs/adapter-static@^3.0": "npm:@sveltejs/adapter-static@3.0.4_@sveltejs+kit@2.5.26__@sveltejs+vite-plugin-svelte@3.1.2___svelte@4.2.19___vite@5.4.3__svelte@4.2.19__vite@5.4.3_@sveltejs+vite-plugin-svelte@3.1.2__svelte@4.2.19__vite@5.4.3_svelte@4.2.19_vite@5.4.3",
"npm:@sveltejs/kit@2.5.26": "npm:@sveltejs/kit@2.5.26_@sveltejs+vite-plugin-svelte@3.1.2__svelte@4.2.19__vite@5.4.3_svelte@4.2.19_vite@5.4.3",
"npm:@sveltejs/kit@^2.5": "npm:@sveltejs/kit@2.5.26_@sveltejs+vite-plugin-svelte@3.1.2__svelte@4.2.19__vite@5.4.3_svelte@4.2.19_vite@5.4.3",
"npm:@sveltejs/vite-plugin-svelte@^3.1": "npm:@sveltejs/vite-plugin-svelte@3.1.2_svelte@4.2.19_vite@5.4.3",
"npm:@tauri-apps/api@^1.6": "npm:@tauri-apps/api@1.6.0",
"npm:@tauri-apps/api@^2.0.0-rc": "npm:@tauri-apps/api@2.0.0-rc.4",
"npm:autoprefixer@^10.4": "npm:autoprefixer@10.4.20_postcss@8.4.45",
"npm:phosphor-svelte@^2.0": "npm:phosphor-svelte@2.0.1_svelte@4.2.19",
"npm:postcss@^8.4": "npm:postcss@8.4.45",
"npm:svelte-check@3.8.6": "npm:svelte-check@3.8.6_svelte@4.2.19_postcss@8.4.45_typescript@5.5.4",
"npm:svelte-check@^3.8": "npm:svelte-check@3.8.6_svelte@4.2.19_postcss@8.4.45_typescript@5.5.4",
"npm:svelte@^4.2": "npm:svelte@4.2.19",
"npm:tailwindcss@^3.4": "npm:tailwindcss@3.4.10_postcss@8.4.45",
@@ -300,8 +298,8 @@
"vitefu": "vitefu@0.2.5_vite@5.4.3"
}
},
"@tauri-apps/api@1.6.0": {
"integrity": "sha512-rqI++FWClU5I2UBp4HXFvl+sBWkdigBkxnpJDQUWttNyG7IZP4FwQGhTNL5EOw0vI8i6eSAJ5frLqO7n7jbJdg==",
"@tauri-apps/api@2.0.0-rc.4": {
"integrity": "sha512-UNiIhhKG08j4ooss2oEEVexffmWkgkYlC2M3GcX3VPtNsqFgVNL8Mcw/4Y7rO9M9S+ffAMnLOF5ypzyuyb8tyg==",
"dependencies": {}
},
"@types/cookie@0.6.0": {
@@ -1321,7 +1319,7 @@
"npm:@sveltejs/adapter-static@^3.0",
"npm:@sveltejs/kit@^2.5",
"npm:@sveltejs/vite-plugin-svelte@^3.1",
"npm:@tauri-apps/api@^1.6",
"npm:@tauri-apps/api@^2.0.0-rc",
"npm:autoprefixer@^10.4",
"npm:phosphor-svelte@^2.0",
"npm:postcss@^8.4",
+1 -1
View File
@@ -25,7 +25,7 @@
},
"type": "module",
"dependencies": {
"@tauri-apps/api": "^1.6",
"@tauri-apps/api": "^2.0.0-rc",
"phosphor-svelte": "^2.0"
}
}
+1119 -810
View File
File diff suppressed because it is too large. Load diff
+7 -5
View File
@@ -10,12 +10,12 @@ edition = "2021"
rust-version = "1.77"
[build-dependencies]
tauri-build = { version = "1.5", features = [] }
tauri-build = { version = "2.0.0-rc", features = [] }
built = { version = "0.7", features = [ "dependency-tree", "git2" ] }
[dependencies]
# Large, fundamental libraries
tauri = { version = "1.7", features = [ "dialog-confirm", "dialog-message", "shell-execute", "shell-open", "system-tray", "devtools" ] }
tauri = { version = "2.0.0-rc", features = [ "devtools" , "tray-icon"] }
serde = { version = "1.0", features = [ "derive" ] }
serde_json = "1.0"
serialport = "4.5"
@@ -31,9 +31,11 @@ futures-util = "0.3"
anyhow = "1.0"
log = "0.4"
log-panics = "2.1"
tauri-plugin-log = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
tauri-plugin-shell = { version = "2.0.0-rc" }
tauri-plugin-dialog = { version = "2.0.0-rc" }
tauri-plugin-log = { version = "2.0.0-rc" }
tauri-plugin-single-instance = { version = "2.0.0-rc" }
tauri-plugin-autostart = { version = "2.0.0-rc" }
serde-inline-default = "0.2"
serde_with = "3.9"
os_info = "3.8"
+14
View File
@@ -0,0 +1,14 @@
{
"identifier": "main",
"local": true,
"windows": [
"main"
],
"permissions": [
"core:default",
"shell:allow-execute",
"shell:allow-open",
"dialog:allow-message",
"dialog:allow-confirm"
]
}
+2 -3
View File
@@ -66,12 +66,11 @@ pub fn initialise_devices() {
}
async fn register_device(id: String, device: DeviceInfo) {
let app = crate::APP_HANDLE.get().unwrap();
if let Ok(profiles) = get_device_profiles(&device.id, app) {
if let Ok(profiles) = get_device_profiles(&device.id) {
let mut profile_stores = crate::store::profiles::PROFILE_STORES.write().await;
for profile in profiles {
// This is called to initialise the store for each profile when the device is registered.
if let Err(e) = profile_stores.get_profile_store_mut(&device, &profile, app).await {
if let Err(e) = profile_stores.get_profile_store_mut(&device, &profile).await {
error!("{}", e);
}
}
+3 -3
View File
@@ -3,7 +3,7 @@ use super::Error;
use crate::shared::{Action, ActionContext, ActionInstance, Context};
use crate::store::profiles::{acquire_locks_mut, get_instance_mut, get_slot_mut, save_profile, LocksMut};
use tauri::{command, AppHandle, Manager};
use tauri::{command, AppHandle, Emitter, Manager};
#[command]
pub async fn create_instance(app: AppHandle, action: Action, context: Context) -> Result<Option<ActionInstance>, Error> {
@@ -155,7 +155,7 @@ struct UpdateStateEvent {
}
pub async fn update_state(app: &AppHandle, context: ActionContext, locks: &mut LocksMut<'_>) -> Result<(), anyhow::Error> {
let window = app.get_window("main").unwrap();
let window = app.get_webview_window("main").unwrap();
window.emit(
"update_state",
UpdateStateEvent {
@@ -192,7 +192,7 @@ struct KeyMovedEvent {
}
pub async fn key_moved(app: &AppHandle, context: Context, pressed: bool) -> Result<(), anyhow::Error> {
let window = app.get_window("main").unwrap();
let window = app.get_webview_window("main").unwrap();
window.emit("key_moved", KeyMovedEvent { context, pressed })?;
Ok(())
}
+6 -5
View File
@@ -9,7 +9,7 @@ use crate::shared::{Action, CATEGORIES};
use std::collections::HashMap;
use tauri::{command, AppHandle, Manager};
use tauri::{command, Emitter, Manager};
#[derive(Debug, serde_with::SerializeDisplay, serde::Deserialize)]
pub struct Error {
@@ -47,9 +47,10 @@ pub async fn get_devices() -> HashMap<std::string::String, crate::devices::Devic
DEVICES.read().await.clone()
}
pub async fn update_devices() {
pub async fn update_devices() -> Option<()> {
let app = crate::APP_HANDLE.get().unwrap();
let _ = app.get_window("main").unwrap().emit("devices", DEVICES.read().await.clone());
let _ = app.get_webview_window("main")?.emit("devices", DEVICES.read().await.clone());
Some(())
}
#[command]
@@ -67,10 +68,10 @@ pub async fn get_categories() -> HashMap<std::string::String, Vec<Action>> {
}
#[command]
pub async fn get_localisations(app: AppHandle, locale: &str) -> Result<HashMap<String, serde_json::Value>, Error> {
pub async fn get_localisations(locale: &str) -> Result<HashMap<String, serde_json::Value>, Error> {
let mut localisations: HashMap<String, serde_json::Value> = HashMap::new();
let mut entries = match tokio::fs::read_dir(&app.path_resolver().app_config_dir().unwrap().join("plugins")).await {
let mut entries = match tokio::fs::read_dir(&crate::shared::config_dir().join("plugins")).await {
Ok(entries) => entries,
Err(error) => return Err(anyhow::Error::from(error).into()),
};
+7 -5
View File
@@ -1,3 +1,5 @@
use crate::shared::config_dir;
use super::Error;
use tauri::{command, AppHandle};
@@ -12,10 +14,10 @@ pub struct PluginInfo {
}
#[command]
pub async fn list_plugins(app: AppHandle) -> Result<Vec<PluginInfo>, Error> {
pub async fn list_plugins() -> Result<Vec<PluginInfo>, Error> {
let mut plugins = vec![];
let mut entries = match tokio::fs::read_dir(&app.path_resolver().app_config_dir().unwrap().join("plugins")).await {
let mut entries = match tokio::fs::read_dir(&config_dir().join("plugins")).await {
Ok(entries) => entries,
Err(error) => return Err(anyhow::Error::from(error).into()),
};
@@ -57,7 +59,7 @@ pub async fn install_plugin(app: AppHandle, id: String, url: Option<String>) ->
let _ = crate::plugins::deactivate_plugin(&app, &format!("{}.sdPlugin", id)).await;
let config_dir = app.path_resolver().app_config_dir().unwrap();
let config_dir = config_dir();
let _ = tokio::fs::create_dir_all(config_dir.join("temp")).await;
let temp = config_dir.join("temp").join(format!("{id}.sdPlugin"));
@@ -87,7 +89,7 @@ pub async fn remove_plugin(app: AppHandle, id: String) -> Result<(), Error> {
}
crate::plugins::deactivate_plugin(&app, &id).await?;
if let Err(error) = tokio::fs::remove_dir_all(app.path_resolver().app_config_dir().unwrap().join("plugins").join(&id)).await {
if let Err(error) = tokio::fs::remove_dir_all(config_dir().join("plugins").join(&id)).await {
return Err(anyhow::Error::from(error).into());
}
@@ -103,5 +105,5 @@ pub async fn remove_plugin(app: AppHandle, id: String) -> Result<(), Error> {
#[command]
pub async fn reload_plugin(app: AppHandle, id: String) {
let _ = crate::plugins::deactivate_plugin(&app, &id).await;
let _ = crate::plugins::initialise_plugin(&app.path_resolver().app_config_dir().unwrap().join("plugins").join(id)).await;
let _ = crate::plugins::initialise_plugin(&config_dir().join("plugins").join(id)).await;
}
+8 -8
View File
@@ -3,11 +3,11 @@ use super::Error;
use crate::devices::DEVICES;
use crate::store::profiles::{get_device_profiles, DEVICE_STORES, PROFILE_STORES};
use tauri::{command, AppHandle};
use tauri::command;
#[command]
pub fn get_profiles(app: AppHandle, device: &str) -> Result<Vec<String>, Error> {
Ok(get_device_profiles(device, &app)?)
pub fn get_profiles(device: &str) -> Result<Vec<String>, Error> {
Ok(get_device_profiles(device)?)
}
#[command]
@@ -23,7 +23,7 @@ pub async fn get_selected_profile(device: String) -> Result<crate::shared::Profi
#[allow(clippy::flat_map_identity)]
#[command]
pub async fn set_selected_profile(app: AppHandle, device: String, id: String) -> Result<(), Error> {
pub async fn set_selected_profile(device: String, id: String) -> Result<(), Error> {
let mut device_stores = DEVICE_STORES.write().await;
let devices = DEVICES.read().await;
let mut profile_stores = PROFILE_STORES.write().await;
@@ -43,7 +43,7 @@ pub async fn set_selected_profile(app: AppHandle, device: String, id: String) ->
}
// We must use the mutable version of get_profile_store in order to create the store if it does not exist.
let store = profile_stores.get_profile_store_mut(devices.get(&device).unwrap(), &id, &app).await?;
let store = profile_stores.get_profile_store_mut(devices.get(&device).unwrap(), &id).await?;
let new_profile = &store.value;
for instance in new_profile.keys.iter().flatten().chain(&mut new_profile.sliders.iter().flatten()) {
if !matches!(instance.action.uuid.as_str(), "com.amansprojects.opendeck.multiaction" | "com.amansprojects.opendeck.toggleaction") {
@@ -56,13 +56,13 @@ pub async fn set_selected_profile(app: AppHandle, device: String, id: String) ->
}
store.save()?;
device_stores.set_selected_profile(&device, id, &app)?;
device_stores.set_selected_profile(&device, id)?;
Ok(())
}
#[command]
pub async fn delete_profile(app: AppHandle, device: String, profile: String) {
pub async fn delete_profile(device: String, profile: String) {
let mut profile_stores = PROFILE_STORES.write().await;
profile_stores.remove_profile(&device, &profile, &app);
profile_stores.remove_profile(&device, &profile);
}
@@ -2,11 +2,12 @@ use super::Error;
use crate::shared::ActionContext;
use tauri::{command, AppHandle, Manager};
use tauri::{command, AppHandle};
use tauri_plugin_shell::ShellExt;
#[command]
pub async fn make_info(app: AppHandle, plugin: String) -> Result<crate::plugins::info_param::Info, Error> {
let mut path = app.path_resolver().app_config_dir().unwrap();
pub async fn make_info(plugin: String) -> Result<crate::plugins::info_param::Info, Error> {
let mut path = crate::shared::config_dir();
path.push("plugins");
path.push(&plugin);
path.push("manifest.json");
@@ -33,7 +34,7 @@ pub async fn switch_property_inspector(old: Option<ActionContext>, new: Option<A
#[command]
pub async fn open_url(app: AppHandle, url: String) -> Result<(), Error> {
if let Err(error) = tauri::api::shell::open(&app.shell_scope(), url, None) {
if let Err(error) = app.shell().open(url, None) {
return Err(anyhow::Error::from(error).into());
}
Ok(())
+9 -9
View File
@@ -2,13 +2,13 @@ use super::Error;
use crate::built_info;
use tauri::{command, AppHandle};
use tauri::command;
#[cfg(not(debug_assertions))]
use tauri_plugin_autostart::ManagerExt;
#[command]
pub async fn get_settings(app: AppHandle) -> Result<crate::store::Settings, Error> {
let store = crate::store::get_settings(&app);
pub async fn get_settings() -> Result<crate::store::Settings, Error> {
let store = crate::store::get_settings();
match store {
Ok(store) => Ok(store.value),
Err(error) => Err(error.into()),
@@ -16,15 +16,15 @@ pub async fn get_settings(app: AppHandle) -> Result<crate::store::Settings, Erro
}
#[command]
pub async fn set_settings(app: AppHandle, settings: crate::store::Settings) -> Result<(), Error> {
pub async fn set_settings(_app: tauri::AppHandle, settings: crate::store::Settings) -> Result<(), Error> {
#[cfg(not(debug_assertions))]
let _ = match settings.autolaunch {
true => app.autolaunch().enable(),
false => app.autolaunch().disable(),
true => _app.autolaunch().enable(),
false => _app.autolaunch().disable(),
};
crate::devices::elgato::set_brightness(settings.brightness).await;
let mut store = match crate::store::get_settings(&app) {
let mut store = match crate::store::get_settings() {
Ok(store) => store,
Err(error) => return Err(error.into()),
};
@@ -35,14 +35,14 @@ pub async fn set_settings(app: AppHandle, settings: crate::store::Settings) -> R
}
#[command]
pub fn open_config_directory(app: AppHandle) {
pub fn open_config_directory() {
#[cfg(target_os = "windows")]
let command = "explorer";
#[cfg(target_os = "macos")]
let command = "open";
#[cfg(target_os = "linux")]
let command = "xdg-open";
std::process::Command::new(command).arg(app.path_resolver().app_config_dir().unwrap()).spawn().unwrap();
std::process::Command::new(command).arg(crate::shared::config_dir()).spawn().unwrap();
}
#[command]
+6 -7
View File
@@ -1,6 +1,7 @@
use super::{ContextAndPayloadEvent, ContextEvent, PayloadEvent};
use tauri::{api::shell::open, Manager};
use tauri::{Emitter, Manager};
use tauri_plugin_shell::ShellExt;
use serde::Deserialize;
@@ -17,7 +18,7 @@ pub struct LogMessageEvent {
pub async fn open_url(event: PayloadEvent<OpenUrlEvent>) -> Result<(), anyhow::Error> {
let app_handle = crate::APP_HANDLE.get().unwrap();
log::debug!("Opening URL {}", event.payload.url);
open(&app_handle.shell_scope(), event.payload.url, None)?;
app_handle.shell().open(event.payload.url, None)?;
Ok(())
}
@@ -38,15 +39,13 @@ pub async fn send_to_plugin(event: ContextAndPayloadEvent<serde_json::Value>) ->
pub async fn show_alert(event: ContextEvent) -> Result<(), anyhow::Error> {
let app = crate::APP_HANDLE.get().unwrap();
let window = app.get_window("main").unwrap();
window.emit("show_alert", event.context)?;
app.get_webview_window("main").unwrap().emit("show_alert", event.context)?;
Ok(())
}
pub async fn show_ok(event: ContextEvent) -> Result<(), anyhow::Error> {
let app = crate::APP_HANDLE.get().unwrap();
let window = app.get_window("main").unwrap();
window.emit("show_ok", event.context)?;
app.get_webview_window("main").unwrap().emit("show_ok", event.context)?;
Ok(())
}
@@ -58,6 +57,6 @@ pub struct SwitchProfileEvent {
pub async fn switch_profile(event: SwitchProfileEvent) -> Result<(), anyhow::Error> {
let app_handle = crate::APP_HANDLE.get().unwrap();
app_handle.get_window("main").unwrap().emit("switch_profile", event)?;
app_handle.get_webview_window("main").unwrap().emit("switch_profile", event)?;
Ok(())
}
+1 -3
View File
@@ -38,9 +38,7 @@ pub async fn set_global_settings(event: super::ContextAndPayloadEvent<serde_json
};
{
let app = crate::APP_HANDLE.get().unwrap();
let settings_dir = app.path_resolver().app_config_dir().unwrap().join("settings");
let settings_dir = crate::shared::config_dir().join("settings");
tokio::fs::create_dir_all(&settings_dir).await?;
let path = settings_dir.join(uuid + ".json");
+1 -2
View File
@@ -67,8 +67,7 @@ async fn send_to_plugin(plugin: &str, data: &impl Serialize) -> Result<(), anyho
}
async fn send_to_all_plugins(data: &impl Serialize) -> Result<(), anyhow::Error> {
let app = crate::APP_HANDLE.get().unwrap();
let mut entries = tokio::fs::read_dir(app.path_resolver().app_config_dir().unwrap().join("plugins")).await?;
let mut entries = tokio::fs::read_dir(crate::shared::config_dir().join("plugins")).await?;
while let Ok(Some(entry)) = entries.next_entry().await {
let path = match entry.metadata().await?.is_symlink() {
true => tokio::fs::read_link(entry.path()).await?,
+1 -3
View File
@@ -52,9 +52,7 @@ pub async fn did_receive_settings(instance: &crate::shared::ActionInstance, to_p
}
pub async fn did_receive_global_settings(context: &str, to_property_inspector: bool) -> Result<(), anyhow::Error> {
let app = crate::APP_HANDLE.get().unwrap();
let settings_dir = app.path_resolver().app_config_dir().unwrap().join("settings");
let settings_dir = crate::shared::config_dir().join("settings");
let path = settings_dir.join(format!("{}.json", context));
let settings: serde_json::Value = match tokio::fs::read(path).await {
Ok(contents) => serde_json::from_slice(&contents)?,
+37 -33
View File
@@ -15,8 +15,12 @@ mod built_info {
use events::frontend;
use once_cell::sync::OnceCell;
use tauri::{AppHandle, Builder, CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem, WindowEvent};
use tauri_plugin_log::LogTarget;
use tauri::{
menu::{MenuBuilder, MenuItemBuilder, PredefinedMenuItem},
tray::TrayIconBuilder,
AppHandle, Builder, Manager, WindowEvent,
};
use tauri_plugin_log::{Target, TargetKind};
static APP_HANDLE: OnceCell<AppHandle> = OnceCell::new();
@@ -24,14 +28,6 @@ static APP_HANDLE: OnceCell<AppHandle> = OnceCell::new();
async fn main() {
log_panics::init();
let tray = {
let open = CustomMenuItem::new("open".to_string(), "Open");
let hide = CustomMenuItem::new("hide".to_string(), "Hide");
let quit = CustomMenuItem::new("quit".to_string(), "Quit");
let menu = SystemTrayMenu::new().add_item(open).add_item(hide).add_native_item(SystemTrayMenuItem::Separator).add_item(quit);
SystemTray::new().with_menu(menu)
};
let app = match Builder::default()
.invoke_handler(tauri::generate_handler![
frontend::get_devices,
@@ -59,9 +55,32 @@ async fn main() {
frontend::settings::open_config_directory,
frontend::settings::get_build_info
])
.setup(|app| {
let open = MenuItemBuilder::with_id("open", "Open").build(app)?;
let hide = MenuItemBuilder::with_id("hide", "Hide").build(app)?;
let quit = MenuItemBuilder::with_id("quit", "Quit").build(app)?;
let separator = PredefinedMenuItem::separator(app)?;
let menu = MenuBuilder::new(app).items(&[&open, &hide, &separator, &quit]).build()?;
let _tray = TrayIconBuilder::new()
.menu(&menu)
.on_menu_event(move |app, event| {
let window = app.get_webview_window("main").unwrap();
let _ = match event.id().as_ref() {
"open" => window.show(),
"hide" => window.hide(),
"quit" => {
app.exit(0);
Ok(())
}
_ => Ok(()),
};
})
.build(app)?;
Ok(())
})
.plugin(
tauri_plugin_log::Builder::default()
.targets([LogTarget::LogDir, LogTarget::Stdout])
.targets([Target::new(TargetKind::LogDir { file_name: None }), Target::new(TargetKind::Stdout)])
.level(log::LevelFilter::Debug)
.filter(|v| {
!matches!(
@@ -72,25 +91,10 @@ async fn main() {
.build(),
)
.plugin(tauri_plugin_autostart::init(tauri_plugin_autostart::MacosLauncher::LaunchAgent, Some(vec!["--hide"])))
.plugin(tauri_plugin_single_instance::init(|app, _, _| app.get_window("main").unwrap().show().unwrap()))
.system_tray(tray)
.on_system_tray_event(|app, event| {
if let SystemTrayEvent::MenuItemClick { id, .. } = event {
let window = app.get_window("main").unwrap();
let _ = match id.as_str() {
"open" => window.show(),
"hide" => window.hide(),
"quit" => {
app.exit(0);
Ok(())
}
_ => Ok(()),
};
}
})
.on_window_event(|event| {
if let WindowEvent::CloseRequested { api, .. } = event.event() {
event.window().hide().unwrap();
.plugin(tauri_plugin_single_instance::init(|app, _, _| app.get_webview_window("main").unwrap().show().unwrap()))
.on_window_event(|window, event| {
if let WindowEvent::CloseRequested { api, .. } = event {
window.hide().unwrap();
api.prevent_close();
}
})
@@ -101,13 +105,13 @@ async fn main() {
};
if std::env::args().any(|v| v == "--hide") {
let _ = app.get_window("main").unwrap().hide();
let _ = app.get_webview_window("main").unwrap().hide();
}
APP_HANDLE.set(app.handle()).unwrap();
APP_HANDLE.set(app.handle().clone()).unwrap();
devices::initialise_devices();
plugins::initialise_plugins(app.handle());
plugins::initialise_plugins();
app.run(|_, _| {});
}
+1 -1
View File
@@ -84,7 +84,7 @@ pub async fn make_info(uuid: String, version: String, wine: bool) -> Info {
Info {
application: ApplicationInfo {
font: "ui-sans-serif".to_owned(),
language: crate::store::get_settings(crate::APP_HANDLE.get().unwrap()).unwrap().value.language,
language: crate::store::get_settings().unwrap().value.language,
platform: if !wine { platform.to_owned() } else { "windows".to_owned() },
platformVersion: if !wine { os_info::get().version().to_string() } else { "10.0.19045.4474".to_owned() },
version: env!("CARGO_PKG_VERSION").to_owned(),
+8 -8
View File
@@ -2,7 +2,7 @@ pub mod info_param;
pub mod manifest;
mod webserver;
use crate::shared::{convert_icon, Action, CATEGORIES};
use crate::shared::{config_dir, convert_icon, Action, CATEGORIES};
use crate::store::get_settings;
use crate::APP_HANDLE;
@@ -146,11 +146,11 @@ pub async fn initialise_plugin(path: &path::PathBuf) -> anyhow::Result<()> {
if code_path.to_lowercase().ends_with(".html") || code_path.to_lowercase().ends_with(".htm") || code_path.to_lowercase().ends_with(".xhtml") {
// Create a webview window for the plugin and call its registration function.
let url = "http://localhost:57118/".to_owned() + path.join(code_path).to_str().unwrap();
let window = tauri::WindowBuilder::new(APP_HANDLE.get().unwrap(), plugin_uuid.replace('.', "_"), tauri::WindowUrl::External(url.parse()?))
let window = tauri::WebviewWindowBuilder::new(APP_HANDLE.get().unwrap(), plugin_uuid.replace('.', "_"), tauri::WebviewUrl::External(url.parse()?))
.visible(false)
.build()?;
if let Ok(store) = get_settings(APP_HANDLE.get().unwrap()) {
if let Ok(store) = get_settings() {
if store.value.developer {
let _ = window.show();
window.open_devtools();
@@ -278,7 +278,7 @@ pub async fn deactivate_plugin(app: &AppHandle, uuid: &str) -> Result<(), anyhow
if let Some(instance) = instances.remove(uuid) {
match instance {
PluginInstance::Webview => {
let window = app.get_window(&uuid.replace('.', "_")).unwrap();
let window = app.get_webview_window(&uuid.replace('.', "_")).unwrap();
Ok(window.close()?)
}
PluginInstance::Node(mut child) | PluginInstance::Wine(mut child) | PluginInstance::Native(mut child) => Ok(child.kill()?),
@@ -289,13 +289,13 @@ pub async fn deactivate_plugin(app: &AppHandle, uuid: &str) -> Result<(), anyhow
}
/// Initialise plugins from the plugins directory.
pub fn initialise_plugins(app: AppHandle) {
pub fn initialise_plugins() {
tokio::spawn(init_websocket_server());
tokio::spawn(webserver::init_webserver(app.path_resolver().app_config_dir().unwrap()));
tokio::spawn(webserver::init_webserver(config_dir()));
let plugin_dir = app.path_resolver().app_config_dir().unwrap().join("plugins");
let plugin_dir = config_dir().join("plugins");
let _ = fs::create_dir_all(&plugin_dir);
let _ = fs::create_dir_all(app.path_resolver().app_config_dir().unwrap().join("logs").join("plugins"));
let _ = fs::create_dir_all(config_dir().join("logs").join("plugins"));
let entries = match fs::read_dir(&plugin_dir) {
Ok(p) => p,
+7
View File
@@ -5,8 +5,15 @@ use serde::{Deserialize, Serialize};
use serde_inline_default::serde_inline_default;
use once_cell::sync::Lazy;
use tauri::Manager;
use tokio::sync::RwLock;
/// Get the application configuration directory.
pub fn config_dir() -> std::path::PathBuf {
let app_handle = crate::APP_HANDLE.get().unwrap();
app_handle.path().app_config_dir().unwrap()
}
/// Convert an icon specified in a plugin manifest to its full path.
pub fn convert_icon(path: String) -> String {
if Path::new(&(path.clone() + ".svg")).exists() {
+2 -2
View File
@@ -88,6 +88,6 @@ impl Default for Settings {
impl NotProfile for Settings {}
pub fn get_settings(app_handle: &tauri::AppHandle) -> Result<Store<Settings>, anyhow::Error> {
Store::new("settings", &app_handle.path_resolver().app_config_dir().unwrap(), Settings::default())
pub fn get_settings() -> Result<Store<Settings>, anyhow::Error> {
Store::new("settings", &crate::shared::config_dir(), Settings::default())
}
+12 -13
View File
@@ -2,7 +2,7 @@ use super::{
simplified_context::{DiskActionInstance, DiskProfile},
Store,
};
use crate::shared::{Action, ActionInstance, ActionState, Profile};
use crate::shared::{config_dir, Action, ActionInstance, ActionState, Profile};
use std::collections::HashMap;
use std::fs;
@@ -30,7 +30,7 @@ impl ProfileStores {
}
}
pub async fn get_profile_store_mut(&mut self, device: &crate::devices::DeviceInfo, id: &str, app: &tauri::AppHandle) -> Result<&mut Store<Profile>, anyhow::Error> {
pub async fn get_profile_store_mut(&mut self, device: &crate::devices::DeviceInfo, id: &str) -> Result<&mut Store<Profile>, anyhow::Error> {
#[cfg(target_os = "windows")]
let path = PathBuf::from("profiles").join(&device.id).join(id.replace('/', "\\"));
#[cfg(not(target_os = "windows"))]
@@ -46,7 +46,7 @@ impl ProfileStores {
sliders: vec![None; device.sliders as usize],
};
let mut store = Store::new(path, &app.path_resolver().app_config_dir().unwrap(), default).context(format!("Failed to create store for profile {}", path))?;
let mut store = Store::new(path, &config_dir(), default).context(format!("Failed to create store for profile {}", path))?;
let categories = crate::shared::CATEGORIES.read().await;
let actions = categories.values().flatten().collect::<Vec<_>>();
@@ -66,9 +66,9 @@ impl ProfileStores {
}
}
pub fn remove_profile(&mut self, device: &str, id: &str, app: &tauri::AppHandle) {
pub fn remove_profile(&mut self, device: &str, id: &str) {
self.stores.remove(id);
let config_dir = app.path_resolver().app_config_dir().unwrap();
let config_dir = config_dir();
#[cfg(target_os = "windows")]
let id = &id.replace('/', "\\");
let path = config_dir.join("profiles").join(device).join(format!("{id}.json"));
@@ -109,15 +109,14 @@ impl DeviceStores {
};
let path = PathBuf::from("profiles").join(device);
let store = Store::new(path.to_str().unwrap(), &crate::APP_HANDLE.get().unwrap().path_resolver().app_config_dir().unwrap(), default)
.context(format!("Failed to create store for device config {}", device))?;
let store = Store::new(path.to_str().unwrap(), &config_dir(), default).context(format!("Failed to create store for device config {}", device))?;
store.save()?;
self.stores.insert(device.to_owned(), store);
}
let from_store = &self.stores.get(device).unwrap().value.selected_profile;
let all = get_device_profiles(device, crate::APP_HANDLE.get().unwrap())?;
let all = get_device_profiles(device)?;
if all.contains(from_store) {
Ok(from_store.clone())
} else {
@@ -125,7 +124,7 @@ impl DeviceStores {
}
}
pub fn set_selected_profile(&mut self, device: &str, id: String, app: &tauri::AppHandle) -> Result<(), anyhow::Error> {
pub fn set_selected_profile(&mut self, device: &str, id: String) -> Result<(), anyhow::Error> {
if self.stores.contains_key(device) {
let store = self.stores.get_mut(device).unwrap();
store.value.selected_profile = id;
@@ -134,7 +133,7 @@ impl DeviceStores {
let default = DeviceConfig { selected_profile: id };
let path = PathBuf::from("profiles").join(device);
let store = Store::new(path.to_str().unwrap(), &app.path_resolver().app_config_dir().unwrap(), default).context(format!("Failed to create store for device config {}", device))?;
let store = Store::new(path.to_str().unwrap(), &config_dir(), default).context(format!("Failed to create store for device config {}", device))?;
store.save()?;
self.stores.insert(device.to_owned(), store);
@@ -226,10 +225,10 @@ fn migrate_profile(path: PathBuf) -> Result<(), anyhow::Error> {
Ok(())
}
pub fn get_device_profiles(device: &str, app: &tauri::AppHandle) -> Result<Vec<String>, anyhow::Error> {
pub fn get_device_profiles(device: &str) -> Result<Vec<String>, anyhow::Error> {
let mut profiles: Vec<String> = vec![];
let device_path = app.path_resolver().app_config_dir().unwrap().join("profiles").join(device);
let device_path = config_dir().join("profiles").join(device);
fs::create_dir_all(&device_path)?;
let entries = fs::read_dir(device_path)?;
@@ -318,7 +317,7 @@ pub async fn get_slot<'a>(context: &crate::shared::Context, locks: &'a Locks<'_>
pub async fn get_slot_mut<'a>(context: &crate::shared::Context, locks: &'a mut LocksMut<'_>) -> Result<&'a mut Option<crate::shared::ActionInstance>, anyhow::Error> {
let device = locks.devices.get(&context.device).unwrap();
let store = locks.profile_stores.get_profile_store_mut(device, &context.profile, crate::APP_HANDLE.get().unwrap()).await?;
let store = locks.profile_stores.get_profile_store_mut(device, &context.profile).await?;
let configured = match &context.controller[..] {
"Encoder" => &mut store.value.sliders[context.position as usize],
+2 -2
View File
@@ -46,7 +46,7 @@ impl From<ActionContext> for DiskActionContext {
impl DiskActionContext {
fn into_action_context(self, path: &Path) -> ActionContext {
let config_dir = crate::APP_HANDLE.get().unwrap().path_resolver().app_config_dir().unwrap();
let config_dir = crate::shared::config_dir();
let mut iter = path.strip_prefix(config_dir).unwrap().iter();
let device = iter.nth(1).unwrap().to_string_lossy().into_owned();
let mut profile = iter.map(|x| x.to_string_lossy()).collect::<Vec<_>>().join("/");
@@ -114,7 +114,7 @@ impl From<&Profile> for DiskProfile {
impl DiskProfile {
fn into_profile(self, path: &Path) -> Profile {
let config_dir = crate::APP_HANDLE.get().unwrap().path_resolver().app_config_dir().unwrap();
let config_dir = crate::shared::config_dir();
let mut iter = path.strip_prefix(config_dir).unwrap().iter();
let _ = iter.nth(1);
let mut id = iter.map(|x| x.to_string_lossy()).collect::<Vec<_>>().join("/");
+40 -52
View File
@@ -2,43 +2,13 @@
"build": {
"beforeBuildCommand": "deno task build",
"beforeDevCommand": "deno task dev",
"devPath": "http://localhost:5173",
"distDir": "../build"
"frontendDist": "../build",
"devUrl": "http://localhost:5173"
},
"package": {
"productName": "OpenDeck",
"version": "2.0.0"
},
"tauri": {
"windows": [
{
"title": "OpenDeck",
"fullscreen": false,
"resizable": true,
"width": 800,
"height": 600,
"minWidth": 800,
"minHeight": 600,
"center": true,
"fileDropEnabled": false
}
],
"bundle": {
"active": true,
"targets": "all",
"identifier": "com.amansprojects.opendeck",
"publisher": "ninjadev64",
"shortDescription": "A cross-platform desktop application for ProntoKey and Stream Deck.",
"longDescription": "OpenDeck is a cross-platform desktop application that provides functionality for stream controller devices.",
"category": "Productivity",
"icon": [
"icons/icon.png",
"icons/icon.icns",
"icons/icon.ico"
],
"macOS": {
"exceptionDomain": "localhost"
},
"bundle": {
"active": true,
"targets": "all",
"linux": {
"deb": {
"desktopTemplate": "opendeck.desktop",
"files": {
@@ -52,24 +22,42 @@
}
}
},
"security": {
"csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: http://localhost:57118 https://ninjadev64.github.io https://plugins.amansprojects.com; frame-src http://localhost:57118; connect-src https://ninjadev64.github.io https://api.github.com https://plugins.amansprojects.com;"
},
"allowlist": {
"shell": {
"open": true,
"execute": true
},
"dialog": {
"message": true,
"confirm": true
"publisher": "ninjadev64",
"shortDescription": "A cross-platform desktop application for ProntoKey and Stream Deck.",
"longDescription": "OpenDeck is a cross-platform desktop application that provides functionality for stream controller devices.",
"category": "Productivity",
"icon": [
"icons/icon.png",
"icons/icon.icns",
"icons/icon.ico"
],
"macOS": {
"exceptionDomain": "localhost"
}
},
"productName": "OpenDeck",
"mainBinaryName": "opendeck",
"version": "2.0.0",
"identifier": "com.amansprojects.opendeck",
"plugins": {},
"app": {
"windows": [
{
"title": "OpenDeck",
"fullscreen": false,
"resizable": true,
"width": 800,
"height": 600,
"minWidth": 800,
"minHeight": 600,
"center": true
}
},
"updater": {
"active": false
},
"systemTray": {
],
"trayIcon": {
"iconPath": "icons/icon.png"
},
"security": {
"csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: http://localhost:57118 https://ninjadev64.github.io https://plugins.amankhanna.me; frame-src http://localhost:57118; connect-src ipc: http://ipc.localhost https://ninjadev64.github.io https://api.github.com https://plugins.amankhanna.me;"
}
}
}
+1 -3
View File
@@ -1,5 +1,3 @@
{
"package": {
"productName": "opendeck"
}
"productName": "opendeck"
}
+1 -1
View File
@@ -4,7 +4,7 @@
import ListedAction from "./ListedAction.svelte";
import { localisations } from "$lib/settings";
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
let categories: { [name: string]: Action[] } = {};
export async function reload() {
+1 -1
View File
@@ -3,7 +3,7 @@
import type { Profile } from "$lib/Profile";
import type ProfileSelector from "./ProfileSelector.svelte";
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";
export let devices: { [id: string]: DeviceInfo } = {};
+1 -1
View File
@@ -8,7 +8,7 @@
import Slider from "./Slider.svelte";
import { inspectedParentAction } from "$lib/propertyInspector";
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
export let device: DeviceInfo;
export let profile: Profile;
+1 -1
View File
@@ -3,7 +3,7 @@
import { getImage, resizeImage } from "$lib/rendererHelper";
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
export let instance: ActionInstance;
export let showEditor: boolean;
+1 -1
View File
@@ -12,7 +12,7 @@
import { copiedContext, inspectedInstance, inspectedParentAction, openContextMenu } from "$lib/propertyInspector";
import { renderImage } from "$lib/rendererHelper";
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";
export let context: Context;
+1 -1
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
</script>
<div class="flex flex-col justify-center items-center w-full h-full text-center dark:text-neutral-300">
+1 -1
View File
@@ -7,7 +7,7 @@
import Key from "./Key.svelte";
import { inspectedParentAction } from "$lib/propertyInspector";
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
export let profile: Profile;
+1 -1
View File
@@ -11,7 +11,7 @@
import { localisations, settings } from "$lib/settings";
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
export let actionList: () => ActionList;
export let deviceSelector: () => DeviceSelector;
+1 -1
View File
@@ -7,7 +7,7 @@
import Upload from "phosphor-svelte/lib/Upload";
import Popup from "./Popup.svelte";
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
let folders: { [name: string]: string[] } = {};
let value: string;
+1 -1
View File
@@ -4,7 +4,7 @@
import type { Profile } from "$lib/Profile";
import { inspectedInstance } from "$lib/propertyInspector";
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
let iframes: { [context: string]: HTMLIFrameElement } = {};
let iframeContainer: HTMLDivElement;
+1 -1
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { settings } from "$lib/settings";
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
import Popup from "./Popup.svelte";
import Tooltip from "./Tooltip.svelte";
+1 -1
View File
@@ -5,7 +5,7 @@
import { inspectedInstance } from "$lib/propertyInspector";
import { getImage } from "$lib/rendererHelper";
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";
export let context: Context;
+1 -1
View File
@@ -4,7 +4,7 @@ import { writable, type Writable } from "svelte/store";
export const inspectedInstance: Writable<string | null> = writable(null);
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
let old: string | null = null;
inspectedInstance.subscribe(async (value) => {
await invoke("switch_property_inspector", { old, new: value });
+1 -1
View File
@@ -1,4 +1,4 @@
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
import type { ActionState } from "./ActionState";
import type { Context } from "./Context";
+1 -1
View File
@@ -6,7 +6,7 @@ export type Settings = {
developer: boolean
};
import { invoke } from "@tauri-apps/api";
import { invoke } from "@tauri-apps/api/core";
import { writable, type Writable } from "svelte/store";
export const settings: Writable<Settings | null> = writable(null);