diff --git a/src/main.js b/src/main.js index 0410a88..b57fad8 100644 --- a/src/main.js +++ b/src/main.js @@ -4841,7 +4841,7 @@ function createProgressModal() { // Create text to show the current frame info const progressText = document.createElement('p'); progressText.id = 'progressText'; - progressText.innerText = 'Rendering frame 0 of 0'; + progressText.innerText = 'Initializing...'; // Append elements to modalContent modalContent.appendChild(progressBar); diff --git a/src/styles.css b/src/styles.css index ab71481..0871d04 100644 --- a/src/styles.css +++ b/src/styles.css @@ -490,7 +490,7 @@ button { display: none; } -#overlay { +#overlay, #saveOverlay { display: none; /* Hidden by default */ position: fixed; top: 0; @@ -502,7 +502,7 @@ button { } /* Scoped styles for the dialog */ -#newFileDialog { +#newFileDialog, #saveDialog { display: none; /* Hidden by default */ position: fixed; top: 50%; @@ -517,19 +517,19 @@ button { z-index: 1000; /* Make sure it's in front of other elements */ } -#newFileDialog .dialog-label { +#newFileDialog .dialog-label, #saveDialog label { display: block; margin: 10px 0 5px; } -#newFileDialog .dialog-input { +#newFileDialog .dialog-input, #saveDialog input { width: 100%; padding: 8px; margin: 5px 0; border: 1px solid #aaa; } -#newFileDialog .dialog-button { +#newFileDialog .dialog-button, #saveDialog button { width: 100%; padding: 10px; margin-top: 10px; @@ -632,11 +632,11 @@ button { background-color: #0f0f0f69; } - #newFileDialog { + #newFileDialog, #saveDialog { background-color: #444; border: 1px solid #333; } - #newFileDialog .dialog-input { + #newFileDialog .dialog-input, #saveDialog input { border: 1px solid #333; } #recentFilesList li:hover { diff --git a/src/tauri_polyfill.js b/src/tauri_polyfill.js index 04f2899..1c0e045 100644 --- a/src/tauri_polyfill.js +++ b/src/tauri_polyfill.js @@ -47,6 +47,88 @@ if (!window.__TAURI__) { }); }; + function promptForFilename(filters, defaultFilename = '') { + function createLabel(text, forId) { + const label = document.createElement('label'); + label.setAttribute('for', forId); + label.textContent = text; + return label; + } + return new Promise((resolve, reject) => { + // Create and style modal dynamically + const modal = document.createElement('div'); + const modalContent = document.createElement('div'); + const filenameInput = document.createElement('input'); + const fileFilter = document.createElement('select'); + const submitBtn = document.createElement('button'); + const cancelBtn = document.createElement('button'); + + // Append elements + modal.appendChild(modalContent); + modalContent.appendChild(createLabel('Enter filename:', 'filenameInput')); + modalContent.appendChild(filenameInput); + modalContent.appendChild(createLabel('Select file type:', 'fileFilter')); + modalContent.appendChild(fileFilter); + modalContent.appendChild(submitBtn); + modalContent.appendChild(cancelBtn); + + document.body.appendChild(modal); + + // Style modal elements + modal.id = "saveOverlay"; + modal.style.display = 'block'; + modalContent.id = "saveDialog"; + modalContent.style.display = 'block'; + [filenameInput, fileFilter].forEach(el => Object.assign(el.style, { + width: '100%', padding: '10px', marginBottom: '10px' + })); + [submitBtn, cancelBtn].forEach(el => el.style.padding = '10px 20px'); + + // Populate filter dropdown and set default filename + filters.forEach(filter => fileFilter.add(new Option(filter.name, filter.extensions[0]))); + // filenameInput.value = defaultFilename.split('.')[0]; + filenameInput.value = defaultFilename + const extension = defaultFilename.split('.').pop(); + filenameInput.focus() + filenameInput.setSelectionRange(0, defaultFilename.length - extension.length - 1); // Select only the base filename + + // Update extension based on selected filter + fileFilter.addEventListener('change', () => updateFilename(true)); + filenameInput.addEventListener('input', () => updateFilename(false)); + + function updateFilename(reselect) { + const base = filenameInput.value.split('.')[0]; + filenameInput.value = `${base}.${fileFilter.value}`; + if (reselect) { + filenameInput.focus() + filenameInput.setSelectionRange(0, base.length); // Select only the base filename + } + } + + // Handle buttons + submitBtn.textContent = 'Submit'; + cancelBtn.textContent = 'Cancel'; + submitBtn.onclick = () => { + const chosenFilename = filenameInput.value; + if (!chosenFilename) reject(new Error('Filename missing.')); + resolve(chosenFilename); + modal.remove(); + }; + cancelBtn.onclick = () => { + reject(new Error('User canceled.')); + modal.remove(); + }; + + // Close modal if clicked outside + window.addEventListener('click', (e) => { + if (e.target === modal) { + reject(new Error('User clicked outside.')); + modal.remove(); + } + }); + }); + } + window.__TAURI__ = { core: { invoke: () => {} @@ -184,8 +266,8 @@ if (!window.__TAURI__) { input.click(); }); }, - save: async () => { - return prompt("Filename", "untitled.beam") + save: async (params) => { + return await promptForFilename(params.filters, params.defaultPath) }, message: () => {}, confirm: () => {},