Release 0.7.13-alpha
This commit is contained in:
commit
73fd191a28
|
|
@ -1,3 +1,12 @@
|
||||||
|
# 0.7.12-alpha:
|
||||||
|
New features:
|
||||||
|
- Add "New Window" command
|
||||||
|
- Enable files to be opened with Lightningbeam
|
||||||
|
Bugfixes:
|
||||||
|
- Fix error when an object is deleted from a frame
|
||||||
|
- Fix parent references being lost
|
||||||
|
- Fix objects not showing up when imported multiple times
|
||||||
|
|
||||||
# 0.7.11-alpha:
|
# 0.7.11-alpha:
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
- Fix duplicate objects showing up after grouping
|
- Fix duplicate objects showing up after grouping
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Ensure the script stops on error
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Check if a version argument was passed
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "Usage: ./create-release.sh <version>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION=$1
|
||||||
|
RELEASE_BRANCH="release"
|
||||||
|
MAIN_BRANCH="main"
|
||||||
|
CONFIG_FILE="src-tauri/tauri.conf.json"
|
||||||
|
|
||||||
|
echo "Updating version to $VERSION in $CONFIG_FILE..."
|
||||||
|
jq --arg version "$VERSION" '.version = $version' $CONFIG_FILE > tmp.json && mv tmp.json $CONFIG_FILE
|
||||||
|
|
||||||
|
echo "Committing to main..."
|
||||||
|
git add $CONFIG_FILE
|
||||||
|
git commit -m "Bump version to $VERSION"
|
||||||
|
|
||||||
|
echo "Checking out the release branch..."
|
||||||
|
git checkout $RELEASE_BRANCH
|
||||||
|
|
||||||
|
echo "Merging the main branch into $RELEASE_BRANCH..."
|
||||||
|
git merge $MAIN_BRANCH --no-ff -m "Release $VERSION"
|
||||||
|
|
||||||
|
echo "Pushing changes to the release branch..."
|
||||||
|
git push origin $RELEASE_BRANCH
|
||||||
|
|
||||||
|
git checkout $MAIN_BRANCH
|
||||||
|
|
||||||
|
echo "Release $VERSION created and pushed successfully!"
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -18,7 +18,7 @@ crate-type = ["staticlib", "cdylib", "rlib"]
|
||||||
tauri-build = { version = "2", features = [] }
|
tauri-build = { version = "2", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tauri = { version = "2", features = [] }
|
tauri = { version = "2", features = ["protocol-asset"] }
|
||||||
tauri-plugin-shell = "2"
|
tauri-plugin-shell = "2"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::{path::PathBuf, sync::Mutex};
|
||||||
|
|
||||||
use tauri_plugin_log::{Target, TargetKind};
|
use tauri_plugin_log::{Target, TargetKind};
|
||||||
use log::{trace, info, debug, warn, error};
|
use log::{trace, info, debug, warn, error};
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use tauri::{Manager, WebviewUrl, WebviewWindowBuilder};
|
use tauri::{AppHandle, Manager, Url, WebviewUrl, WebviewWindowBuilder};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -39,27 +39,131 @@ fn error(msg: String) {
|
||||||
error!("{}",msg);
|
error!("{}",msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use tauri::PhysicalSize;
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn create_window(app: tauri::AppHandle) {
|
async fn create_window(app: tauri::AppHandle, path: Option<String>) {
|
||||||
let state = app.state::<Mutex<AppState>>();
|
let state = app.state::<Mutex<AppState>>();
|
||||||
|
|
||||||
// Lock the mutex to get mutable access:
|
// Lock the mutex to get mutable access:
|
||||||
let mut state = state.lock().unwrap();
|
let mut state = state.lock().unwrap();
|
||||||
|
|
||||||
// Increment the counter and generate a unique window label
|
// Increment the counter and generate a unique window label
|
||||||
let window_label = format!("window{}", state.counter);
|
let window_label = format!("window{}", state.counter);
|
||||||
state.counter += 1;
|
state.counter += 1;
|
||||||
|
|
||||||
// Build the new window with the unique label
|
// Build the new window with the unique label
|
||||||
let _webview_window = WebviewWindowBuilder::new(&app, &window_label, WebviewUrl::App("index.html".into()))
|
let webview_window = WebviewWindowBuilder::new(&app, &window_label, WebviewUrl::App("index.html".into()))
|
||||||
|
.title("Lightningbeam")
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// Get the current monitor's screen size from the new window
|
||||||
|
if let Ok(Some(monitor)) = webview_window.current_monitor() {
|
||||||
|
let screen_size = monitor.size(); // Get the size of the monitor
|
||||||
|
let width = 4096;
|
||||||
|
let height = 4096;
|
||||||
|
|
||||||
|
// Set the window size to be the smaller of the specified size or the screen size
|
||||||
|
let new_width = width.min(screen_size.width as u32);
|
||||||
|
let new_height = height.min(screen_size.height as u32 - 100);
|
||||||
|
|
||||||
|
// Set the size using PhysicalSize
|
||||||
|
webview_window.set_size(tauri::Size::Physical(PhysicalSize::new(new_width, new_height)))
|
||||||
|
.expect("Failed to set window size");
|
||||||
|
} else {
|
||||||
|
eprintln!("Could not detect the current monitor.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the opened file if provided
|
||||||
|
if let Some(val) = path {
|
||||||
|
// Pass path data to the window via JavaScript
|
||||||
|
webview_window.eval(&format!("window.openedFiles = [\"{val}\"]")).unwrap();
|
||||||
|
|
||||||
|
// Set the window title if provided
|
||||||
|
webview_window.set_title(&val).expect("Failed to set window title");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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(",");
|
||||||
|
warn!("{}",files);
|
||||||
|
|
||||||
|
let window = app.get_webview_window("main").unwrap();
|
||||||
|
window.eval(&format!("window.openedFiles = [{files}]")).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
let pkg_name = env!("CARGO_PKG_NAME").to_string();
|
let pkg_name = env!("CARGO_PKG_NAME").to_string();
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
|
.setup(|app| {
|
||||||
|
{
|
||||||
|
app.manage(Mutex::new(AppState::default()));
|
||||||
|
}
|
||||||
|
#[cfg(any(windows, target_os = "linux"))] // Windows/Linux needs different handling from macOS
|
||||||
|
{
|
||||||
|
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::parse(&maybe_file) {
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
#[cfg(debug_assertions)] // only include this code on debug builds
|
||||||
|
{
|
||||||
|
let window = app.get_webview_window("main").unwrap();
|
||||||
|
window.open_devtools();
|
||||||
|
window.close_devtools();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
.plugin(
|
.plugin(
|
||||||
tauri_plugin_log::Builder::new()
|
tauri_plugin_log::Builder::new()
|
||||||
.timezone_strategy(tauri_plugin_log::TimezoneStrategy::UseLocal)
|
.timezone_strategy(tauri_plugin_log::TimezoneStrategy::UseLocal)
|
||||||
|
|
@ -81,26 +185,28 @@ pub fn run() {
|
||||||
Target::new(TargetKind::LogDir { file_name: Some("logs".to_string()) }),
|
Target::new(TargetKind::LogDir { file_name: Some("logs".to_string()) }),
|
||||||
Target::new(TargetKind::Webview),
|
Target::new(TargetKind::Webview),
|
||||||
])
|
])
|
||||||
.build(),
|
.build()
|
||||||
)
|
)
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
.plugin(tauri_plugin_fs::init())
|
.plugin(tauri_plugin_fs::init())
|
||||||
.plugin(tauri_plugin_shell::init())
|
.plugin(tauri_plugin_shell::init())
|
||||||
.invoke_handler(tauri::generate_handler![greet, trace, debug, info, warn, error, create_window])
|
.invoke_handler(tauri::generate_handler![greet, trace, debug, info, warn, error, create_window])
|
||||||
// .manage(window_counter)
|
// .manage(window_counter)
|
||||||
.setup(|app| {
|
.build(tauri::generate_context!())
|
||||||
#[cfg(debug_assertions)] // only include this code on debug builds
|
.expect("error while running tauri application")
|
||||||
{
|
.run(
|
||||||
let window = app.get_webview_window("main").unwrap();
|
#[allow(unused_variables)]
|
||||||
window.open_devtools();
|
|app, event| {
|
||||||
window.close_devtools();
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
}
|
if let tauri::RunEvent::Opened { urls } = event {
|
||||||
{
|
let files = urls
|
||||||
app.manage(Mutex::new(AppState::default()));
|
.into_iter()
|
||||||
}
|
.filter_map(|url| url.to_file_path().ok())
|
||||||
Ok(())
|
.collect::<Vec<_>>();
|
||||||
})
|
|
||||||
.run(tauri::generate_context!())
|
handle_file_associations(app.clone(), files);
|
||||||
.expect("error while running tauri application");
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
tracing_subscriber::fmt().with_env_filter(EnvFilter::new(format!("{}=trace", pkg_name))).init();
|
tracing_subscriber::fmt().with_env_filter(EnvFilter::new(format!("{}=trace", pkg_name))).init();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lightningbeam",
|
"productName": "Lightningbeam",
|
||||||
"version": "0.7.11-alpha",
|
"version": "0.7.13-alpha",
|
||||||
"identifier": "org.lightningbeam.core",
|
"identifier": "org.lightningbeam.core",
|
||||||
"build": {
|
"build": {
|
||||||
"frontendDist": "../src"
|
"frontendDist": "../src"
|
||||||
|
|
@ -17,7 +17,10 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"security": {
|
"security": {
|
||||||
"csp": null
|
"csp": null,
|
||||||
|
"assetProtocol": {
|
||||||
|
"enable": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bundle": {
|
"bundle": {
|
||||||
|
|
@ -43,6 +46,14 @@
|
||||||
"files": {},
|
"files": {},
|
||||||
"release": "1"
|
"release": "1"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"fileAssociations": [
|
||||||
|
{
|
||||||
|
"ext": [
|
||||||
|
"beam"
|
||||||
|
],
|
||||||
|
"mimeType": "text/plain"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
74
src/main.js
74
src/main.js
|
|
@ -354,6 +354,7 @@ let config = {
|
||||||
undo: "<mod>z",
|
undo: "<mod>z",
|
||||||
redo: "<mod>Z",
|
redo: "<mod>Z",
|
||||||
new: "<mod>n",
|
new: "<mod>n",
|
||||||
|
newWindow: "<mod>N",
|
||||||
save: "<mod>s",
|
save: "<mod>s",
|
||||||
saveAs: "<mod>S",
|
saveAs: "<mod>S",
|
||||||
open: "<mod>o",
|
open: "<mod>o",
|
||||||
|
|
@ -3688,6 +3689,9 @@ class GraphicsObject extends Widget {
|
||||||
graphicsObject.currentFrameNum = json.currentFrameNum;
|
graphicsObject.currentFrameNum = json.currentFrameNum;
|
||||||
graphicsObject.currentLayer = json.currentLayer;
|
graphicsObject.currentLayer = json.currentLayer;
|
||||||
graphicsObject.children = [];
|
graphicsObject.children = [];
|
||||||
|
if (json.parent in pointerList) {
|
||||||
|
graphicsObject.parent = pointerList[json.parent]
|
||||||
|
}
|
||||||
for (let layer of json.layers) {
|
for (let layer of json.layers) {
|
||||||
graphicsObject.layers.push(Layer.fromJSON(layer));
|
graphicsObject.layers.push(Layer.fromJSON(layer));
|
||||||
}
|
}
|
||||||
|
|
@ -3714,6 +3718,7 @@ class GraphicsObject extends Widget {
|
||||||
json.currentFrameNum = this.currentFrameNum;
|
json.currentFrameNum = this.currentFrameNum;
|
||||||
json.currentLayer = this.currentLayer;
|
json.currentLayer = this.currentLayer;
|
||||||
json.layers = [];
|
json.layers = [];
|
||||||
|
json.parent = this.parent?.idx
|
||||||
for (let layer of this.layers) {
|
for (let layer of this.layers) {
|
||||||
json.layers.push(layer.toJSON(randomizeUuid));
|
json.layers.push(layer.toJSON(randomizeUuid));
|
||||||
}
|
}
|
||||||
|
|
@ -4369,6 +4374,10 @@ function decrementFrame() {
|
||||||
updateUI();
|
updateUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function newWindow(path) {
|
||||||
|
invoke("create_window", {app: window.__TAURI__.app, path: path})
|
||||||
|
}
|
||||||
|
|
||||||
function _newFile(width, height, fps) {
|
function _newFile(width, height, fps) {
|
||||||
root = new GraphicsObject("root");
|
root = new GraphicsObject("root");
|
||||||
context.objectStack = [root];
|
context.objectStack = [root];
|
||||||
|
|
@ -4409,7 +4418,7 @@ async function _save(path) {
|
||||||
// console.log(action.name);
|
// console.log(action.name);
|
||||||
// }
|
// }
|
||||||
const fileData = {
|
const fileData = {
|
||||||
version: "1.7.6",
|
version: "1.7.7",
|
||||||
width: config.fileWidth,
|
width: config.fileWidth,
|
||||||
height: config.fileHeight,
|
height: config.fileHeight,
|
||||||
fps: config.framerate,
|
fps: config.framerate,
|
||||||
|
|
@ -4583,6 +4592,19 @@ async function _open(path, returnJson = false) {
|
||||||
undoStack.push(action);
|
undoStack.push(action);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (file.version < "1.7.7") {
|
||||||
|
function setParentReferences(obj, parentIdx = null) {
|
||||||
|
if (obj.type === "GraphicsObject") {
|
||||||
|
obj.parent = parentIdx; // Set the parent property
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.values(obj).forEach(child => {
|
||||||
|
if (typeof child === 'object' && child !== null) setParentReferences(child, obj.type === "GraphicsObject" ? obj.idx : parentIdx);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
setParentReferences(file.json)
|
||||||
|
console.log(file.json)
|
||||||
|
}
|
||||||
if (file.version < "1.7.6") {
|
if (file.version < "1.7.6") {
|
||||||
function restoreLineColors(obj) {
|
function restoreLineColors(obj) {
|
||||||
// Step 1: Create colorMapping dictionary
|
// Step 1: Create colorMapping dictionary
|
||||||
|
|
@ -4773,23 +4795,27 @@ async function importFile() {
|
||||||
function assignUUIDs(obj, existing) {
|
function assignUUIDs(obj, existing) {
|
||||||
const uuidCache = {}; // Cache to store UUIDs for existing values
|
const uuidCache = {}; // Cache to store UUIDs for existing values
|
||||||
|
|
||||||
function deepAssign(obj) {
|
function replaceUuids(obj) {
|
||||||
for (const [key, value] of Object.entries(obj)) {
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
if (typeof value === "object" && value !== null) {
|
if (typeof value === "object" && value !== null) {
|
||||||
// Recurse for nested objects
|
replaceUuids(value);
|
||||||
deepAssign(value);
|
|
||||||
} else if (value in existing && key != "name") {
|
} else if (value in existing && key != "name") {
|
||||||
// If the value is in the "existing" list, assign a UUID
|
|
||||||
if (!uuidCache[value]) {
|
if (!uuidCache[value]) {
|
||||||
uuidCache[value] = uuidv4(); // Store the generated UUID for the value
|
uuidCache[value] = uuidv4();
|
||||||
}
|
}
|
||||||
obj[key] = uuidCache[value]; // Assign the UUID to the object property
|
obj[key] = uuidCache[value];
|
||||||
} else if (key in existing) {
|
}
|
||||||
// If the value is in the "existing" list, assign a UUID
|
}
|
||||||
if (!uuidCache[key]) {
|
}
|
||||||
uuidCache[key] = uuidv4(); // Store the generated UUID for the value
|
|
||||||
}
|
function replaceReferences(obj) {
|
||||||
obj[key] = uuidCache[key]; // Assign the UUID to the object property
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
|
if (key in existing) {
|
||||||
|
obj[uuidCache[key]] = obj[key];
|
||||||
|
delete obj[key]
|
||||||
|
}
|
||||||
|
if (typeof value === "object" && value !== null) {
|
||||||
|
replaceReferences(value);
|
||||||
} else if (value in uuidCache) {
|
} else if (value in uuidCache) {
|
||||||
obj[key] = value
|
obj[key] = value
|
||||||
}
|
}
|
||||||
|
|
@ -4797,7 +4823,8 @@ async function importFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the recursion with the provided object
|
// Start the recursion with the provided object
|
||||||
deepAssign(obj);
|
replaceUuids(obj);
|
||||||
|
replaceReferences(obj)
|
||||||
|
|
||||||
return obj; // Return the updated object
|
return obj; // Return the updated object
|
||||||
}
|
}
|
||||||
|
|
@ -5944,6 +5971,7 @@ function stage() {
|
||||||
for (let child of context.selection) {
|
for (let child of context.selection) {
|
||||||
if (!context.activeObject.currentFrame) continue;
|
if (!context.activeObject.currentFrame) continue;
|
||||||
if (!context.activeObject.currentFrame.keys) continue;
|
if (!context.activeObject.currentFrame.keys) continue;
|
||||||
|
if (!child.idx in context.activeObject.currentFrame.keys) continue;
|
||||||
context.activeObject.currentFrame.keys[child.idx].x +=
|
context.activeObject.currentFrame.keys[child.idx].x +=
|
||||||
mouse.x - context.lastMouse.x;
|
mouse.x - context.lastMouse.x;
|
||||||
context.activeObject.currentFrame.keys[child.idx].y +=
|
context.activeObject.currentFrame.keys[child.idx].y +=
|
||||||
|
|
@ -6389,6 +6417,7 @@ function timeline() {
|
||||||
|
|
||||||
const frame = layer.getFrame(timeline_cvs.clicked_frame);
|
const frame = layer.getFrame(timeline_cvs.clicked_frame);
|
||||||
if (frame.exists) {
|
if (frame.exists) {
|
||||||
|
console.log(frame.keys)
|
||||||
if (!e.shiftKey) {
|
if (!e.shiftKey) {
|
||||||
// Check if the clicked frame is already in the selection
|
// Check if the clicked frame is already in the selection
|
||||||
const existingIndex = context.selectedFrames.findIndex(
|
const existingIndex = context.selectedFrames.findIndex(
|
||||||
|
|
@ -6700,7 +6729,9 @@ function outliner(object = undefined) {
|
||||||
async function startup() {
|
async function startup() {
|
||||||
await loadConfig();
|
await loadConfig();
|
||||||
createNewFileDialog(_newFile, _open, config);
|
createNewFileDialog(_newFile, _open, config);
|
||||||
showNewFileDialog(config);
|
if (!window.openedFiles) {
|
||||||
|
showNewFileDialog(config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startup();
|
startup();
|
||||||
|
|
@ -7881,6 +7912,12 @@ async function renderMenu() {
|
||||||
action: newFile,
|
action: newFile,
|
||||||
accelerator: getShortcut("new"),
|
accelerator: getShortcut("new"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: "New Window",
|
||||||
|
enabled: true,
|
||||||
|
action: newWindow,
|
||||||
|
accelerator: getShortcut("newWindow"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: "Save",
|
text: "Save",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
@ -8306,3 +8343,10 @@ function renderAll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderAll();
|
renderAll();
|
||||||
|
|
||||||
|
if (window.openedFiles?.length>0) {
|
||||||
|
_open(window.openedFiles[0])
|
||||||
|
for (let i=1; i<window.openedFiles.length; i++) {
|
||||||
|
newWindow(window.openedFiles[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -145,12 +145,14 @@ function createNewFileDialog(newFileCallback, openFileCallback, config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function showNewFileDialog(config) {
|
function showNewFileDialog(config) {
|
||||||
|
if (!overlay) return;
|
||||||
overlay.style.display = 'block';
|
overlay.style.display = 'block';
|
||||||
newFileDialog.style.display = 'block';
|
newFileDialog.style.display = 'block';
|
||||||
displayFiles(config.recentFiles); // Reload the recent files
|
displayFiles(config.recentFiles); // Reload the recent files
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDialog() {
|
function closeDialog() {
|
||||||
|
if (!overlay) return;
|
||||||
overlay.style.display = 'none';
|
overlay.style.display = 'none';
|
||||||
newFileDialog.style.display = 'none';
|
newFileDialog.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue