Przeglądaj źródła

Added web desktop upload indicator

TC pushbot 5 4 lat temu
rodzic
commit
ccc1167a35

+ 1 - 2
web/SystemAO/file_system/file_explorer.html

@@ -4236,8 +4236,7 @@
         function uploadFile(file, uuid=undefined, targetDir=undefined) {
             if (lowMemoryMode){
                  /*
-                    Low Memory Upload Mode (Experimental)
-                    (For host with less than 2GB RAM)
+                    Low Memory Upload Mode
                 */
                 var filename = encodeURIComponent(file.name);
                 var filesize = file.size;

+ 239 - 24
web/desktop.system

@@ -1023,6 +1023,9 @@
             focus: null
         };
 
+        //Upload related
+        let uploadFileChunkSize = 1024 * 512; //512KB per chunk in low memory upload
+
         //Others
         var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
         var daysNames = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
@@ -1030,15 +1033,17 @@
         var userInfo = {};
         var hardwareman = false;
         var downloadMode = false;
+        var lowMemoryMode = true;
         var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
-
+        var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
 
         //Initiation functions
         initDesktopTheme();
         initDesktopHostInfo();
         initDesktopUserInfo();
         initBackgroundSwitchingAnimation();
-        //initDesktopFiles();               //Will be called in initDesktopIconPreference() -> refresh()
+        //Commented for debug purpose
+        initUploadMode();
         initModuleList();
         initDesktopIconPreference()
         initUserDefinedThemeColor();
@@ -2884,6 +2889,7 @@
             let shortenedName = filename;
             screenX += iconOffsetXY[0];
             screenY += iconOffsetXY[1];
+            
             if (isDir) {
                 //Folder objects
                 icon = "folder outline";
@@ -3249,6 +3255,7 @@
                         let thisFilename = files[j].name;
                         let x = parseInt(locations[j][0]);
                         let y = parseInt(locations[j][1]);
+                        let uploadIconUUID = generateUploadingIcon(thisFile.name, [x,y]);
                         uploadFile(thisFile,function(){
                             console.log("Uploader callback");
                             $.ajax({
@@ -3257,10 +3264,10 @@
                                 data: {"set": thisFilename, "x": x, "y": y},
                                 success: function(data) {
                                     //Refresh the desktop
-                                    refresh(undefined, true);
+                                    refresh(undefined, false);
                                 }
                             });
-                        });
+                        }, uploadIconUUID);
                         
                     }
                 }else if (sourceFilelist.length > 0 && Array.isArray(sourceFilelist)){
@@ -3683,6 +3690,7 @@
             return targetLocation;
         }
 
+        //Convert location to grid index
         function getGridIndexFromLocation(x,y){
             var gridIndex = [-1,-1];
             for (var i = 0; i < desktopGrids.length; i++){
@@ -3702,6 +3710,38 @@
             return gridIndex;
         }
 
+        //Convert grid index to location
+        function getLocationFromGridIndex(x, y){
+            var location = [-1,-1];
+            
+            //Calculate the usable grid on screen
+            var iheight = 106;
+            var iwidth = 70;
+            var padding = 16;
+            if (desktopIconSize == "small") {
+                iheight = 82;
+                iwidth = 50;
+            } else if (desktopIconSize == "medium") {
+                iheight = 106;
+                iwidth = 70;
+            } else if (desktopIconSize == "big") {
+                iheight = 124;
+                iwidth = 84;
+            }
+
+            var screenHeight = window.innerHeight;
+            var screenWidth = window.innerWidth;
+
+            var vc = Math.floor((screenHeight - 20 - padding) / iheight);
+            var hc = Math.floor((screenWidth - padding) / iwidth);
+
+            //Calculate the position of this icon on the grid
+            var resultX = padding + iwidth * x + iconOffsetXY[0];
+            var resultY = padding + iheight * y + iconOffsetXY[1];
+
+            return [resultX, resultY];
+        }   
+
 
         //Set allow overshoot to allow drop point to get closest grid with x / y > cursor posx /y
         function findClosestGrid(x, y, allowOvershoot = true) {
@@ -5198,30 +5238,205 @@
            
         }
 
-        function uploadFile(file, callback=undefined) {
-            let url = 'system/file_system/upload'
-            let uploadCurrentPath = "user:/Desktop/";
-            let formData = new FormData();
-            let xhr = new XMLHttpRequest();
-            formData.append('file', file);
-            formData.append('path', uploadCurrentPath);
+        //Check if this server is a low memory one
+        function initUploadMode(){
+            $.ajax({
+                url: "system/info/getRAMinfo",
+                success: function(data){
+                    if (data.error !== undefined){
+                        //Permission denied or other reasons that cannot access harwdare info. Use default mode
+                        lowMemoryMode = true;
+                    }else{
+                        //Check if ramsize > 1.8 GB (2GB). If yes, switch to large memory upload mode
+                        var memsize = JSON.parse(data);
+                        if (parseFloat(memsize)/ 1024 / 1024 / 1024 >= 3.8){
+                            console.log("[Desktop] Setting upload mode to large memory mode")
+                            lowMemoryMode = false;
+                        }
+                    }
+                },
+                error: function(){
+                    //Hardware mode disabled. Always use low memory upload mode instead
+                    lowMemoryMode = true;
+                }
+            });
+        }
 
-            xhr.open('POST', url, true)
-            xhr.upload.addEventListener("progress", function(e) {
-                console.log((e.loaded * 100.0 / e.total) || 100)
-            })
+        //Generate a loading icon for this upload task
+        function generateUploadingIcon(filename, position){
+            //Get position for appending
+            var onScreenLocation = getLocationFromGridIndex(position[0], position[1]);
+            //Append to UI
+            var uploadIconUUID = Date.now();
+            $("#iconwrapper").append(`<div href="javascript:void(0);" class="${uploadIconUUID} launchIcon" type="dummy" filename="${filename}" filepath="user:/Desktop/${filename}"  style="width:70px; height:106px;left:${onScreenLocation[0]}px; top:${onScreenLocation[1]}px;">
+                <span class="launchIconWrapper">
+                    <img class="launchIconImage medium" src="img/desktop/files_icon/${desktopIconPack}/file upload.png" draggable="false">
+                    <p class="launchIconText ${desktopIconSize}" >Uploading</p>
+                    <div class="ts tiny primary progress" style="margin-top: -4px;">
+                        <div class="bar" style="min-width: 0px !important; width: 0%;"></div>
+                    </div>
+                </span>
+            </div>`);
+            return uploadIconUUID;
+        }
 
-            xhr.addEventListener('readystatechange', function(e) {
-                if (xhr.readyState == 4 && xhr.status == 200) {
-                    if (callback !== undefined){
-                        callback(e.target.response);
-                    }
+        function uploadFile(file, callback=undefined, uploadingIconUUID = undefined) {
+            if (lowMemoryMode){
+                /*
+                    Low Memory Upload Mode
+                */
+                var filename = encodeURIComponent(file.name);
+                var filesize = file.size;
+
+                //Open the websocket
+                let path = "user:/Desktop";
+                let protocol = "wss://";
+                if (location.protocol !== 'https:') {
+                    protocol = "ws://";
                 }
-                else if (xhr.readyState == 4 && xhr.status != 200) {
-                    console.log("Upload failed :" + xhr.status);
+
+                var port = window.location.port;
+                if (window.location.port == ""){
+                    port = "80";
                 }
-            })
-            xhr.send(formData);
+
+                let uploadDir = "user:/Desktop";
+    
+                //Fixing Firefox path issues on or above FF48.0
+                if (isFirefox && file.webkitRelativePath != ""){
+                    //Use the webkitRelativePath instead of the name, this is a folder upload
+                    let pathinfo = file.webkitRelativePath.split("/");
+                    pathinfo.pop();
+                    let subpath = pathinfo.join("/");
+                    uploadDir = uploadDir + subpath;
+                }
+
+                let socket = new WebSocket(protocol + window.location.hostname + ":" + port + "/system/file_system/lowmemUpload?filename=" + filename + "&path=" + uploadDir);
+                let currentSendingIndex = 0;
+                let chunks = Math.ceil(file.size/uploadFileChunkSize,uploadFileChunkSize);
+                
+                //Define a function for sending a particular chunk
+                function sendChunk(id, uploadingIconUUID){
+                    var offsetStart = id*uploadFileChunkSize;
+                    var offsetEnd = id*uploadFileChunkSize + uploadFileChunkSize;
+                    var thisblob = file.slice(offsetStart,offsetEnd);
+                    socket.send(thisblob);
+                    //console.log(id + "/" + chunks);
+
+                    //Update progress to first percentage
+                    var progress = id / (chunks-1) * 100.0;
+                    if (progress > 100){
+                        progress = 100;
+                    }
+
+
+                    if (uploadingIconUUID != undefined){
+                        //Update the progress on the object
+                        $("." + uploadingIconUUID + ".launchIcon").find(".bar").css("width", progress + "%");
+                        if (progress == 100){
+                            $("." + uploadingIconUUID + ".launchIcon").find(".progress").addClass("indeterminate");
+                        }
+                    }
+                 
+                }
+
+                //Start sending
+                socket.onopen = function(e) {
+                    if (filesize < uploadFileChunkSize){
+                        //This file is smaller than chunk size, set it to somwhere within 10% - 20% so it doesn't look like it is stuck
+                        
+                    }
+                    
+                    //Send the first chunk
+                    sendChunk(0, uploadingIconUUID);
+                    currentSendingIndex++;
+                };
+
+                socket.onmessage = function(event) {
+                    //Append to the send index
+                    var incomingValue = event.data;
+
+                    if (incomingValue == "next"){
+                        if (currentSendingIndex == chunks + 1){
+                            //Already finished
+                            socket.send("done");
+                        }else{
+                            //Send next chunk
+                            sendChunk(currentSendingIndex, uploadingIconUUID);
+                            currentSendingIndex++;
+                        }
+                      
+                    }else if (incomingValue == "OK"){
+                        //Merge completed
+                        
+                    }else{
+                        //Try to parse it as JSON
+                        try{
+                            var resp = JSON.parse(incomingValue.split('\\' + '"').join("\""));
+                            console.log(resp);
+                            if (resp.error !== undefined){
+                                //This is an error message
+                                sendNotification("Upload Failed", resp.error, "remove")
+
+                                //Update the progress bar to error
+                               
+                            }
+                        }catch(ex){
+                            //Something else
+                            console.log(incomingValue);
+                            console.log(ex);
+                        }
+                    }
+
+                };
+
+                socket.onclose = function(event) {
+                    if (callback != undefined){
+                        callback();
+                    }
+                };
+
+                socket.onerror = function(error) {
+                    console.log(error.message);
+                    console.log("[Desktop] Unable to open WebSocket connection. Fall back to FORM POST upload mode. (Check your nginx / reverse proxy settings!!!)")
+                    //Try to fallback to FORM POST upload mode
+                    lowMemoryMode = false;
+                    uploadFile(thisFile, callback)
+                    return
+                };
+            }else{
+                let url = 'system/file_system/upload'
+                let uploadCurrentPath = "user:/Desktop/";
+                let formData = new FormData();
+                let xhr = new XMLHttpRequest();
+                formData.append('file', file);
+                formData.append('path', uploadCurrentPath);
+
+                xhr.open('POST', url, true)
+                xhr.upload.addEventListener("progress", function(e) {
+                    console.log((e.loaded * 100.0 / e.total) || 100)
+                    var progress = (e.loaded * 100.0 / e.total) || 100;
+                    if (uploadingIconUUID != undefined){
+                        //Update the progress on the object
+                        $("." + uploadingIconUUID + ".launchIcon").find(".bar").css("width", progress + "%");
+                        if (progress == 100){
+                            $("." + uploadingIconUUID + ".launchIcon").find(".progress").addClass("indeterminate");
+                        }
+                    }
+                })
+
+                xhr.addEventListener('readystatechange', function(e) {
+                    if (xhr.readyState == 4 && xhr.status == 200) {
+                        if (callback !== undefined){
+                            callback(e.target.response);
+                        }
+                    }
+                    else if (xhr.readyState == 4 && xhr.status != 200) {
+                        console.log("Upload failed :" + xhr.status);
+                    }
+                })
+                xhr.send(formData);
+            }
         }
 
         function setStorage(key, value, callback = undefined) {

BIN
web/img/desktop/files_icon/default/file upload.png


BIN
web/img/desktop/files_icon/default/file upload.psd