diff --git a/src/UI/UIWindowProgress.js b/src/UI/UIWindowProgress.js new file mode 100644 index 000000000..85dc5da9f --- /dev/null +++ b/src/UI/UIWindowProgress.js @@ -0,0 +1,125 @@ +/** + * Copyright (C) 2024 Puter Technologies Inc. + * + * This file is part of Puter. + * + * Puter is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import UIWindow from './UIWindow.js' +import Placeholder from '../util/Placeholder.js'; +import Button from './Components/Button.js'; + +/** + * General purpose progress dialog. + * @param operation_id If provided, is saved in the data-operation-id attribute, for later lookup. + * @param show_progress Enable a progress bar, and display `(foo%)` after the status message + * @param on_cancel A callback run when the Cancel button is clicked. Without it, no Cancel button will appear. + * @returns {Promise<{set_progress: *, set_status: *, close: *, element: Element}>} Object for managing the progress dialog + * @constructor + * TODO: Error display + * TODO: Debouncing logic (show only after a delay, then hide only after a delay) + */ +async function UIWindowProgress({ + operation_id = null, + show_progress = false, + on_cancel = null, +} = {}){ + const placeholder_cancel_btn = Placeholder(); + + let h = ''; + h += `
`; + h += `
`; + // spinner + h += `circle anim`; + // Progress report + h += `
+ ${i18n('preparing')}`; + if (show_progress) { + h += ` (0%)`; + } + h += `
`; + h +=`
`; + if (show_progress) { + h += `
`; + h += `
`; + h += `
`; + } + if (on_cancel) { + h += `
`; + h += placeholder_cancel_btn.html; + h += `
`; + } + h += `
`; + + const el_window = await UIWindow({ + uid: null, + is_dir: false, + body_content: h, + has_head: false, + selectable_body: false, + draggable_body: true, + allow_context_menu: false, + is_resizable: false, + is_droppable: false, + init_center: true, + allow_native_ctxmenu: false, + allow_user_select: false, + window_class: 'window-progress', + width: 450, + dominant: true, + window_css:{ + height: 'initial', + }, + body_css: { + padding: '22px', + width: 'initial', + 'background-color': `hsla( + var(--primary-hue), + var(--primary-saturation), + var(--primary-lightness), + var(--primary-alpha))`, + 'backdrop-filter': 'blur(3px)', + } + }); + + if (on_cancel) { + const cancel_btn = new Button({ + label: i18n('cancel'), + style: 'small', + on_click: () => { + $(el_window).close(); + on_cancel(); + }, + }); + cancel_btn.attach(placeholder_cancel_btn); + } + + return { + element: el_window, + set_status: (text) => { + el_window.querySelector('.progress-msg').innerHTML = text; + }, + set_progress: (percent) => { + el_window.querySelector('.progress-bar').style.width = `${percent}%`; + el_window.querySelector('.progress-percent').innerText = `${percent}%`; + }, + close: () => { + $(el_window).close(); + }, + // TODO: show_error(), which replaces the window content with a title, error message, and OK button + }; +} + +export default UIWindowProgress; \ No newline at end of file diff --git a/src/css/style.css b/src/css/style.css index faa21aba9..69a19e30d 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -2708,17 +2708,19 @@ fieldset[name=number-code] { } } -.upload-progress-bar-container, .download-progress-bar-container { +.progress-bar-container, .upload-progress-bar-container, .download-progress-bar-container { + box-sizing: border-box; width: 100%; - height: 15px; + height: 17px; border: 1px solid rgb(40 109 157); + border-radius: 3px; background-color: white; box-shadow: inset -1px 3px 4px #dfdfdf; } -.upload-progress-bar, .download-progress-bar { +.progress-bar, .upload-progress-bar, .download-progress-bar { width: 0; - height: 15px; + height: 100%; background-color: rgb(0 137 255); transition: 0.4s width; background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.05)); @@ -3937,4 +3939,4 @@ fieldset[name=number-code] { .taskmgr-task-title { flex-grow: 1; padding-left: calc(2.5 * var(--scale)); -} \ No newline at end of file +}