فهرست منبع

Refactor to use KV exclusively

Nariman Jelveh 11 ماه پیش
والد
کامیت
21c537fe22
5فایلهای تغییر یافته به همراه270 افزوده شده و 341 حذف شده
  1. 27 71
      src/IPC.js
  2. 14 20
      src/UI/UIDesktop.js
  3. 1 1
      src/UI/UIWindow.js
  4. 54 249
      src/helpers.js
  5. 174 0
      src/helpers/globToRegExp.js

+ 27 - 71
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,
+            }, '*');
         })
     }
     //--------------------------------------------------------

+ 14 - 20
src/UI/UIDesktop.js

@@ -540,14 +540,11 @@ async function UIDesktop(options){
     h += `</div>`;
 
     // 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,
+                })
             }
         })
     }

+ 1 - 1
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;
         }

+ 54 - 249
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 ?? `<strong>Congrats on storing data!</strong><p>Don't forget to save your session! You are in a temporary session. Save session to avoid accidentally losing your work.</p>`,
+                    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 ?? `<strong>Congrats on storing data!</strong><p>Don't forget to save your session! You are in a temporary session. Save session to avoid accidentally losing your work.</p>`,
-                        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) => {

+ 174 - 0
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 <https://www.gnu.org/licenses/>.
+ */
+
+/* globToRegExp is derived from: https://github.com/fitzgen/glob-to-regexp
+ *
+ * Copyright (c) 2013, Nick Fitzgerald All rights reserved.
+ * See full license text here: https://github.com/fitzgen/glob-to-regexp#license
+ */
+
+
+/**
+ * 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.
+ */
+const 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);
+};
+  
+
+export default globToRegExp;