Make polyfilled save dialog consistent with other dialogs

This commit is contained in:
Skyler Lehmkuhl 2025-01-14 22:03:20 -05:00
parent 2ab0df9835
commit df3e2832bf
3 changed files with 92 additions and 10 deletions

View File

@ -4841,7 +4841,7 @@ function createProgressModal() {
// Create text to show the current frame info // Create text to show the current frame info
const progressText = document.createElement('p'); const progressText = document.createElement('p');
progressText.id = 'progressText'; progressText.id = 'progressText';
progressText.innerText = 'Rendering frame 0 of 0'; progressText.innerText = 'Initializing...';
// Append elements to modalContent // Append elements to modalContent
modalContent.appendChild(progressBar); modalContent.appendChild(progressBar);

View File

@ -490,7 +490,7 @@ button {
display: none; display: none;
} }
#overlay { #overlay, #saveOverlay {
display: none; /* Hidden by default */ display: none; /* Hidden by default */
position: fixed; position: fixed;
top: 0; top: 0;
@ -502,7 +502,7 @@ button {
} }
/* Scoped styles for the dialog */ /* Scoped styles for the dialog */
#newFileDialog { #newFileDialog, #saveDialog {
display: none; /* Hidden by default */ display: none; /* Hidden by default */
position: fixed; position: fixed;
top: 50%; top: 50%;
@ -517,19 +517,19 @@ button {
z-index: 1000; /* Make sure it's in front of other elements */ z-index: 1000; /* Make sure it's in front of other elements */
} }
#newFileDialog .dialog-label { #newFileDialog .dialog-label, #saveDialog label {
display: block; display: block;
margin: 10px 0 5px; margin: 10px 0 5px;
} }
#newFileDialog .dialog-input { #newFileDialog .dialog-input, #saveDialog input {
width: 100%; width: 100%;
padding: 8px; padding: 8px;
margin: 5px 0; margin: 5px 0;
border: 1px solid #aaa; border: 1px solid #aaa;
} }
#newFileDialog .dialog-button { #newFileDialog .dialog-button, #saveDialog button {
width: 100%; width: 100%;
padding: 10px; padding: 10px;
margin-top: 10px; margin-top: 10px;
@ -632,11 +632,11 @@ button {
background-color: #0f0f0f69; background-color: #0f0f0f69;
} }
#newFileDialog { #newFileDialog, #saveDialog {
background-color: #444; background-color: #444;
border: 1px solid #333; border: 1px solid #333;
} }
#newFileDialog .dialog-input { #newFileDialog .dialog-input, #saveDialog input {
border: 1px solid #333; border: 1px solid #333;
} }
#recentFilesList li:hover { #recentFilesList li:hover {

View File

@ -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__ = { window.__TAURI__ = {
core: { core: {
invoke: () => {} invoke: () => {}
@ -184,8 +266,8 @@ if (!window.__TAURI__) {
input.click(); input.click();
}); });
}, },
save: async () => { save: async (params) => {
return prompt("Filename", "untitled.beam") return await promptForFilename(params.filters, params.defaultPath)
}, },
message: () => {}, message: () => {},
confirm: () => {}, confirm: () => {},