Add config saving/loading and recent files list on new file dialog
This commit is contained in:
parent
570bb10f04
commit
237b8882cf
148
src/main.js
148
src/main.js
|
|
@ -13,7 +13,7 @@ const {
|
||||||
message: messageDialog,
|
message: messageDialog,
|
||||||
confirm: confirmDialog,
|
confirm: confirmDialog,
|
||||||
} = window.__TAURI__.dialog;
|
} = window.__TAURI__.dialog;
|
||||||
const { documentDir, join, basename } = window.__TAURI__.path;
|
const { documentDir, join, basename, appLocalDataDir } = window.__TAURI__.path;
|
||||||
const { Menu, MenuItem, Submenu } = window.__TAURI__.menu ;
|
const { Menu, MenuItem, Submenu } = window.__TAURI__.menu ;
|
||||||
const { getCurrentWindow } = window.__TAURI__.window;
|
const { getCurrentWindow } = window.__TAURI__.window;
|
||||||
const { getVersion } = window.__TAURI__.app;
|
const { getVersion } = window.__TAURI__.app;
|
||||||
|
|
@ -66,15 +66,19 @@ let maxFileVersion = "2.0"
|
||||||
|
|
||||||
let filePath = undefined
|
let filePath = undefined
|
||||||
let fileExportPath = undefined
|
let fileExportPath = undefined
|
||||||
let fileWidth = 1500
|
// let fileWidth = 1500
|
||||||
let fileHeight = 1000
|
// let fileHeight = 1000
|
||||||
let fileFps = 12
|
// let fileFps = 12
|
||||||
|
|
||||||
|
|
||||||
let playing = false
|
let playing = false
|
||||||
|
|
||||||
let clipboard = []
|
let clipboard = []
|
||||||
|
|
||||||
|
const CONFIG_FILE_PATH = 'config.json';
|
||||||
|
const defaultConfig = {
|
||||||
|
};
|
||||||
|
|
||||||
let tools = {
|
let tools = {
|
||||||
select: {
|
select: {
|
||||||
icon: "/assets/select.svg",
|
icon: "/assets/select.svg",
|
||||||
|
|
@ -250,6 +254,43 @@ let config = {
|
||||||
group: "<mod>g",
|
group: "<mod>g",
|
||||||
zoomIn: "<mod>+",
|
zoomIn: "<mod>+",
|
||||||
zoomOut: "<mod>-",
|
zoomOut: "<mod>-",
|
||||||
|
},
|
||||||
|
fileWidth: 800,
|
||||||
|
fileHeight: 600,
|
||||||
|
framerate: 24,
|
||||||
|
recentFiles: []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the configuration from the file system
|
||||||
|
async function loadConfig() {
|
||||||
|
try {
|
||||||
|
const configPath = await join(await appLocalDataDir(), CONFIG_FILE_PATH);
|
||||||
|
const configData = await readTextFile(configPath);
|
||||||
|
config = JSON.parse(configData);
|
||||||
|
updateUI()
|
||||||
|
console.log(config)
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error loading config, returning default config:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the configuration to a file
|
||||||
|
async function saveConfig() {
|
||||||
|
try {
|
||||||
|
const configPath = await join(await appLocalDataDir(), CONFIG_FILE_PATH);
|
||||||
|
await writeTextFile(configPath, JSON.stringify(config, null, 2));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error saving config:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addRecentFile(filePath) {
|
||||||
|
if (!config.recentFiles.includes(filePath)) {
|
||||||
|
config.recentFiles.unshift(filePath);
|
||||||
|
if (config.recentFiles.length > 10) {
|
||||||
|
config.recentFiles = config.recentFiles.slice(0, 10);
|
||||||
|
}
|
||||||
|
await saveConfig(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -488,7 +529,7 @@ let actions = {
|
||||||
newAudioLayer.track.add(0,action.uuid)
|
newAudioLayer.track.add(0,action.uuid)
|
||||||
object.audioLayers.push(newAudioLayer)
|
object.audioLayers.push(newAudioLayer)
|
||||||
// TODO: compute image height better
|
// TODO: compute image height better
|
||||||
generateWaveform(img, player.buffer, 50, 25, fileFps)
|
generateWaveform(img, player.buffer, 50, 25, config.framerate)
|
||||||
updateLayers()
|
updateLayers()
|
||||||
},
|
},
|
||||||
rollback: (action) => {
|
rollback: (action) => {
|
||||||
|
|
@ -1985,11 +2026,11 @@ class GraphicsObject {
|
||||||
let frame = layer.getFrame(this.currentFrameNum)
|
let frame = layer.getFrame(this.currentFrameNum)
|
||||||
for (let shape of frame.shapes) {
|
for (let shape of frame.shapes) {
|
||||||
if (context.shapeselection.indexOf(shape) >= 0) {
|
if (context.shapeselection.indexOf(shape) >= 0) {
|
||||||
invertPixels(ctx, fileWidth, fileHeight)
|
invertPixels(ctx, config.fileWidth, config.fileHeight)
|
||||||
}
|
}
|
||||||
shape.draw(context)
|
shape.draw(context)
|
||||||
if (context.shapeselection.indexOf(shape) >= 0) {
|
if (context.shapeselection.indexOf(shape) >= 0) {
|
||||||
invertPixels(ctx, fileWidth, fileHeight)
|
invertPixels(ctx, config.fileWidth, config.fileHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let child of layer.children) {
|
for (let child of layer.children) {
|
||||||
|
|
@ -2362,7 +2403,7 @@ function playPause() {
|
||||||
console.log(1)
|
console.log(1)
|
||||||
for (let i in audioLayer.sounds) {
|
for (let i in audioLayer.sounds) {
|
||||||
let sound = audioLayer.sounds[i]
|
let sound = audioLayer.sounds[i]
|
||||||
sound.player.start(0,context.activeObject.currentFrameNum / fileFps)
|
sound.player.start(0,context.activeObject.currentFrameNum / config.framerate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
advanceFrame()
|
advanceFrame()
|
||||||
|
|
@ -2384,7 +2425,7 @@ function advanceFrame() {
|
||||||
updateUI()
|
updateUI()
|
||||||
if (playing) {
|
if (playing) {
|
||||||
if (context.activeObject.currentFrameNum < context.activeObject.maxFrame - 1) {
|
if (context.activeObject.currentFrameNum < context.activeObject.maxFrame - 1) {
|
||||||
setTimeout(advanceFrame, 1000/fileFps)
|
setTimeout(advanceFrame, 1000/config.framerate)
|
||||||
} else {
|
} else {
|
||||||
playing = false
|
playing = false
|
||||||
for (let audioLayer of context.activeObject.audioLayers) {
|
for (let audioLayer of context.activeObject.audioLayers) {
|
||||||
|
|
@ -2407,9 +2448,10 @@ function decrementFrame() {
|
||||||
function _newFile(width, height, fps) {
|
function _newFile(width, height, fps) {
|
||||||
root = new GraphicsObject("root");
|
root = new GraphicsObject("root");
|
||||||
context.objectStack = [root]
|
context.objectStack = [root]
|
||||||
fileWidth = width
|
config.fileWidth = width
|
||||||
fileHeight = height
|
config.fileHeight = height
|
||||||
fileFps = fps
|
config.framerate = fps
|
||||||
|
saveConfig()
|
||||||
undoStack = []
|
undoStack = []
|
||||||
redoStack = []
|
redoStack = []
|
||||||
for (let stage of document.querySelectorAll(".stage")) {
|
for (let stage of document.querySelectorAll(".stage")) {
|
||||||
|
|
@ -2425,7 +2467,7 @@ function _newFile(width, height, fps) {
|
||||||
|
|
||||||
async function newFile() {
|
async function newFile() {
|
||||||
if (await confirmDialog("Create a new file? Unsaved work will be lost.", {title: "New file", kind: "warning"})) {
|
if (await confirmDialog("Create a new file? Unsaved work will be lost.", {title: "New file", kind: "warning"})) {
|
||||||
showNewFileDialog()
|
showNewFileDialog(config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2433,14 +2475,15 @@ async function _save(path) {
|
||||||
try {
|
try {
|
||||||
const fileData = {
|
const fileData = {
|
||||||
version: "1.3",
|
version: "1.3",
|
||||||
width: fileWidth,
|
width: config.fileWidth,
|
||||||
height: fileHeight,
|
height: config.fileHeight,
|
||||||
fps: fileFps,
|
fps: config.framerate,
|
||||||
actions: undoStack
|
actions: undoStack
|
||||||
}
|
}
|
||||||
const contents = JSON.stringify(fileData);
|
const contents = JSON.stringify(fileData);
|
||||||
await writeTextFile(path, contents)
|
await writeTextFile(path, contents)
|
||||||
filePath = path
|
filePath = path
|
||||||
|
addRecentFile(path)
|
||||||
lastSaveIndex = undoStack.length - 1;
|
lastSaveIndex = undoStack.length - 1;
|
||||||
console.log(`${path} saved successfully!`);
|
console.log(`${path} saved successfully!`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -2470,20 +2513,7 @@ async function saveAs() {
|
||||||
if (path != undefined) _save(path);
|
if (path != undefined) _save(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function open() {
|
async function _open(path) {
|
||||||
closeDialog()
|
|
||||||
const path = await openFileDialog({
|
|
||||||
multiple: false,
|
|
||||||
directory: false,
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
name: 'Lightningbeam files (.beam)',
|
|
||||||
extensions: ['beam'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
defaultPath: await documentDir(),
|
|
||||||
});
|
|
||||||
if (path) {
|
|
||||||
try {
|
try {
|
||||||
const contents = await readTextFile(path)
|
const contents = await readTextFile(path)
|
||||||
let file = JSON.parse(contents)
|
let file = JSON.parse(contents)
|
||||||
|
|
@ -2509,6 +2539,7 @@ async function open() {
|
||||||
}
|
}
|
||||||
lastSaveIndex = undoStack.length - 1;
|
lastSaveIndex = undoStack.length - 1;
|
||||||
filePath = path
|
filePath = path
|
||||||
|
addRecentFile(path)
|
||||||
updateUI()
|
updateUI()
|
||||||
} else {
|
} else {
|
||||||
await messageDialog(`File ${path} was created in a newer version of Lightningbeam and cannot be opened in this version.`, { title: 'File version mismatch', kind: 'error' });
|
await messageDialog(`File ${path} was created in a newer version of Lightningbeam and cannot be opened in this version.`, { title: 'File version mismatch', kind: 'error' });
|
||||||
|
|
@ -2524,6 +2555,23 @@ async function open() {
|
||||||
await messageDialog(`Could not parse ${path}, is it actually a Lightningbeam file?`, { title: 'Error', kind: 'error' })
|
await messageDialog(`Could not parse ${path}, is it actually a Lightningbeam file?`, { title: 'Error', kind: 'error' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function open() {
|
||||||
|
closeDialog()
|
||||||
|
const path = await openFileDialog({
|
||||||
|
multiple: false,
|
||||||
|
directory: false,
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
name: 'Lightningbeam files (.beam)',
|
||||||
|
extensions: ['beam'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultPath: await documentDir(),
|
||||||
|
});
|
||||||
|
if (path) {
|
||||||
|
_open(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2680,8 +2728,8 @@ async function render() {
|
||||||
|
|
||||||
const frames = [];
|
const frames = [];
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
canvas.width = fileWidth; // Set desired width
|
canvas.width = config.fileWidth; // Set desired width
|
||||||
canvas.height = fileHeight; // Set desired height
|
canvas.height = config.fileHeight; // Set desired height
|
||||||
let exportContext = {
|
let exportContext = {
|
||||||
...context,
|
...context,
|
||||||
ctx: canvas.getContext('2d'),
|
ctx: canvas.getContext('2d'),
|
||||||
|
|
@ -2695,7 +2743,7 @@ async function render() {
|
||||||
|
|
||||||
root.currentFrameNum = i
|
root.currentFrameNum = i
|
||||||
exportContext.ctx.fillStyle = "white"
|
exportContext.ctx.fillStyle = "white"
|
||||||
exportContext.ctx.rect(0,0,fileWidth, fileHeight)
|
exportContext.ctx.rect(0,0,config.fileWidth, config.fileHeight)
|
||||||
exportContext.ctx.fill()
|
exportContext.ctx.fill()
|
||||||
await root.draw(exportContext)
|
await root.draw(exportContext)
|
||||||
|
|
||||||
|
|
@ -2709,7 +2757,7 @@ async function render() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Use UPNG.js to create the animated PNG
|
// Step 3: Use UPNG.js to create the animated PNG
|
||||||
const apng = UPNG.encode(frames, canvas.width, canvas.height, 0, parseInt(100/fileFps));
|
const apng = UPNG.encode(frames, canvas.width, canvas.height, 0, parseInt(100/config.framerate));
|
||||||
|
|
||||||
// Step 4: Save the APNG file (in Tauri, use writeFile or in the browser, download it)
|
// Step 4: Save the APNG file (in Tauri, use writeFile or in the browser, download it)
|
||||||
const apngBlob = new Blob([apng], { type: 'image/png' });
|
const apngBlob = new Blob([apng], { type: 'image/png' });
|
||||||
|
|
@ -2774,8 +2822,8 @@ function stage() {
|
||||||
let scroller = document.createElement("div")
|
let scroller = document.createElement("div")
|
||||||
let stageWrapper = document.createElement("div")
|
let stageWrapper = document.createElement("div")
|
||||||
stage.className = "stage"
|
stage.className = "stage"
|
||||||
stage.width = 1500
|
stage.width = config.fileWidth
|
||||||
stage.height = 1000
|
stage.height = config.fileHeight
|
||||||
scroller.className = "scroll"
|
scroller.className = "scroll"
|
||||||
stageWrapper.className = "stageWrapper"
|
stageWrapper.className = "stageWrapper"
|
||||||
let selectionRect = document.createElement("div")
|
let selectionRect = document.createElement("div")
|
||||||
|
|
@ -2998,7 +3046,7 @@ function stage() {
|
||||||
|
|
||||||
// We didn't find an existing region to paintbucket, see if we can make one
|
// We didn't find an existing region to paintbucket, see if we can make one
|
||||||
try {
|
try {
|
||||||
regionPoints = floodFillRegion(mouse,epsilon,fileWidth,fileHeight,context, debugPoints, debugPaintbucket)
|
regionPoints = floodFillRegion(mouse,epsilon,config.fileWidth,config.fileHeight,context, debugPoints, debugPaintbucket)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
updateUI()
|
updateUI()
|
||||||
throw e;
|
throw e;
|
||||||
|
|
@ -3007,7 +3055,7 @@ function stage() {
|
||||||
console.log(regionPoints.length)
|
console.log(regionPoints.length)
|
||||||
if (regionPoints.length>0 && regionPoints.length < 10) {
|
if (regionPoints.length>0 && regionPoints.length < 10) {
|
||||||
// probably a very small area, rerun with minimum epsilon
|
// probably a very small area, rerun with minimum epsilon
|
||||||
regionPoints = floodFillRegion(mouse,1,fileWidth,fileHeight,context, debugPoints)
|
regionPoints = floodFillRegion(mouse,1,config.fileWidth,config.fileHeight,context, debugPoints)
|
||||||
}
|
}
|
||||||
let points = []
|
let points = []
|
||||||
for (let point of regionPoints) {
|
for (let point of regionPoints) {
|
||||||
|
|
@ -3700,9 +3748,14 @@ function infopanel() {
|
||||||
return panel
|
return panel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function startup() {
|
||||||
|
await loadConfig()
|
||||||
|
createNewFileDialog(_newFile, _open, config);
|
||||||
|
showNewFileDialog(config)
|
||||||
|
|
||||||
createNewFileDialog(_newFile);
|
}
|
||||||
showNewFileDialog()
|
|
||||||
|
startup()
|
||||||
|
|
||||||
function createPaneMenu(div) {
|
function createPaneMenu(div) {
|
||||||
const menuItems = ["Item 1", "Item 2", "Item 3"]; // The items for the menu
|
const menuItems = ["Item 1", "Item 2", "Item 3"]; // The items for the menu
|
||||||
|
|
@ -3877,22 +3930,22 @@ function updateLayout(element) {
|
||||||
|
|
||||||
function updateUI() {
|
function updateUI() {
|
||||||
for (let canvas of canvases) {
|
for (let canvas of canvases) {
|
||||||
canvas.width = fileWidth * context.zoomLevel
|
canvas.width = config.fileWidth * context.zoomLevel
|
||||||
canvas.height = fileHeight * context.zoomLevel
|
canvas.height = config.fileHeight * context.zoomLevel
|
||||||
canvas.style.width = `${fileWidth * context.zoomLevel}px`
|
canvas.style.width = `${config.fileWidth * context.zoomLevel}px`
|
||||||
canvas.style.height = `${fileHeight * context.zoomLevel}px`
|
canvas.style.height = `${config.fileHeight * context.zoomLevel}px`
|
||||||
let ctx = canvas.getContext("2d")
|
let ctx = canvas.getContext("2d")
|
||||||
ctx.resetTransform();
|
ctx.resetTransform();
|
||||||
ctx.scale(context.zoomLevel, context.zoomLevel)
|
ctx.scale(context.zoomLevel, context.zoomLevel)
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
ctx.fillStyle = "white"
|
ctx.fillStyle = "white"
|
||||||
ctx.fillRect(0,0,fileWidth,fileHeight)
|
ctx.fillRect(0,0,config.fileWidth,config.fileHeight)
|
||||||
|
|
||||||
context.ctx = ctx;
|
context.ctx = ctx;
|
||||||
root.draw(context)
|
root.draw(context)
|
||||||
if (context.activeObject != root) {
|
if (context.activeObject != root) {
|
||||||
ctx.fillStyle = "rgba(255,255,255,0.5)"
|
ctx.fillStyle = "rgba(255,255,255,0.5)"
|
||||||
ctx.fillRect(0,0,fileWidth,fileHeight)
|
ctx.fillRect(0,0,config.fileWidth,config.fileHeight)
|
||||||
context.activeObject.draw(context)
|
context.activeObject.draw(context)
|
||||||
}
|
}
|
||||||
if (context.activeShape) {
|
if (context.activeShape) {
|
||||||
|
|
@ -3903,7 +3956,7 @@ function updateUI() {
|
||||||
if (debugQuadtree) {
|
if (debugQuadtree) {
|
||||||
|
|
||||||
ctx.fillStyle = "rgba(255,255,255,0.5)"
|
ctx.fillStyle = "rgba(255,255,255,0.5)"
|
||||||
ctx.fillRect(0,0,fileWidth,fileHeight)
|
ctx.fillRect(0,0,config.fileWidth,config.fileHeight)
|
||||||
const ep = 2.5
|
const ep = 2.5
|
||||||
const bbox = {
|
const bbox = {
|
||||||
x: { min: context.mousePos.x - ep, max: context.mousePos.x + ep },
|
x: { min: context.mousePos.x - ep, max: context.mousePos.x + ep },
|
||||||
|
|
@ -4708,3 +4761,4 @@ function startToneOnUserInteraction() {
|
||||||
document.addEventListener("keydown", startTone);
|
document.addEventListener("keydown", startTone);
|
||||||
}
|
}
|
||||||
startToneOnUserInteraction()
|
startToneOnUserInteraction()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
|
const { basename, dirname, join } = window.__TAURI__.path;
|
||||||
|
|
||||||
let overlay;
|
let overlay;
|
||||||
let newFileDialog;
|
let newFileDialog;
|
||||||
|
|
||||||
function createNewFileDialog(callback) {
|
let displayFiles
|
||||||
|
|
||||||
|
function createNewFileDialog(newFileCallback, openFileCallback, config) {
|
||||||
overlay = document.createElement('div');
|
overlay = document.createElement('div');
|
||||||
overlay.id = 'overlay';
|
overlay.id = 'overlay';
|
||||||
document.body.appendChild(overlay);
|
document.body.appendChild(overlay);
|
||||||
|
|
@ -11,7 +15,6 @@ function createNewFileDialog(callback) {
|
||||||
newFileDialog.classList.add('hidden');
|
newFileDialog.classList.add('hidden');
|
||||||
document.body.appendChild(newFileDialog);
|
document.body.appendChild(newFileDialog);
|
||||||
|
|
||||||
// Create dialog content dynamically
|
|
||||||
const title = document.createElement('h3');
|
const title = document.createElement('h3');
|
||||||
title.textContent = 'Create New File';
|
title.textContent = 'Create New File';
|
||||||
newFileDialog.appendChild(title);
|
newFileDialog.appendChild(title);
|
||||||
|
|
@ -27,7 +30,8 @@ function createNewFileDialog(callback) {
|
||||||
widthInput.type = 'number';
|
widthInput.type = 'number';
|
||||||
widthInput.id = 'width';
|
widthInput.id = 'width';
|
||||||
widthInput.classList.add('dialog-input');
|
widthInput.classList.add('dialog-input');
|
||||||
widthInput.value = '1500'; // Default value
|
console.log(config.fileWidth)
|
||||||
|
widthInput.value = config.fileWidth;
|
||||||
newFileDialog.appendChild(widthInput);
|
newFileDialog.appendChild(widthInput);
|
||||||
|
|
||||||
// Create Height input
|
// Create Height input
|
||||||
|
|
@ -41,7 +45,7 @@ function createNewFileDialog(callback) {
|
||||||
heightInput.type = 'number';
|
heightInput.type = 'number';
|
||||||
heightInput.id = 'height';
|
heightInput.id = 'height';
|
||||||
heightInput.classList.add('dialog-input');
|
heightInput.classList.add('dialog-input');
|
||||||
heightInput.value = '1000'; // Default value
|
heightInput.value = config.fileHeight;
|
||||||
newFileDialog.appendChild(heightInput);
|
newFileDialog.appendChild(heightInput);
|
||||||
|
|
||||||
// Create FPS input
|
// Create FPS input
|
||||||
|
|
@ -55,7 +59,7 @@ function createNewFileDialog(callback) {
|
||||||
fpsInput.type = 'number';
|
fpsInput.type = 'number';
|
||||||
fpsInput.id = 'fps';
|
fpsInput.id = 'fps';
|
||||||
fpsInput.classList.add('dialog-input');
|
fpsInput.classList.add('dialog-input');
|
||||||
fpsInput.value = '24'; // Default value
|
fpsInput.value = config.framerate;
|
||||||
newFileDialog.appendChild(fpsInput);
|
newFileDialog.appendChild(fpsInput);
|
||||||
|
|
||||||
// Create Create button
|
// Create Create button
|
||||||
|
|
@ -65,31 +69,87 @@ function createNewFileDialog(callback) {
|
||||||
createButton.onclick = createNewFile;
|
createButton.onclick = createNewFile;
|
||||||
newFileDialog.appendChild(createButton);
|
newFileDialog.appendChild(createButton);
|
||||||
|
|
||||||
|
// Recent Files Section
|
||||||
|
const recentFilesTitle = document.createElement('h4');
|
||||||
|
recentFilesTitle.textContent = 'Recent Files';
|
||||||
|
newFileDialog.appendChild(recentFilesTitle);
|
||||||
|
|
||||||
|
const recentFilesList = document.createElement('ul');
|
||||||
|
recentFilesList.id = 'recentFilesList';
|
||||||
|
newFileDialog.appendChild(recentFilesList);
|
||||||
|
|
||||||
// Create the new file (simulation)
|
|
||||||
function createNewFile() {
|
function createNewFile() {
|
||||||
const width = document.getElementById('width').value;
|
const width = parseInt(document.getElementById('width').value);
|
||||||
const height = document.getElementById('height').value;
|
const height = parseInt(document.getElementById('height').value);
|
||||||
const fps = document.getElementById('fps').value;
|
const fps = parseInt(document.getElementById('fps').value);
|
||||||
console.log(`New file created with width: ${width} and height: ${height}`);
|
console.log(`New file created with width: ${width} and height: ${height}`);
|
||||||
callback(width, height, fps)
|
newFileCallback(width, height, fps)
|
||||||
|
closeDialog();
|
||||||
// Add any further logic to handle the new file creation here
|
}
|
||||||
|
|
||||||
closeDialog(); // Close the dialog after file creation
|
|
||||||
|
async function displayRecentFiles(recentFiles) {
|
||||||
|
const recentFilesList = document.getElementById('recentFilesList');
|
||||||
|
const recentFilesTitle = document.querySelector('h4');
|
||||||
|
|
||||||
|
recentFilesList.innerHTML = '';
|
||||||
|
|
||||||
|
// Only show the list if there are recent files
|
||||||
|
if (recentFiles.length === 0) {
|
||||||
|
recentFilesTitle.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
recentFilesTitle.style.display = 'block';
|
||||||
|
const filenames = {};
|
||||||
|
|
||||||
|
for (let filePath of recentFiles) {
|
||||||
|
const filename = await basename(filePath);
|
||||||
|
const dirPath = await dirname(filePath);
|
||||||
|
|
||||||
|
if (!filenames[filename]) {
|
||||||
|
filenames[filename] = [];
|
||||||
|
}
|
||||||
|
filenames[filename].push(dirPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(filenames).forEach((filename) => {
|
||||||
|
const filePaths = filenames[filename];
|
||||||
|
|
||||||
|
// If only one directory, just display the filename
|
||||||
|
if (filePaths.length === 1) {
|
||||||
|
const listItem = document.createElement('li');
|
||||||
|
listItem.textContent = filename;
|
||||||
|
listItem.onclick = () => openFile(filePaths[0], filename);
|
||||||
|
recentFilesList.appendChild(listItem);
|
||||||
|
} else {
|
||||||
|
// For duplicates, display each directory with the filename
|
||||||
|
filePaths.forEach((dirPath) => {
|
||||||
|
const listItem = document.createElement('li');
|
||||||
|
listItem.innerHTML = `${filename} (${dirPath}/)`;
|
||||||
|
listItem.onclick = () => openFile(dirPath, filename);
|
||||||
|
recentFilesList.appendChild(listItem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
displayFiles = displayRecentFiles
|
||||||
|
|
||||||
|
async function openFile(dirPath, filename) {
|
||||||
|
console.log(await join(dirPath, filename))
|
||||||
|
openFileCallback(await join(dirPath, filename))
|
||||||
|
closeDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the dialog if the overlay is clicked
|
|
||||||
overlay.onclick = closeDialog;
|
overlay.onclick = closeDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the dialog
|
function showNewFileDialog(config) {
|
||||||
function showNewFileDialog() {
|
|
||||||
overlay.style.display = 'block';
|
overlay.style.display = 'block';
|
||||||
newFileDialog.style.display = 'block';
|
newFileDialog.style.display = 'block';
|
||||||
|
displayFiles(config.recentFiles); // Reload the recent files
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the dialog
|
|
||||||
function closeDialog() {
|
function closeDialog() {
|
||||||
overlay.style.display = 'none';
|
overlay.style.display = 'none';
|
||||||
newFileDialog.style.display = 'none';
|
newFileDialog.style.display = 'none';
|
||||||
|
|
|
||||||
|
|
@ -537,6 +537,25 @@ button {
|
||||||
#newFileDialog .dialog-button:hover {
|
#newFileDialog .dialog-button:hover {
|
||||||
background-color: #0056b3;
|
background-color: #0056b3;
|
||||||
}
|
}
|
||||||
|
#recentFilesList li {
|
||||||
|
word-wrap: break-word;
|
||||||
|
max-width: 100%;
|
||||||
|
white-space: normal;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#recentFilesList {
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#recentFilesList li:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
#popupMenu {
|
#popupMenu {
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
|
|
@ -596,6 +615,13 @@ button {
|
||||||
#newFileDialog .dialog-input {
|
#newFileDialog .dialog-input {
|
||||||
border: 1px solid #333;
|
border: 1px solid #333;
|
||||||
}
|
}
|
||||||
|
#recentFilesList li:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #555;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
#popupMenu {
|
#popupMenu {
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue