this repo has no description

qol updates

phaz.uk 8403d560 1d0a2674

verified
+3
src-tauri/Cargo.lock
··· 7 version = "0.1.0" 8 dependencies = [ 9 "anyhow", 10 "crossbeam-channel", 11 "dirs", 12 "enigo", ··· 519 checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" 520 dependencies = [ 521 "iana-time-zone", 522 "num-traits", 523 "serde", 524 "windows-link 0.2.1", 525 ] 526
··· 7 version = "0.1.0" 8 dependencies = [ 9 "anyhow", 10 + "chrono", 11 "crossbeam-channel", 12 "dirs", 13 "enigo", ··· 520 checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" 521 dependencies = [ 522 "iana-time-zone", 523 + "js-sys", 524 "num-traits", 525 "serde", 526 + "wasm-bindgen", 527 "windows-link 0.2.1", 528 ] 529
+1
src-tauri/Cargo.toml
··· 33 34 # [target.'cfg(windows)'.dependencies] 35 enigo = { version = "0.6.1" } 36
··· 33 34 # [target.'cfg(windows)'.dependencies] 35 enigo = { version = "0.6.1" } 36 + chrono = "0.4.42" 37
+1 -1
src-tauri/src/frontend_calls/load_previous_tabs.rs
··· 8 pub fn load_previous_tabs( 9 window: Window, 10 conf: State<Config>, 11 - ) -> HashMap<String, (Vec<Node>, String, Option<String>)> { 12 let config = conf.store.lock().unwrap(); 13 14 if !config.hide_editor_on_start {
··· 8 pub fn load_previous_tabs( 9 window: Window, 10 conf: State<Config>, 11 + ) -> HashMap<String, (Vec<Node>, String, Option<String>, bool)> { 12 let config = conf.store.lock().unwrap(); 13 14 if !config.hide_editor_on_start {
+6 -1
src-tauri/src/frontend_calls/sync_tab.rs
··· 1 use crossbeam_channel::Sender; 2 3 use tauri::State; ··· 9 graph: Vec<Node>, 10 id: String, 11 name: String, 12 location: Option<String>, 13 cmd: State<Sender<RuntimeCommand>>, 14 conf: State<Config>, ··· 18 .unwrap(); 19 20 let mut config = conf.store.lock().unwrap(); 21 - config.loaded_tabs.insert(id, (graph, name, location)); // TODO: When loading a tab into config, store the save state of it too 22 } 23 24 #[tauri::command]
··· 1 + use chrono::Utc; 2 use crossbeam_channel::Sender; 3 4 use tauri::State; ··· 10 graph: Vec<Node>, 11 id: String, 12 name: String, 13 + save_state: bool, 14 location: Option<String>, 15 cmd: State<Sender<RuntimeCommand>>, 16 conf: State<Config>, ··· 20 .unwrap(); 21 22 let mut config = conf.store.lock().unwrap(); 23 + config.loaded_tabs.insert(id, (graph, name, location, save_state)); // TODO: When loading a tab into config, store the save state of it too 24 + 25 + // If we haven't updated the config in the last second, let's update it again. 26 + if config.last_save + 1 < Utc::now().timestamp(){ conf.save_prelocked(config); } 27 } 28 29 #[tauri::command]
-4
src-tauri/src/runtime.rs
··· 55 if node.is_none() { bail!("Cannot find node"); } 56 57 let node = node.unwrap(); 58 - 59 let inputs = node.inputs(); 60 - dbg!(&inputs); 61 62 let mut needed_input_nodes = HashMap::new(); 63 ··· 72 } 73 } 74 } 75 - 76 - dbg!(&needed_input_nodes); 77 78 for ( id, needed ) in needed_input_nodes{ 79 let (out_args, _) = runtime(id, tab, vec![]).unwrap();
··· 55 if node.is_none() { bail!("Cannot find node"); } 56 57 let node = node.unwrap(); 58 let inputs = node.inputs(); 59 60 let mut needed_input_nodes = HashMap::new(); 61 ··· 70 } 71 } 72 } 73 74 for ( id, needed ) in needed_input_nodes{ 75 let (out_args, _) = runtime(id, tab, vec![]).unwrap();
+4 -3
src-tauri/src/runtime/nodes/shell.rs
··· 1 - use std::process::Command; 2 3 use crate::{ 4 runtime::nodes::RuntimeNode, ··· 40 41 fn execute(&mut self, args: Vec<ParameterType>) -> Vec<ParameterType> { 42 if let Ok(cmd) = args[1].as_string(){ 43 - dbg!(&cmd); 44 - 45 if cmd != ""{ 46 let mut split_cmd = cmd.split(" "); 47 48 let mut cmd = Command::new(split_cmd.nth(0).unwrap()); 49 if split_cmd.clone().count() > 0{ cmd.args(split_cmd); } 50 51 let child = cmd.spawn().unwrap(); 52 let output = child.wait_with_output().unwrap();
··· 1 + use std::{io::Stdin, process::{Command, Stdio}}; 2 3 use crate::{ 4 runtime::nodes::RuntimeNode, ··· 40 41 fn execute(&mut self, args: Vec<ParameterType>) -> Vec<ParameterType> { 42 if let Ok(cmd) = args[1].as_string(){ 43 if cmd != ""{ 44 let mut split_cmd = cmd.split(" "); 45 46 let mut cmd = Command::new(split_cmd.nth(0).unwrap()); 47 if split_cmd.clone().count() > 0{ cmd.args(split_cmd); } 48 + 49 + cmd.stdout(Stdio::piped()); 50 + cmd.stderr(Stdio::piped()); 51 52 let child = cmd.spawn().unwrap(); 53 let output = child.wait_with_output().unwrap();
+10 -3
src-tauri/src/setup.rs
··· 23 window.hide().unwrap(); 24 25 let win_handle = window.clone(); 26 window.on_window_event(move |event| match event { 27 WindowEvent::CloseRequested { api, .. } => { 28 api.prevent_close(); 29 - 30 - win_handle.hide().unwrap(); 31 - win_handle.emit("hide-window", ()).unwrap(); 32 } 33 _ => {} 34 });
··· 23 window.hide().unwrap(); 24 25 let win_handle = window.clone(); 26 + 27 window.on_window_event(move |event| match event { 28 WindowEvent::CloseRequested { api, .. } => { 29 api.prevent_close(); 30 + win_handle.emit("prompt_to_close", ()).unwrap(); 31 + } 32 + WindowEvent::Resized(_) => { 33 + let minimised = win_handle.is_minimized().unwrap(); 34 + if minimised{ 35 + win_handle.hide().unwrap(); 36 + win_handle.emit("hide-window", ()).unwrap(); 37 + win_handle.unminimize().unwrap(); 38 + } 39 } 40 _ => {} 41 });
+23 -6
src-tauri/src/utils/config.rs
··· 3 fs::File, 4 io::{Read, Write}, 5 path::PathBuf, 6 - sync::Mutex, 7 }; 8 9 use flate2::{read::GzDecoder, write::GzEncoder, Compression}; 10 use serde::{Deserialize, Serialize}; 11 ··· 14 #[derive(Clone, Serialize, Deserialize, Debug)] 15 pub struct ConfigValues { 16 #[serde(default)] 17 - pub loaded_tabs: HashMap<String, (Vec<Node>, String, Option<String>)>, 18 19 #[serde(default)] 20 pub hide_editor_on_start: bool, 21 } 22 23 pub struct Config { 24 pub store: Mutex<ConfigValues>, 25 path: PathBuf, 26 } ··· 39 40 let json: ConfigValues = serde_json::from_str(&json_string).unwrap(); 41 42 - dbg!(&json); 43 - 44 Config { 45 store: Mutex::new(json), 46 path: path, ··· 48 } 49 50 pub fn save(&self) { 51 - let dat = serde_json::to_string(&self.store.lock().unwrap().clone()).unwrap(); 52 - dbg!(&dat); 53 54 let file = File::create(&self.path).unwrap(); 55 let mut encoder = GzEncoder::new(file, Compression::default());
··· 3 fs::File, 4 io::{Read, Write}, 5 path::PathBuf, 6 + sync::{Mutex, MutexGuard}, 7 }; 8 9 + use chrono::Utc; 10 use flate2::{read::GzDecoder, write::GzEncoder, Compression}; 11 use serde::{Deserialize, Serialize}; 12 ··· 15 #[derive(Clone, Serialize, Deserialize, Debug)] 16 pub struct ConfigValues { 17 #[serde(default)] 18 + pub loaded_tabs: HashMap<String, (Vec<Node>, String, Option<String>, bool)>, 19 20 #[serde(default)] 21 pub hide_editor_on_start: bool, 22 + 23 + #[serde(default)] 24 + pub last_save: i64, 25 } 26 27 pub struct Config { 28 + 29 pub store: Mutex<ConfigValues>, 30 path: PathBuf, 31 } ··· 44 45 let json: ConfigValues = serde_json::from_str(&json_string).unwrap(); 46 47 Config { 48 store: Mutex::new(json), 49 path: path, ··· 51 } 52 53 pub fn save(&self) { 54 + let mut dat = self.store.lock().unwrap(); 55 + dat.last_save = Utc::now().timestamp(); 56 + 57 + let dat = serde_json::to_string(&*dat).unwrap(); 58 + 59 + let file = File::create(&self.path).unwrap(); 60 + let mut encoder = GzEncoder::new(file, Compression::default()); 61 + 62 + encoder.write_all(dat.as_bytes()).unwrap(); 63 + encoder.finish().unwrap(); 64 + } 65 + 66 + pub fn save_prelocked(&self, mut dat: MutexGuard<'_, ConfigValues>) { 67 + dat.last_save = Utc::now().timestamp(); 68 + 69 + let dat = serde_json::to_string(&*dat).unwrap(); 70 71 let file = File::create(&self.path).unwrap(); 72 let mut encoder = GzEncoder::new(file, Compression::default());
+7 -13
src-tauri/src/utils/setup_traymenu.rs
··· 11 .build(handle) 12 .unwrap(); 13 14 - let hide = MenuItemBuilder::new("Hide / Show Editor") 15 - .id("hide") 16 .build(handle) 17 .unwrap(); 18 19 let tray_menu = MenuBuilder::new(handle) 20 - .items(&[&quit, &hide]) 21 .build() 22 .unwrap(); 23 ··· 30 "quit" => { 31 app.emit("prompt_to_close", ()).unwrap(); 32 } 33 - "hide" => { 34 let window = app.get_webview_window("main").unwrap(); 35 36 - if window.is_visible().unwrap() { 37 - window.hide().unwrap(); 38 - 39 - window.emit("hide-window", ()).unwrap(); 40 - } else { 41 - window.show().unwrap(); 42 - window.set_focus().unwrap(); 43 44 - window.emit("show-window", ()).unwrap(); 45 - } 46 } 47 _ => {} 48 })
··· 11 .build(handle) 12 .unwrap(); 13 14 + let show = MenuItemBuilder::new("Show Editor") 15 + .id("show") 16 .build(handle) 17 .unwrap(); 18 19 let tray_menu = MenuBuilder::new(handle) 20 + .items(&[&quit, &show]) 21 .build() 22 .unwrap(); 23 ··· 30 "quit" => { 31 app.emit("prompt_to_close", ()).unwrap(); 32 } 33 + "show" => { 34 let window = app.get_webview_window("main").unwrap(); 35 36 + window.show().unwrap(); 37 + window.set_focus().unwrap(); 38 39 + window.emit("show-window", ()).unwrap(); 40 } 41 _ => {} 42 })
+14 -2
src/Mangers/NodeManager.tsx
··· 27 setInterval(() => { 28 let tabs = Object.values(this._tabs).filter(x => x.needSync); 29 for(let tab of tabs){ 30 - invoke('sync_tab', { graph: this._generateTabGraph(tab.id)[0], id: tab.id, name: tab.name, location: tab.saveLocation }); 31 tab.needSync = false; 32 } 33 }, 1000); ··· 40 let version = await getVersion(); 41 42 for(let tab of Object.entries<any>(tabs)){ 43 - await this._loadFromConfig(tab[1][2], tab[0], JSON.stringify({ 44 tab_name: tab[1][1], 45 version, 46 graph: tab[1][0] 47 })); 48 }; 49 50 this.UpdateConfig(); ··· 336 337 tab.needSync = false; 338 if(!id)this.UpdateConfig(false); 339 } 340 341 private _generateTabGraph( tabId: string | null ): [ any, Tab | null ]{
··· 27 setInterval(() => { 28 let tabs = Object.values(this._tabs).filter(x => x.needSync); 29 for(let tab of tabs){ 30 + invoke('sync_tab', { 31 + graph: this._generateTabGraph(tab.id)[0], 32 + id: tab.id, 33 + name: tab.name, 34 + location: tab.saveLocation, 35 + saveState: tab.needsSave() 36 + }); 37 + 38 tab.needSync = false; 39 } 40 }, 1000); ··· 47 let version = await getVersion(); 48 49 for(let tab of Object.entries<any>(tabs)){ 50 + let loaded_tab = await this._loadFromConfig(tab[1][2], tab[0], JSON.stringify({ 51 tab_name: tab[1][1], 52 version, 53 graph: tab[1][0] 54 })); 55 + 56 + if(loaded_tab) 57 + loaded_tab.setNeedsSave(tab[1][3]); 58 }; 59 60 this.UpdateConfig(); ··· 346 347 tab.needSync = false; 348 if(!id)this.UpdateConfig(false); 349 + 350 + return tab; 351 } 352 353 private _generateTabGraph( tabId: string | null ): [ any, Tab | null ]{
-1
src/Nodes/Conditional/IfEqual.tsx
··· 9 typeId: 'ifequal', 10 11 w: 220, 12 - h: 150, 13 14 statics: [{ 15 type: NodeType.Label,
··· 9 typeId: 'ifequal', 10 11 w: 220, 12 13 statics: [{ 14 type: NodeType.Label,
-1
src/Nodes/Conditional/IfFalse.tsx
··· 9 typeId: 'iffalse', 10 11 w: 220, 12 - h: 120, 13 14 statics: [{ 15 type: NodeType.Label,
··· 9 typeId: 'iffalse', 10 11 w: 220, 12 13 statics: [{ 14 type: NodeType.Label,
-1
src/Nodes/Conditional/IfTrue.tsx
··· 9 typeId: 'iftrue', 10 11 w: 220, 12 - h: 120, 13 14 statics: [{ 15 type: NodeType.Label,
··· 9 typeId: 'iftrue', 10 11 w: 220, 12 13 statics: [{ 14 type: NodeType.Label,
-1
src/Nodes/Debug.tsx
··· 9 typeId: 'debug', 10 11 w: 200, 12 - h: 110, 13 14 statics: [ 15 {
··· 9 typeId: 'debug', 10 11 w: 200, 12 13 statics: [ 14 {
+1 -2
src/Nodes/Nodes.tsx
··· 17 onStaticsUpdate?: ( node: Node ) => Promise<void>, 18 // build?: ( pos: [ number, number ], onStaticsUpdate: ( node: Node ) => void ) => Promise<Node>, 19 w?: number, 20 - h?: number, 21 statics?: NodeStatic[], 22 inputs?: { name: string, type: NodeType }[], 23 outputs?: { name: string, type: NodeType }[], ··· 29 [details: string] : NodeDefinition; 30 } 31 32 - // TODO: (Node Additions) Pressing keyboard keys 33 // TODO: (Node Additions) Getting media state from os 34 // TODO: (Node Additions) Sending custom OSC messages 35 // TODO: (Node Additions) Sending HTTP requests?
··· 17 onStaticsUpdate?: ( node: Node ) => Promise<void>, 18 // build?: ( pos: [ number, number ], onStaticsUpdate: ( node: Node ) => void ) => Promise<Node>, 19 w?: number, 20 statics?: NodeStatic[], 21 inputs?: { name: string, type: NodeType }[], 22 outputs?: { name: string, type: NodeType }[], ··· 28 [details: string] : NodeDefinition; 29 } 30 31 + // TODO: (Node Additions) Pressing keyboard keys (like to do linux, but has extra steps) 32 // TODO: (Node Additions) Getting media state from os 33 // TODO: (Node Additions) Sending custom OSC messages 34 // TODO: (Node Additions) Sending HTTP requests?
-1
src/Nodes/OSCActions/Send Chatbox.tsx
··· 9 typeId: 'oscsendchatbox', 10 11 w: 200, 12 - h: 120, 13 14 statics: [{ 15 type: NodeType.Label,
··· 9 typeId: 'oscsendchatbox', 10 11 w: 200, 12 13 statics: [{ 14 type: NodeType.Label,
+1 -2
src/Nodes/OSCTrigger.tsx
··· 12 typeId: 'osctrigger', 13 14 w: 200, 15 - h: 50, 16 17 statics: [ 18 { ··· 99 }) 100 101 node.outputs = tempOutputs; 102 - node.h = 60 + (parameters.length + 1) * 30; 103 } 104 105 NodeManager.Instance.UpdateConfig();
··· 12 typeId: 'osctrigger', 13 14 w: 200, 15 16 statics: [ 17 { ··· 98 }) 99 100 node.outputs = tempOutputs; 101 + node.updateSize(); 102 } 103 104 NodeManager.Instance.UpdateConfig();
-1
src/Nodes/PressKey.tsx
··· 9 typeId: 'presskey', 10 11 w: 200, 12 - h: 80, 13 14 statics: [ 15 {
··· 9 typeId: 'presskey', 10 11 w: 200, 12 13 statics: [ 14 {
-1
src/Nodes/Shell.tsx
··· 9 typeId: 'shellcommand', 10 11 w: 200, 12 - h: 120, 13 14 statics: [], 15
··· 9 typeId: 'shellcommand', 10 11 w: 200, 12 13 statics: [], 14
-1
src/Nodes/Statics/Float.tsx
··· 9 typeId: 'staticfloat', 10 11 w: 200, 12 - h: 80, 13 14 statics: [{ 15 type: NodeType.Float,
··· 9 typeId: 'staticfloat', 10 11 w: 200, 12 13 statics: [{ 14 type: NodeType.Float,
-1
src/Nodes/Statics/Int.tsx
··· 9 typeId: 'staticint', 10 11 w: 200, 12 - h: 80, 13 14 statics: [{ 15 type: NodeType.Int,
··· 9 typeId: 'staticint', 10 11 w: 200, 12 13 statics: [{ 14 type: NodeType.Int,
-1
src/Nodes/Statics/String.tsx
··· 9 typeId: 'staticstring', 10 11 w: 200, 12 - h: 80, 13 14 statics: [{ 15 type: NodeType.String,
··· 9 typeId: 'staticstring', 10 11 w: 200, 12 13 statics: [{ 14 type: NodeType.String,
+7 -2
src/structs/node.ts
··· 20 this.typeId = node.typeId!; 21 this.x = pos[0]; 22 this.y = pos[1]; 23 - this.w = node.w!; 24 - this.h = node.h!; 25 26 this.inputs = node.inputs ? node.inputs.map(( x, indx ) => { 27 return { ··· 43 } 44 }) : []; 45 46 this.selected = false; 47 this.statics = node.statics!, 48 this.onStaticsUpdate = node.onStaticsUpdate!; 49 } 50 } 51
··· 20 this.typeId = node.typeId!; 21 this.x = pos[0]; 22 this.y = pos[1]; 23 24 this.inputs = node.inputs ? node.inputs.map(( x, indx ) => { 25 return { ··· 41 } 42 }) : []; 43 44 + this.w = node.w || 200; 45 + this.h = 50 + Math.max(this.outputs.length, this.inputs.length) * 30; 46 + 47 this.selected = false; 48 this.statics = node.statics!, 49 this.onStaticsUpdate = node.onStaticsUpdate!; 50 + } 51 + 52 + updateSize(){ 53 + this.h = 50 + Math.max(this.outputs.length, this.inputs.length) * 30; 54 } 55 } 56