diff --git a/src/IPC.js b/src/IPC.js index 8e9499df..a8439171 100644 --- a/src/IPC.js +++ b/src/IPC.js @@ -185,89 +185,45 @@ window.addEventListener('message', async (event) => { // setItem //-------------------------------------------------------- else if(event.data.msg === 'setItem' && event.data.key && event.data.value){ - // todo: validate key and value to avoid unnecessary api calls - return await $.ajax({ - url: window.api_origin + "/setItem", - type: 'POST', - data: JSON.stringify({ - app: app_uuid, - key: event.data.key, - value: event.data.value, - }), - async: true, - contentType: "application/json", - headers: { - "Authorization": "Bearer "+window.auth_token - }, - statusCode: { - 401: function () { - window.logout(); - }, - }, - success: function (fsentry){ - } + puter.kv.set({ + key: event.data.key, + value: event.data.value, + app: app_uuid, + }).then(() => { + // send confirmation to requester window + target_iframe.contentWindow.postMessage({ + original_msg_id: msg_id, + }, '*'); }) } //-------------------------------------------------------- // getItem //-------------------------------------------------------- else if(event.data.msg === 'getItem' && event.data.key){ - // todo: validate key to avoid unnecessary api calls - $.ajax({ - url: window.api_origin + "/getItem", - type: 'POST', - data: JSON.stringify({ - key: event.data.key, - app: app_uuid, - }), - async: true, - contentType: "application/json", - headers: { - "Authorization": "Bearer "+window.auth_token - }, - statusCode: { - 401: function () { - window.logout(); - }, - }, - success: function (result){ - // send confirmation to requester window - target_iframe.contentWindow.postMessage({ - original_msg_id: msg_id, - msg: 'getItemSucceeded', - value: result ? result.value : null, - }, '*'); - } + puter.kv.get({ + key: event.data.key, + app: app_uuid, + }).then((result) => { + // send confirmation to requester window + target_iframe.contentWindow.postMessage({ + original_msg_id: msg_id, + msg: 'getItemSucceeded', + value: result ?? null, + }, '*'); }) } //-------------------------------------------------------- // removeItem //-------------------------------------------------------- else if(event.data.msg === 'removeItem' && event.data.key){ - // todo: validate key to avoid unnecessary api calls - $.ajax({ - url: window.api_origin + "/removeItem", - type: 'POST', - data: JSON.stringify({ - key: event.data.key, - app: app_uuid, - }), - async: true, - contentType: "application/json", - headers: { - "Authorization": "Bearer "+window.auth_token - }, - statusCode: { - 401: function () { - window.logout(); - }, - }, - success: function (result){ - // send confirmation to requester window - target_iframe.contentWindow.postMessage({ - original_msg_id: msg_id, - }, '*'); - } + puter.kv.del({ + key: event.data.key, + app: app_uuid, + }).then(() => { + // send confirmation to requester window + target_iframe.contentWindow.postMessage({ + original_msg_id: msg_id, + }, '*'); }) } //-------------------------------------------------------- diff --git a/src/UI/UIDesktop.js b/src/UI/UIDesktop.js index f8ac7249..b8db345e 100644 --- a/src/UI/UIDesktop.js +++ b/src/UI/UIDesktop.js @@ -540,14 +540,11 @@ async function UIDesktop(options){ h += ``; // Get window sidebar width - window.getItem({ - key: "window_sidebar_width", - success: async function(res){ - let value = parseInt(res.value); - // if value is a valid number - if(!isNaN(value) && value > 0){ - window.window_sidebar_width = value; - } + puter.kv.get('window_sidebar_width').then(async (val) => { + let value = parseInt(val); + // if value is a valid number + if(!isNaN(value) && value > 0){ + window.window_sidebar_width = value; } }) @@ -1072,18 +1069,15 @@ async function UIDesktop(options){ // show referral notice window if(window.show_referral_notice && !window.user.email_confirmed){ - window.getItem({ - key: "shown_referral_notice", - success: async function(res){ - if(!res){ - setTimeout(() => { - UIWindowClaimReferral(); - }, 1000); - window.setItem({ - key: "shown_referral_notice", - value: true, - }) - } + puter.kv.get('shown_referral_notice').then(async (val) => { + if(!val || val === 'false' || val === false){ + setTimeout(() => { + UIWindowClaimReferral(); + }, 1000); + puter.kv.set({ + key: "shown_referral_notice", + value: true, + }) } }) } diff --git a/src/UI/UIWindow.js b/src/UI/UIWindow.js index dae15157..1952e67c 100644 --- a/src/UI/UIWindow.js +++ b/src/UI/UIWindow.js @@ -1776,7 +1776,7 @@ async function UIWindow(options) { $('.window').css('pointer-events', 'initial'); const new_width = $(el_window_sidebar).width(); // save new width in the cloud, to user's settings - window.setItem({key: "window_sidebar_width", value: new_width}); + puter.kv.set({key: "window_sidebar_width", value: new_width}); // save new width locally, to window object window.window_sidebar_width = new_width; } diff --git a/src/helpers.js b/src/helpers.js index 63dc08ef..10cc92f6 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -30,6 +30,7 @@ import content_type_to_icon from './helpers/content_type_to_icon.js'; import truncate_filename from './helpers/truncate_filename.js'; import UIWindowProgress from './UI/UIWindowProgress.js'; import launch_app from "./helpers/launch_app.js"; +import globToRegExp from "./helpers/globToRegExp.js"; window.is_auth = ()=>{ if(localStorage.getItem("auth_token") === null || window.auth_token === null) @@ -162,203 +163,6 @@ window.scrollParentToChild = (parent, child)=>{ } } -window.getItem = async function(options){ - return $.ajax({ - url: window.api_origin + "/getItem", - type: 'POST', - data: JSON.stringify({ - key: options.key, - app: options.app_uid, - }), - async: true, - contentType: "application/json", - headers: { - "Authorization": "Bearer "+window.auth_token - }, - statusCode: { - 401: function () { - window.logout(); - }, - }, - success: function (result){ - if(options.success && typeof(options.success) === "function") - options.success(result); - } - }) -} - -window.setItem = async function(options){ - return $.ajax({ - url: window.api_origin + "/setItem", - type: 'POST', - data: JSON.stringify({ - app: options.app_uid, - key: options.key, - value: options.value, - }), - async: true, - contentType: "application/json", - headers: { - "Authorization": "Bearer "+window.auth_token - }, - statusCode: { - 401: function () { - window.logout(); - }, - }, - success: function (fsentry){ - if(options.success && typeof(options.success) === "function") - options.success(fsentry) - } - }) -} - -/** - * Converts a glob pattern to a regular expression, with optional extended or globstar matching. - * - * @param {string} glob - The glob pattern to convert. - * @param {Object} [opts] - Optional options for the conversion. - * @param {boolean} [opts.extended=false] - If true, enables extended matching with single character matching, character ranges, group matching, etc. - * @param {boolean} [opts.globstar=false] - If true, uses globstar matching, where '*' matches zero or more path segments. - * @param {string} [opts.flags] - Regular expression flags to include (e.g., 'i' for case-insensitive). - * @returns {RegExp} The generated regular expression. - * @throws {TypeError} If the provided glob pattern is not a string. - */ -window.globToRegExp = function (glob, opts) { - if (typeof glob !== 'string') { - throw new TypeError('Expected a string'); - } - - var str = String(glob); - - // The regexp we are building, as a string. - var reStr = ""; - - // Whether we are matching so called "extended" globs (like bash) and should - // support single character matching, matching ranges of characters, group - // matching, etc. - var extended = opts ? !!opts.extended : false; - - // When globstar is _false_ (default), '/foo/*' is translated a regexp like - // '^\/foo\/.*$' which will match any string beginning with '/foo/' - // When globstar is _true_, '/foo/*' is translated to regexp like - // '^\/foo\/[^/]*$' which will match any string beginning with '/foo/' BUT - // which does not have a '/' to the right of it. - // E.g. with '/foo/*' these will match: '/foo/bar', '/foo/bar.txt' but - // these will not '/foo/bar/baz', '/foo/bar/baz.txt' - // Lastely, when globstar is _true_, '/foo/**' is equivelant to '/foo/*' when - // globstar is _false_ - var globstar = opts ? !!opts.globstar : false; - - // If we are doing extended matching, this boolean is true when we are inside - // a group (eg {*.html,*.js}), and false otherwise. - var inGroup = false; - - // RegExp flags (eg "i" ) to pass in to RegExp constructor. - var flags = opts && typeof (opts.flags) === "string" ? opts.flags : ""; - - var c; - for (var i = 0, len = str.length; i < len; i++) { - c = str[i]; - - switch (c) { - case "/": - case "$": - case "^": - case "+": - case ".": - case "(": - case ")": - case "=": - case "!": - case "|": - reStr += "\\" + c; - break; - - case "?": - if (extended) { - reStr += "."; - break; - } - // fallthrough - - case "[": - case "]": - if (extended) { - reStr += c; - break; - } - // fallthrough - - case "{": - if (extended) { - inGroup = true; - reStr += "("; - break; - } - // fallthrough - - case "}": - if (extended) { - inGroup = false; - reStr += ")"; - break; - } - // fallthrough - - case ",": - if (inGroup) { - reStr += "|"; - break; - } - reStr += "\\" + c; - break; - - case "*": - // Move over all consecutive "*"'s. - // Also store the previous and next characters - var prevChar = str[i - 1]; - var starCount = 1; - while (str[i + 1] === "*") { - starCount++; - i++; - } - var nextChar = str[i + 1]; - - if (!globstar) { - // globstar is disabled, so treat any number of "*" as one - reStr += ".*"; - } else { - // globstar is enabled, so determine if this is a globstar segment - var isGlobstar = starCount > 1 // multiple "*"'s - && (prevChar === "/" || prevChar === undefined) // from the start of the segment - && (nextChar === "/" || nextChar === undefined) // to the end of the segment - - if (isGlobstar) { - // it's a globstar, so match zero or more path segments - reStr += "((?:[^/]*(?:/|$))*)"; - i++; // move over the "/" - } else { - // it's not a globstar, so only match one path segment - reStr += "([^/]*)"; - } - } - break; - - default: - reStr += c; - } - } - - // When regexp 'g' flag is specified don't - // constrain the regular expression with ^ & $ - if (!flags || !~flags.indexOf('g')) { - reStr = "^" + reStr + "$"; - } - - return new RegExp(reStr, flags); -}; - /** * Validates the provided file system entry name. * @@ -488,7 +292,7 @@ window.check_fsentry_against_allowed_file_types_string =function (fsentry, allow } // MIME types (e.g. text/plain) - else if(window.globToRegExp(allowed_file_type).test(fsentry.type?.toLowerCase())){ + else if(globToRegExp(allowed_file_type).test(fsentry.type?.toLowerCase())){ passes_allowed_file_type_filter = true; break; } @@ -1014,64 +818,65 @@ window.item_icon = async (fsentry)=>{ */ window.show_save_account_notice_if_needed = function(message){ - window.getItem({ + puter.kv.get({ key: "save_account_notice_shown", - success: async function(value){ - if(!value && window.user?.is_temp){ - window.setItem({key: "save_account_notice_shown", value: true}); + }).then(async function(value){ + if(!value && window.user?.is_temp){ + puter.kv.set({ + key: "save_account_notice_shown", + value: true, + }); + // Show the notice + setTimeout(async () => { + const alert_resp = await UIAlert({ + message: message ?? `Congrats on storing data!
Don't forget to save your session! You are in a temporary session. Save session to avoid accidentally losing your work.
`, + body_icon: window.icons['reminder.svg'], + buttons:[ + { + label: i18n('save_session'), + value: 'save-session', + type: 'primary', + }, + // { + // label: 'Log into an existing account', + // value: 'login', + // }, + { + label: `I'll do it later`, + value: 'remind-later', + }, + ], + window_options: { + backdrop: true, + close_on_backdrop_click: false, + } + + }) + + if(alert_resp === 'remind-later'){ + // TODO + } + if(alert_resp === 'save-session'){ + let saved = await UIWindowSaveAccount({ + send_confirmation_code: false, + }); - // Show the notice - setTimeout(async () => { - const alert_resp = await UIAlert({ - message: message ?? `Congrats on storing data!Don't forget to save your session! You are in a temporary session. Save session to avoid accidentally losing your work.
`, - body_icon: window.icons['reminder.svg'], - buttons:[ - { - label: i18n('save_session'), - value: 'save-session', - type: 'primary', - }, - // { - // label: 'Log into an existing account', - // value: 'login', - // }, - { - label: `I'll do it later`, - value: 'remind-later', - }, - ], + }else if (alert_resp === 'login'){ + let login_result = await UIWindowLogin({ + show_signup_button: false, + reload_on_success: true, + send_confirmation_code: false, window_options: { + show_in_taskbar: false, backdrop: true, close_on_backdrop_click: false, } - - }) - - if(alert_resp === 'remind-later'){ - // TODO - } - if(alert_resp === 'save-session'){ - let saved = await UIWindowSaveAccount({ - send_confirmation_code: false, - }); - - }else if (alert_resp === 'login'){ - let login_result = await UIWindowLogin({ - show_signup_button: false, - reload_on_success: true, - send_confirmation_code: false, - window_options: { - show_in_taskbar: false, - backdrop: true, - close_on_backdrop_click: false, - } - }); - // FIXME: Report login error. - } - }, window.desktop_loading_fade_delay + 1000); - } + }); + // FIXME: Report login error. + } + }, window.desktop_loading_fade_delay + 1000); } - }) + }); } window.onpopstate = (event) => { diff --git a/src/helpers/globToRegExp.js b/src/helpers/globToRegExp.js new file mode 100644 index 00000000..d58be6d6 --- /dev/null +++ b/src/helpers/globToRegExp.js @@ -0,0 +1,174 @@ +/** + * 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