瀏覽代碼

Fixed desktop file share icon and context menu darktheme mode bug

Toby Chui 1 年之前
父節點
當前提交
dbcc5d8fb2
共有 4 個文件被更改,包括 805 次插入790 次删除
  1. 1 1
      desktop.go
  2. 641 646
      web/SystemAO/file_system/file_share.html
  3. 22 0
      web/script/ao.css
  4. 141 143
      web/script/contextmenu.css

+ 1 - 1
desktop.go

@@ -286,7 +286,7 @@ func desktop_listFiles(w http.ResponseWriter, r *http.Request) {
 		thisFileObject.IsShortcut = isShortcut
 
 		//Check if this file is shared
-		thisFileObject.IsShared = shareManager.FileIsShared(userinfo, this)
+		thisFileObject.IsShared = shareManager.FileIsShared(userinfo, thisFileObject.Filepath)
 		//Check the file location
 		username, _ := authAgent.GetUserName(w, r)
 		x, y, _ := getDesktopLocatioFromPath(thisFileObject.Filename, username)

+ 641 - 646
web/SystemAO/file_system/file_share.html

@@ -1,647 +1,642 @@
-<html>
-    <head>
-        <title locale="title/title">File Share</title>
-        <link rel="stylesheet" href="../../script/semantic/semantic.min.css">
-        <script src="../../script/jquery.min.js"></script>
-        <script src="../../script/semantic/semantic.min.js"></script>
-        <script src="../../script/ao_module.js"></script>
-        <script type="text/javascript" src="../../script/applocale.js"></script>
-        <script type="text/javascript" src="../../script/qrcode.min.js"></script>
-        <meta charset="UTF-8">
-        <meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
-        <style>
-            body:not(.darkTheme){
-                background: rgba(255,255,255,01) !important;
-            }
-
-            body.darkTheme{
-                background-color: #242330 !important;
-            }
-
-            .sub.header.darkTheme{
-                color: rgba(255, 255, 255, 0.623) !important;
-            }
-
-            .darkTheme:not(a){
-                color: #eeeeee;
-            }
-
-            .yellow.message.darkTheme{
-                box-shadow: none !important;
-                border: 0px solid transparent !important;
-                background-color: #5e550e !important;
-            }
-
-            .dropDown.darkTheme:not(.icon){
-                background-color: #413f57 !important;
-                border: 1px solid white;
-            }
-
-            .dropdown.darkThem  .ui.label{
-                color: rgb(175, 175, 175);
-                background-color: #2f2d3d !important;
-            }
-
-            .dropdown.darkThem  .ui.label:hover{
-                color: white;
-                opacity: 0.8;
-            }
-
-
-        </style>
-    </head>
-    <body>
-        <div id="main" class="ui stackable grid">
-            <div class="eight wide column">
-                <div style="width: 100%;" class="qrcode" align="center">
-                    <div style="display: block; margin-left: auto; margin-right: auto;" align="center">
-                        <div id="qrcode" style="border: 10px solid white; background-color: white;">
-                            <h1><br><i class="ui loading spinner icon"></i><br></h1>
-                        </div>
-                    </div>
-                    <div style="width: 80%; text-align: center;">
-                    <a id="sharelink" href="" target="_blank" style="margin-top:8px; font-size: 120%; padding-left: 20px; padding-right: 20px; word-break: break-all; overflow-wrap: anywhere;"></a>
-                    </div>
-                    
-                </div>
-            </div>
-            <div id="shareSettingOptions" class="eight wide column" style="padding-left: 12px; display:none;">
-                <div class="ui header whiteTheme">
-                    <span locale="share/setting/title">Share Settings</span>
-                    <div class="sub header whiteTheme" locale="share/setting/subtitle">Change who can see this file</div>
-                </div>
-                <div id="shareSettingForm" class="ui form">
-                    <div class="field">
-                        <label><p class="whiteTheme" locale="share/setting/options">Visable options:</p></label>
-                        <div class="ui checkboxes">
-                            <div class="ui radio checkbox">
-                                <input id="anyone" type="radio" class="shareoption" name="shareopt" value="anyone" onchange="updateSharePermission(this);">
-                                <label for="anyone">
-                                    <div class="ui header">
-                                        <div class="content whiteTheme">
-                                            <i class="globe icon"></i> <span locale="share/setting/anyoneWithLink">Anyone with the link</span>
-                                            <div class="sub header whiteTheme" locale="share/setting/anyoneWithLink/desc">Anyone who has the link can access this file</div>
-                                        </div>
-                                    </div>
-                                </label>
-                            </div>
-                            <br><br>
-                            <div class="ui radio checkbox">
-                                <input id="signedin" type="radio" class="shareoption" value="signedin" name="shareopt" onchange="updateSharePermission(this);">
-                                <label for="signedin">
-                                    <div class="ui header">
-                                        <div class="content whiteTheme">
-                                            <i class="user circle outline icon"></i> <span locale="share/setting/anyoneSignedIn">Anyone signed in</span>
-                                            <div class="sub header whiteTheme" locale="share/setting/anyoneSignedIn/desc">Anyone who has signed in can access this file</div>
-                                        </div>
-                                    </div>
-                                </label>
-                            </div>
-                            <br><br>
-                            <div class="ui radio checkbox">
-                                <input id="samegroup" type="radio" class="shareoption" value="samegroup" name="shareopt" onchange="updateSharePermission(this);">
-                                <label for="samegroup">
-                                    <div class="ui header">
-                                        <div class="content whiteTheme">
-                                            <i class="users icon"></i> <span locale="share/setting/sameGroup">Users in the same group</span>
-                                            <div class="sub header whiteTheme" locale="share/setting/sameGroup/desc">Anyone who is in the same group as you do</div>
-                                        </div>
-                                    </div>
-                                </label>
-                            </div>
-                            <br><br>
-                            <div class="ui accordion" id="advanceShare">
-                                <div class="title">
-                                    <i class="dropdown icon"></i>
-                                    <span locale="share/setting/advance/title">Advance Share Options</span>
-                                </div>
-                                <div class="content">
-                                    <div class="ui radio checkbox">
-                                        <input id="users" type="radio" class="shareoption" value="users" name="shareopt" onchange="updateSharePermission(this);">
-                                        <label for="users">
-                                            <div class="ui header">
-                                                <div class="content whiteTheme">
-                                                    <i class="clipboard check icon"></i> <span locale="share/setting/advance/users">Selected Users</span>
-                                                    <div class="sub header whiteTheme" locale="share/setting/advance/usersDesc">Selected users with matching user name</div>
-                                                </div>
-                                            </div>
-                                        </label>
-                                    </div>
-                                    <div id="userselector">
-                                        <p style="margin-top: 1em;" locale="share/setting/advance/usersInstruct"">Select target users from the list below</p>
-                                        <select id="targetUsersList" class="ui fluid search dropdown" multiple="">
-                                            <option value="">Users</option>
-                                        </select>
-                                        <div id="noUserWarning" class="ui yellow message"  style="display:none;">
-                                            <i class="caret up icon"></i> <span locale="share/setting/advance/addUserToSave">Add at least one target share user to save changes</span>
-                                        </div>
-                                    </div>
-                                    <div class="ui radio checkbox" style="margin-top: 1em;">
-                                        <input id="groups" type="radio" class="shareoption" value="groups" name="shareopt" onchange="updateSharePermission(this);">
-                                        <label for="groups">
-                                            <div class="ui header">
-                                                <div class="content whiteTheme">
-                                                    <i class="sitemap icon"></i> <span locale="share/setting/advance/groups">Selected Groups</span>
-                                                    <div class="sub header whiteTheme" locale="share/setting/advance/groupsDesc">All the users that has access to any one of the selected group(s)</div>
-                                                </div>
-                                            </div>
-                                        </label>
-                                    </div>
-                                    <div id="groupselector">
-                                        <p style="margin-top: 1em;" locale="share/setting/advance/groupsInstruct">Select target groups from the list below</p>
-                                        <select id="targetGroupList" class="ui fluid search dropdown" multiple="">
-                                            <option value="">Groups</option>
-                                        </select>
-                                        <div id="noGroupWarning" class="ui yellow message" style="display:none;">
-                                            <i class="caret up icon"></i> <span locale="share/setting/advance/addGroupToSave">Add at least one target share group to save changes</span>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
-                        <br><br>
-                        <div id="udpateNotification" style="display:none; position: fixed; bottom: 1em; right: 1em;" class="ui green inverted segment">
-                                <i class=" checkmark icon"></i> <span locale="share/setting/updated">Share Setting Updated</span>
-                        </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-        <div class="ui divider actionButton"></div>
-        <div class="actionButton" style="width: 100%; padding-right: 12px;" align="right">
-            <div class="ui button popupbuttons whiteTheme allowHover" onclick="copyLinkToClipboard(this)">
-                <i class="copy icon"></i> <span locale="button/copy">Copy</span>
-            </div> 
-            <div id="sharingRemoveBtn" class="ui red button popupbuttons negative whiteTheme allowHover" onclick="removeSharing()">
-                <i class="remove icon"></i> <span locale="button/remove">Remove</span>
-            </div> 
-        </div>
-        <script>
-            /*
-                Usage: Pass in file descriptor to start share a file
-                var fd = encodeURIComponent(JSON.stringify({
-                        filename: "test.txt",
-                        filepath: "user:/Desktop/test.txt"
-                    })
-                );
-                window.open("file_share.html#" + fd);
-                
-                If you want to preset a file sharing mode (aka your module handle the share mode picking),
-                Pass in with the "shareMode" paramter. Example fd as follow:
-                {
-                    filename: "test.txt",
-                    filepath: "user:/Desktop/test.txt",
-                    shareMode: "signedin"
-                }
-
-                To remove a share, pass in "remove" for the share mode
-                Supported Share Mode keywords {anyone/signedin/samegroup/remove}
-
-                Other supported flags
-                {
-                    QRCode: {true/false} //Show or Hide the QR Code and link
-                    ActionButtons: {true/false} //Show or Hide the action button on the bottom
-                }
-
-            */
-            var shareCurrentEditingUUID = "";
-            var shareingFileData = {};
-            var darkTheme = false;
-            var initialized = false;
-            var fileSharingURL = "";
-            var relpath = "../../";
-            
-            function applyDarkThemeMode(){
-                $(".whiteTheme").removeClass("whiteTheme").addClass("darkTheme");
-                $("*:not(button)").addClass("darkTheme");
-                $("body").addClass("darkTheme");
-                $(".ui.button").addClass("inverted");
-                darkTheme = true;
-            }
-
-            function removeQRCodeInDarkTheme(){
-                if (darkTheme){
-                    $("#qrcode").css({
-                        "border":"0px solid transparent",
-                        "background-color":"#242330",
-                    })
-                }
-            }
-
-            if ($(parent) && $(parent.document).find("body").hasClass("darkTheme")){
-                //Switch to darkTheme mode immediately
-                applyDarkThemeMode();
-            }   
-
-            PageReady();
-            function PageReady(){
-                if (initialized){
-                    return;
-                }
-
-                //Load User & Group List
-                $.get(relpath + "../system/users/list", function(data){
-                    var groups = {};
-                    $("#targetUsersList").html(`<option value="">Users</option>`);
-                    data.forEach(user => {
-                        $("#targetUsersList").append(`<option value="${user[0]}">${user[0]}</option>`);
-                        var userGroups = user[1];
-                        userGroups.forEach(thisGroup => {
-                            groups[thisGroup] = true;
-                        });
-                    });
-                    $("#targetGroupList").html(`<option value="">Groups</option>`);
-                    for (var [key, value] of Object.entries(groups)) {
-                        $("#targetGroupList").append(`<option value="${key}">${key}</option>`);
-                    }
-
-                    //Initiate the share details
-                    initFileDetails(shareingFileData, function(shareUUID){
-                        //Set the mode of share if it is defined
-                        if (shareingFileData.shareMode !== undefined && shareingFileData.shareMode == "remove"){
-                            //Remove the share UUID
-                            removeSharing();
-                            return;
-                        }
-                        if (shareingFileData.shareMode !== undefined){
-                            //As the share mode is defined by the caller, hide the setting interface
-                            $("#shareSettingOptions").hide();
-                            $("#sharelink").parent().css({
-                                "width": "100%",
-                                "text-align": "left",
-                            });
-                            $.ajax({
-                                url: relpath + "../system/file_system/share/edit",
-                                data: {uuid: shareCurrentEditingUUID, mode: shareingFileData.shareMode},
-                                success: function(data){
-                                    if (data.error !== undefined){
-                                        alert(data.error);
-                                        return;
-                                    }
-                                    
-                                    //Update the checkbox
-                                    $(".shareoption").each(function(){
-                                        if ($(this)[0].value != shareingFileData.shareMode){
-                                            $(this)[0].checked = false;
-                                        }else{
-                                            $(this)[0].checked = true;
-                                        }
-                                    
-                                    });
-                                }
-                            });
-                        }else{
-                            //Default: show the setting to allow user adjustment
-                            $("#main").css({
-                                "margin-top":"0em",
-                                "padding": "4px"
-                            });
-                            $("#shareSettingOptions").show();
-                        }
-
-                        $(".accordion").accordion();
-                    });
-                });
-
-                //Load theme style
-                $.get(relpath + "../system/file_system/preference?key=file_explorer/theme",function(data){
-                    if (data == "darkTheme"){
-                        applyDarkThemeMode();
-                    }
-                });
-
-
-
-                initialized = true;
-                //Do localization
-                applocale.init(relpath + "../SystemAO/locale/file_share.json", function(){
-                    applocale.translate();
-                });
-
-                $(".checkbox").checkbox();
-                $(".dropdown").dropdown();
-                var inputFile = ao_module_loadInputFiles();
-                if (inputFile == null){
-                    //No file selected
-                    $(".shareoption").parent().addClass("disabled");
-                    $("#qrcode").html(`<h1>No File</h1>`);
-                    $("#sharelink").text(``);
-                    $("#sharingRemoveBtn").addClass("disabled");
-                    return
-                }
-
-
-                //Make sure one file is choicen each time
-                inputFile = inputFile[0]; 
-                console.log("inputFile", inputFile);
-                shareingFileData = inputFile;
-
-                //Filter out the nessary display flags
-                if (shareingFileData.QRCode !== undefined && shareingFileData.QRCode == false){
-                    $(".qrcode").hide();
-                    $("#shareSettingOptions").attr("class", "sixteen wide column");
-                    $("#shareSettingOptions").css("padding", "1em");
-                    $(".eight.wide").hide();
-                }
-
-                if (shareingFileData.ActionButtons !== undefined && shareingFileData.ActionButtons == false){
-                    $(".actionButton").hide();
-                }
-            }
-
-            function initFileDetails(shareingFileData, callback=undefined){
-                $.ajax({
-                    url: relpath + "../system/file_system/share/new",
-                    data: {path: shareingFileData.filepath},
-                    success: function(data){
-                        if (data.error !== undefined){
-                            alert(data.error);
-                        }else{
-                            console.log(data);
-                            updateShareLinkInfo(data.UUID);
-                            shareCurrentEditingUUID = data.UUID;
-                            $(".shareoption").each(function(){
-                                if ($(this)[0].value != data.Permission){
-                                    $(this)[0].checked = false;
-                                }else{
-                                    $(this)[0].checked = true;
-                                    if (data.Permission == "users"){
-                                        $("#advanceShare").accordion("open", 0);
-                                        $("#targetUsersList").dropdown("set selected", data.Accessibles);
-                                        $("#targetUsersList").parent().removeClass("disabled");
-                                        $("#targetGroupList").parent().addClass("disabled");
-                                    }else if (data.Permission == "groups"){
-                                        $("#advanceShare").accordion("open", 0);
-                                        $("#targetGroupList").dropdown("set selected", data.Accessibles);
-                                        $("#targetUsersList").parent().addClass("disabled");
-                                        $("#targetGroupList").parent().removeClass("disabled");
-                                    }else{
-                                        $("#targetGroupList").parent().addClass("disabled");
-                                        $("#targetUsersList").parent().addClass("disabled");
-                                    }
-                                }
-                               
-                            });
-
-                          
-                            $("#targetUsersList").on("change", function(evt){
-                                updateSharePermissionByType("users");
-                            });
-
-                            $("#targetGroupList").on("change", function(evt){
-                                updateSharePermissionByType("groups");
-                            });
-               
-                            
-
-                            //If the file is from desktop, set share icon
-                            if (ao_module_virtualDesktop == true){
-                                var fileDir = shareingFileData.filepath.split("/");
-                                fileDir.pop();
-                                fileDir = fileDir.join("/");
-                                if (fileDir == "user:/Desktop"){
-                                    //Remove share icon
-                                    parent.setFileShareIndicator(shareingFileData.filename);
-                                }
-                            }
-
-                            if (callback != undefined){
-                                callback(data.UUID)
-                            }
-                        }
-                    }
-                });
-            }
-
-            function removeSharing(){
-                if (shareCurrentEditingUUID == ""){
-                    return
-                }
-
-                //The target file to remove
-                $.ajax({
-                    url: relpath + "../system/file_system/share/delete",
-                    data: {uuid: shareCurrentEditingUUID},
-                    success: function(data){
-                        if (data.error !== undefined){
-                            alert(data.error);
-                        }else{
-                            //Removed!
-                            $(".button").addClass('disabled');
-                            $(".checkbox").addClass("disabled");
-                            $("#sharelink").text("");
-                            $("#sharelink").attr("href", "#");
-                            $("#qrcode").html(`<br><br><h1><i class="green checkmark icon"></i> ${applocale.getString("message/removed", "Share Removed")}</h1>`);
-                            removeQRCodeInDarkTheme();
-                            //If the file is located on desktop and it is web desktop mode
-                            if (ao_module_virtualDesktop == true){
-                                var fileDir = shareingFileData.filepath.split("/");
-                                fileDir.pop();
-                                fileDir = fileDir.join("/");
-                                if (fileDir == "user:/Desktop"){
-                                    //Remove share icon
-                                    parent.removeFileShareIndicator(shareingFileData.filename);
-                                }
-                            }
-                        }
-                    }
-                });
-            }
-
-            function updateSharePermission(object){
-                var newPermission = $(object).attr('value');
-                updateSharePermissionByType(newPermission);
-            }   
-
-            function updateSharePermissionByType(newPermission){
-                if (newPermission == "users"){
-                    //Build the user list
-                    $("#targetUsersList").parent().removeClass("disabled");
-                    $("#targetGroupList").parent().addClass("disabled");
-                    var selectedUsers = $("#targetUsersList").val();
-                    $("#noGroupWarning").slideUp("fast");
-                    if (selectedUsers.length == 0){
-                        //Show tips message
-                        $("#noUserWarning").slideDown("fast");
-                        return;
-                    }else{
-                        $("#noUserWarning").slideUp("fast");
-                    }
-                    //Rewrite it to permission handling description
-                    newPermission = "users:" + selectedUsers.join(",");
-                }else if (newPermission == "groups"){
-                    //Build the group list
-                    $("#targetUsersList").parent().addClass("disabled");
-                    $("#targetGroupList").parent().removeClass("disabled");
-                    var selectedGroups = $("#targetGroupList").val();
-                    $("#noUserWarning").slideUp("fast");
-                    if (selectedGroups.length == 0){
-                        //Show tips message
-                        $("#noGroupWarning").slideDown("fast");
-                        return;
-                    }else{
-                        $("#noGroupWarning").slideUp("fast");
-                    }
-                    //Rewrite it to permission handling description
-                    newPermission = "groups:" + selectedGroups.join(",");
-                }
-
-                $.ajax({
-                    url: relpath + "../system/file_system/share/edit",
-                    data: {uuid: shareCurrentEditingUUID, mode: newPermission},
-                    success: function(data){
-                        if (data.error !== undefined){
-                            alert(data.error);
-                            return;
-                        }
-                        $("#udpateNotification").stop().finish().fadeIn("fast").delay(3000).fadeOut("fast");
-                    }
-                });
-            }
-
-            function updateShareLinkInfo(uuid){
-                $("#qrcode").html("");
-                let protocol = "https://";
-                if (location.protocol !== 'https:') {
-                    protocol = "http://";
-                }
-
-                var port = ":" + window.location.port;
-                if (window.location.port == ""){
-                    port = "";
-                }
-                var shareURL = protocol + window.location.hostname + port + "/share/" + uuid;
-                shareCurrentEditingUUID = uuid;
-                fileSharingURL = shareURL;
-                new QRCode(document.getElementById("qrcode"), shareURL);
-                $("#sharelink").text(shareURL);
-                $("#sharelink").attr("href", shareURL)
-            }
-
-            /*
-                Dynamic Script Loader
-
-                This is a really experimental implementation of importing a script from anywhere
-                under the ArozOS web root. This section of code must be written in plain JS to make sure
-                it works without jQuery and other libraries.
-
-                This function try to load jQuery and ao_module from the script folder.
-                Also loading the semantic js and the css main body
-            */
-           /*
-            //The possible location for desktop.system, standard webapp module, SystemAO interfaces and iui sub-interfaces
-            let possibleLocations = ["script/", "../script/", "../../script/", "../../../script/"];
-            let loopCount = Math.min(possibleLocations.length, JSON.parse(JSON.stringify(window.location.toString())).split("/").length - 3);
-            function tryLoad(relpath, filename, successCallback=undefined){
-                var request = new XMLHttpRequest();  
-                request.open('GET', relpath + filename, true);
-                request.onreadystatechange = function(){
-                    if (request.readyState === 4){
-                        if (request.status == 200 || request.status == 304) {  
-                            if (typeof(successCallback) != "undefined"){
-                                successCallback(relpath, filename);
-                            }
-                        }
-                    }
-                };
-                request.send();
-            }
-
-            function injectOtherJavaScriptLibrary(relpath){
-                //Check if ao_module is loaded
-                if (typeof(ao_module_virtualDesktop) == "undefined"){
-                    var script = document.createElement('script');
-                    script.setAttribute('src', relpath + "ao_module.js");
-                    document.getElementsByTagName('head')[0].appendChild(script);
-                }else{
-                    //This routine already run
-                    return;
-                }
-
-                //Inject QR Code library
-                var script = document.createElement('script');
-                script.setAttribute('src', relpath + "qrcode.min.js");
-                document.getElementsByTagName('head')[0].appendChild(script);
-
-                //Inject applocale
-                script = document.createElement('script');
-                script.setAttribute('src', relpath + "applocale.js");
-                document.getElementsByTagName('head')[0].appendChild(script);
-
-                //Inject semmantic css and js anyway
-                var head  = document.getElementsByTagName('head')[0];
-                var link  = document.createElement('link');
-                link.id   = "semantic";
-                link.rel  = 'stylesheet';
-                link.type = 'text/css';
-                link.href = relpath + 'semantic/semantic.min.css';
-                link.media = 'all';
-                head.appendChild(link);
-
-                var script = document.createElement('script');
-                script.setAttribute('src', relpath + "semantic/semantic.min.js");
-                document.getElementsByTagName('head')[0].appendChild(script);
-
-                setTimeout(function(){
-                    PageReady();
-                }, 1000);
-            }
-
-            //Load jQuery first
-            if (typeof(window.jQuery) == "undefined"){
-                //jQuery not found. Load it
-                for (var i = 0; i < loopCount; i++){
-                    var relpath = possibleLocations[i];
-                    tryLoad(relpath, "jquery.min.js", function(relpath, filename){
-                        //Generate the jquery script element
-                        var script = document.createElement('script');
-                        
-                        script.setAttribute('src', relpath + filename);
-                        document.getElementsByTagName('head')[0].appendChild(script);
-                        
-                        doAfterJqueryLoaded(function(){
-                            injectOtherJavaScriptLibrary(relpath);
-                        });
-                        
-                    });
-                }
-            }else{
-                //jQuery exists. Load ao_module
-                injectOtherJavaScriptLibrary();
-            }
-
-            function doAfterJqueryLoaded(callback){
-                setTimeout(function(){
-                    //Wait until it is loaded
-                    if (typeof(window.jQuery) == "undefined"){
-                        doAfterJqueryLoaded(callback);
-                        return
-                    }else{
-                        callback();
-                    }
-                }), 300;
-            }
-            */
-
-            function copyLinkToClipboard(btn){
-                //Copy text
-                const area = document.createElement('textarea');
-                document.body.appendChild(area);
-
-                area.value = fileSharingURL;
-                area.select();
-                document.execCommand('copy');
-
-                document.body.removeChild(area);
-
-                //Do visual feedback
-                let oldContent = $(btn).html();
-                $(btn).html(`<i class="green checkmark icon"></i> ${applocale.getString("button/copied","Copied!")}`);
-                setTimeout(function(){
-                    $(btn).html(oldContent);
-                }, 3000);
-            }
-
-        </script>
-    </body>
+<html>
+    <head>
+        <title locale="title/title">File Share</title>
+        <link rel="stylesheet" href="../../script/semantic/semantic.min.css">
+        <link rel="stylesheet" href="../../script/ao.css">
+        <script src="../../script/jquery.min.js"></script>
+        <script src="../../script/semantic/semantic.min.js"></script>
+        <script src="../../script/ao_module.js"></script>
+        <script type="text/javascript" src="../../script/applocale.js"></script>
+        <script type="text/javascript" src="../../script/qrcode.min.js"></script>
+        <meta charset="UTF-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
+        <style>
+            body{
+                background: var(--body_background) !important;
+            }
+
+            .sub.header.darkTheme{
+                color: rgba(255, 255, 255, 0.623) !important;
+            }
+
+            .darkTheme:not(a){
+                color: #eeeeee;
+            }
+
+            .yellow.message.darkTheme{
+                box-shadow: none !important;
+                border: 0px solid transparent !important;
+                background-color: #5e550e !important;
+            }
+
+            .dropDown.darkTheme:not(.icon){
+                background-color: #413f57 !important;
+                border: 1px solid white;
+            }
+
+            .dropdown.darkThem  .ui.label{
+                color: rgb(175, 175, 175);
+                background-color: #2f2d3d !important;
+            }
+
+            .dropdown.darkThem  .ui.label:hover{
+                color: white;
+                opacity: 0.8;
+            }
+
+
+        </style>
+    </head>
+    <body>
+        <div id="main" class="ui stackable grid">
+            <div class="eight wide column">
+                <div style="width: 100%;" class="qrcode" align="center">
+                    <div style="display: block; margin-left: auto; margin-right: auto;" align="center">
+                        <div id="qrcode" style="border: 10px solid white; background-color: white;">
+                            <h1><br><i class="ui loading spinner icon"></i><br></h1>
+                        </div>
+                    </div>
+                    <div style="width: 80%; text-align: center; margin-top:0.4em; ">
+                    <a id="sharelink" href="" target="_blank" style="font-size: 120%; padding-left: 20px; padding-right: 20px; word-break: break-all; overflow-wrap: anywhere;"></a>
+                    </div>
+                    
+                </div>
+            </div>
+            <div id="shareSettingOptions" class="eight wide column" style="padding-left: 12px; display:none;">
+                <div class="ui header">
+                    <span locale="share/setting/title">Share Settings</span>
+                    <div class="sub header" locale="share/setting/subtitle">Change who can see this file</div>
+                </div>
+                <div id="shareSettingForm" class="ui form">
+                    <div class="field">
+                        <label><p class="" locale="share/setting/options">Visable options:</p></label>
+                        <div class="ui checkboxes">
+                            <div class="ui radio checkbox">
+                                <input id="anyone" type="radio" class="shareoption" name="shareopt" value="anyone" onchange="updateSharePermission(this);">
+                                <label for="anyone">
+                                    <div class="ui header">
+                                        <div class="content ">
+                                            <i class="globe icon"></i> <span locale="share/setting/anyoneWithLink">Anyone with the link</span>
+                                            <div class="sub header" locale="share/setting/anyoneWithLink/desc">Anyone who has the link can access this file</div>
+                                        </div>
+                                    </div>
+                                </label>
+                            </div>
+                            <br><br>
+                            <div class="ui radio checkbox">
+                                <input id="signedin" type="radio" class="shareoption" value="signedin" name="shareopt" onchange="updateSharePermission(this);">
+                                <label for="signedin">
+                                    <div class="ui header">
+                                        <div class="content">
+                                            <i class="user circle outline icon"></i> <span locale="share/setting/anyoneSignedIn">Anyone signed in</span>
+                                            <div class="sub header" locale="share/setting/anyoneSignedIn/desc">Anyone who has signed in can access this file</div>
+                                        </div>
+                                    </div>
+                                </label>
+                            </div>
+                            <br><br>
+                            <div class="ui radio checkbox">
+                                <input id="samegroup" type="radio" class="shareoption" value="samegroup" name="shareopt" onchange="updateSharePermission(this);">
+                                <label for="samegroup">
+                                    <div class="ui header">
+                                        <div class="content">
+                                            <i class="users icon"></i> <span locale="share/setting/sameGroup">Users in the same group</span>
+                                            <div class="sub header" locale="share/setting/sameGroup/desc">Anyone who is in the same group as you do</div>
+                                        </div>
+                                    </div>
+                                </label>
+                            </div>
+                            <br><br>
+                            <div class="ui accordion" id="advanceShare">
+                                <div class="title">
+                                    <i class="dropdown icon"></i>
+                                    <span locale="share/setting/advance/title">Advance Share Options</span>
+                                </div>
+                                <div class="content">
+                                    <div class="ui radio checkbox">
+                                        <input id="users" type="radio" class="shareoption" value="users" name="shareopt" onchange="updateSharePermission(this);">
+                                        <label for="users">
+                                            <div class="ui header">
+                                                <div class="content">
+                                                    <i class="clipboard check icon"></i> <span locale="share/setting/advance/users">Selected Users</span>
+                                                    <div class="sub header" locale="share/setting/advance/usersDesc">Selected users with matching user name</div>
+                                                </div>
+                                            </div>
+                                        </label>
+                                    </div>
+                                    <div id="userselector">
+                                        <p style="margin-top: 1em;" locale="share/setting/advance/usersInstruct"">Select target users from the list below</p>
+                                        <select id="targetUsersList" class="ui fluid search dropdown" multiple="">
+                                            <option value="">Users</option>
+                                        </select>
+                                        <div id="noUserWarning" class="ui yellow message"  style="display:none;">
+                                            <i class="caret up icon"></i> <span locale="share/setting/advance/addUserToSave">Add at least one target share user to save changes</span>
+                                        </div>
+                                    </div>
+                                    <div class="ui radio checkbox" style="margin-top: 1em;">
+                                        <input id="groups" type="radio" class="shareoption" value="groups" name="shareopt" onchange="updateSharePermission(this);">
+                                        <label for="groups">
+                                            <div class="ui header">
+                                                <div class="content">
+                                                    <i class="sitemap icon"></i> <span locale="share/setting/advance/groups">Selected Groups</span>
+                                                    <div class="sub header" locale="share/setting/advance/groupsDesc">All the users that has access to any one of the selected group(s)</div>
+                                                </div>
+                                            </div>
+                                        </label>
+                                    </div>
+                                    <div id="groupselector">
+                                        <p style="margin-top: 1em;" locale="share/setting/advance/groupsInstruct">Select target groups from the list below</p>
+                                        <select id="targetGroupList" class="ui fluid search dropdown" multiple="">
+                                            <option value="">Groups</option>
+                                        </select>
+                                        <div id="noGroupWarning" class="ui yellow message" style="display:none;">
+                                            <i class="caret up icon"></i> <span locale="share/setting/advance/addGroupToSave">Add at least one target share group to save changes</span>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        <br><br>
+                        <div id="udpateNotification" style="display:none; position: fixed; bottom: 1em; right: 1em;" class="ui green inverted segment">
+                                <i class=" checkmark icon"></i> <span locale="share/setting/updated">Share Setting Updated</span>
+                        </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="ui divider actionButton"></div>
+        <div class="actionButton" style="width: 100%; padding-right: 12px;" align="right">
+            <div class="ui basic button popupbuttons allowHover" onclick="copyLinkToClipboard(this)">
+                <i class="copy icon"></i> <span locale="button/copy">Copy</span>
+            </div> 
+            <div id="sharingRemoveBtn" class="ui basic button popupbuttons allowHover" onclick="removeSharing()">
+                <i class="red remove icon"></i> <span locale="button/remove">Remove</span>
+            </div> 
+        </div>
+        <script>
+            /*
+                Usage: Pass in file descriptor to start share a file
+                var fd = encodeURIComponent(JSON.stringify({
+                        filename: "test.txt",
+                        filepath: "user:/Desktop/test.txt"
+                    })
+                );
+                window.open("file_share.html#" + fd);
+                
+                If you want to preset a file sharing mode (aka your module handle the share mode picking),
+                Pass in with the "shareMode" paramter. Example fd as follow:
+                {
+                    filename: "test.txt",
+                    filepath: "user:/Desktop/test.txt",
+                    shareMode: "signedin"
+                }
+
+                To remove a share, pass in "remove" for the share mode
+                Supported Share Mode keywords {anyone/signedin/samegroup/remove}
+
+                Other supported flags
+                {
+                    QRCode: {true/false} //Show or Hide the QR Code and link
+                    ActionButtons: {true/false} //Show or Hide the action button on the bottom
+                }
+
+            */
+            var shareCurrentEditingUUID = "";
+            var shareingFileData = {};
+            var darkTheme = false;
+            var initialized = false;
+            var fileSharingURL = "";
+            var relpath = "../../";
+            
+            function applyDarkThemeMode(){
+                $("body").addClass("darkTheme");
+                $(".ui.message").addClass("inverted");
+                darkTheme = true;
+            }
+
+            function removeQRCodeInDarkTheme(){
+                if (darkTheme){
+                    $("#qrcode").css({
+                        "border":"0px solid transparent",
+                        "background-color":"#242330",
+                    })
+                }
+            }
+
+            if ($(parent) && $(parent.document).find("body").hasClass("darkTheme")){
+                //Switch to darkTheme mode immediately
+                applyDarkThemeMode();
+            }   
+
+            PageReady();
+            function PageReady(){
+                if (initialized){
+                    return;
+                }
+
+                //Load User & Group List
+                $.get(relpath + "../system/users/list", function(data){
+                    var groups = {};
+                    $("#targetUsersList").html(`<option value="">Users</option>`);
+                    data.forEach(user => {
+                        $("#targetUsersList").append(`<option value="${user[0]}">${user[0]}</option>`);
+                        var userGroups = user[1];
+                        userGroups.forEach(thisGroup => {
+                            groups[thisGroup] = true;
+                        });
+                    });
+                    $("#targetGroupList").html(`<option value="">Groups</option>`);
+                    for (var [key, value] of Object.entries(groups)) {
+                        $("#targetGroupList").append(`<option value="${key}">${key}</option>`);
+                    }
+
+                    //Initiate the share details
+                    initFileDetails(shareingFileData, function(shareUUID){
+                        //Set the mode of share if it is defined
+                        if (shareingFileData.shareMode !== undefined && shareingFileData.shareMode == "remove"){
+                            //Remove the share UUID
+                            removeSharing();
+                            return;
+                        }
+                        if (shareingFileData.shareMode !== undefined){
+                            //As the share mode is defined by the caller, hide the setting interface
+                            $("#shareSettingOptions").hide();
+                            $("#sharelink").parent().css({
+                                "width": "100%",
+                                "text-align": "left",
+                            });
+                            $.ajax({
+                                url: relpath + "../system/file_system/share/edit",
+                                data: {uuid: shareCurrentEditingUUID, mode: shareingFileData.shareMode},
+                                success: function(data){
+                                    if (data.error !== undefined){
+                                        alert(data.error);
+                                        return;
+                                    }
+                                    
+                                    //Update the checkbox
+                                    $(".shareoption").each(function(){
+                                        if ($(this)[0].value != shareingFileData.shareMode){
+                                            $(this)[0].checked = false;
+                                        }else{
+                                            $(this)[0].checked = true;
+                                        }
+                                    
+                                    });
+                                }
+                            });
+                        }else{
+                            //Default: show the setting to allow user adjustment
+                            $("#main").css({
+                                "margin-top":"0em",
+                                "padding": "4px"
+                            });
+                            $("#shareSettingOptions").show();
+                        }
+
+                        $(".accordion").accordion();
+                    });
+                });
+
+                //Load theme style
+                $.get(relpath + "../system/file_system/preference?key=file_explorer/theme",function(data){
+                    if (data == "darkTheme"){
+                        applyDarkThemeMode();
+                    }
+                });
+
+
+
+                initialized = true;
+                //Do localization
+                applocale.init(relpath + "../SystemAO/locale/file_share.json", function(){
+                    applocale.translate();
+                });
+
+                $(".checkbox").checkbox();
+                $(".dropdown").dropdown();
+                var inputFile = ao_module_loadInputFiles();
+                if (inputFile == null){
+                    //No file selected
+                    $(".shareoption").parent().addClass("disabled");
+                    $("#qrcode").html(`<h1>No File</h1>`);
+                    $("#sharelink").text(``);
+                    $("#sharingRemoveBtn").addClass("disabled");
+                    return
+                }
+
+
+                //Make sure one file is choicen each time
+                inputFile = inputFile[0]; 
+                console.log("inputFile", inputFile);
+                shareingFileData = inputFile;
+
+                //Filter out the nessary display flags
+                if (shareingFileData.QRCode !== undefined && shareingFileData.QRCode == false){
+                    $(".qrcode").hide();
+                    $("#shareSettingOptions").attr("class", "sixteen wide column");
+                    $("#shareSettingOptions").css("padding", "1em");
+                    $(".eight.wide").hide();
+                }
+
+                if (shareingFileData.ActionButtons !== undefined && shareingFileData.ActionButtons == false){
+                    $(".actionButton").hide();
+                }
+            }
+
+            function initFileDetails(shareingFileData, callback=undefined){
+                $.ajax({
+                    url: relpath + "../system/file_system/share/new",
+                    data: {path: shareingFileData.filepath},
+                    success: function(data){
+                        if (data.error !== undefined){
+                            alert(data.error);
+                        }else{
+                            console.log(data);
+                            updateShareLinkInfo(data.UUID);
+                            shareCurrentEditingUUID = data.UUID;
+                            $(".shareoption").each(function(){
+                                if ($(this)[0].value != data.Permission){
+                                    $(this)[0].checked = false;
+                                }else{
+                                    $(this)[0].checked = true;
+                                    if (data.Permission == "users"){
+                                        $("#advanceShare").accordion("open", 0);
+                                        $("#targetUsersList").dropdown("set selected", data.Accessibles);
+                                        $("#targetUsersList").parent().removeClass("disabled");
+                                        $("#targetGroupList").parent().addClass("disabled");
+                                    }else if (data.Permission == "groups"){
+                                        $("#advanceShare").accordion("open", 0);
+                                        $("#targetGroupList").dropdown("set selected", data.Accessibles);
+                                        $("#targetUsersList").parent().addClass("disabled");
+                                        $("#targetGroupList").parent().removeClass("disabled");
+                                    }else{
+                                        $("#targetGroupList").parent().addClass("disabled");
+                                        $("#targetUsersList").parent().addClass("disabled");
+                                    }
+                                }
+                               
+                            });
+
+                          
+                            $("#targetUsersList").on("change", function(evt){
+                                updateSharePermissionByType("users");
+                            });
+
+                            $("#targetGroupList").on("change", function(evt){
+                                updateSharePermissionByType("groups");
+                            });
+               
+                            
+
+                            //If the file is from desktop, set share icon
+                            if (ao_module_virtualDesktop == true){
+                                var fileDir = shareingFileData.filepath.split("/");
+                                fileDir.pop();
+                                fileDir = fileDir.join("/");
+                                if (fileDir == "user:/Desktop"){
+                                    //Remove share icon
+                                    parent.setFileShareIndicator(shareingFileData.filename);
+                                }
+                            }
+
+                            if (callback != undefined){
+                                callback(data.UUID)
+                            }
+                        }
+                    }
+                });
+            }
+
+            function removeSharing(){
+                if (shareCurrentEditingUUID == ""){
+                    return
+                }
+
+                //The target file to remove
+                $.ajax({
+                    url: relpath + "../system/file_system/share/delete",
+                    data: {uuid: shareCurrentEditingUUID},
+                    success: function(data){
+                        if (data.error !== undefined){
+                            alert(data.error);
+                        }else{
+                            //Removed!
+                            $(".button").addClass('disabled');
+                            $(".checkbox").addClass("disabled");
+                            $("#sharelink").text("");
+                            $("#sharelink").attr("href", "#");
+                            $("#qrcode").html(`<br><br><h1><i class="green checkmark icon"></i> ${applocale.getString("message/removed", "Share Removed")}</h1>`);
+                            removeQRCodeInDarkTheme();
+                            //If the file is located on desktop and it is web desktop mode
+                            if (ao_module_virtualDesktop == true){
+                                var fileDir = shareingFileData.filepath.split("/");
+                                fileDir.pop();
+                                fileDir = fileDir.join("/");
+                                if (fileDir == "user:/Desktop"){
+                                    //Remove share icon
+                                    parent.removeFileShareIndicator(shareingFileData.filename);
+                                }
+                            }
+                        }
+                    }
+                });
+            }
+
+            function updateSharePermission(object){
+                var newPermission = $(object).attr('value');
+                updateSharePermissionByType(newPermission);
+            }   
+
+            function updateSharePermissionByType(newPermission){
+                if (newPermission == "users"){
+                    //Build the user list
+                    $("#targetUsersList").parent().removeClass("disabled");
+                    $("#targetGroupList").parent().addClass("disabled");
+                    var selectedUsers = $("#targetUsersList").val();
+                    $("#noGroupWarning").slideUp("fast");
+                    if (selectedUsers.length == 0){
+                        //Show tips message
+                        $("#noUserWarning").slideDown("fast");
+                        return;
+                    }else{
+                        $("#noUserWarning").slideUp("fast");
+                    }
+                    //Rewrite it to permission handling description
+                    newPermission = "users:" + selectedUsers.join(",");
+                }else if (newPermission == "groups"){
+                    //Build the group list
+                    $("#targetUsersList").parent().addClass("disabled");
+                    $("#targetGroupList").parent().removeClass("disabled");
+                    var selectedGroups = $("#targetGroupList").val();
+                    $("#noUserWarning").slideUp("fast");
+                    if (selectedGroups.length == 0){
+                        //Show tips message
+                        $("#noGroupWarning").slideDown("fast");
+                        return;
+                    }else{
+                        $("#noGroupWarning").slideUp("fast");
+                    }
+                    //Rewrite it to permission handling description
+                    newPermission = "groups:" + selectedGroups.join(",");
+                }
+
+                $.ajax({
+                    url: relpath + "../system/file_system/share/edit",
+                    data: {uuid: shareCurrentEditingUUID, mode: newPermission},
+                    success: function(data){
+                        if (data.error !== undefined){
+                            alert(data.error);
+                            return;
+                        }
+                        $("#udpateNotification").stop().finish().fadeIn("fast").delay(3000).fadeOut("fast");
+                    }
+                });
+            }
+
+            function updateShareLinkInfo(uuid){
+                $("#qrcode").html("");
+                let protocol = "https://";
+                if (location.protocol !== 'https:') {
+                    protocol = "http://";
+                }
+
+                var port = ":" + window.location.port;
+                if (window.location.port == ""){
+                    port = "";
+                }
+                var shareURL = protocol + window.location.hostname + port + "/share/" + uuid;
+                shareCurrentEditingUUID = uuid;
+                fileSharingURL = shareURL;
+                new QRCode(document.getElementById("qrcode"), shareURL);
+                $("#sharelink").text(shareURL);
+                $("#sharelink").attr("href", shareURL)
+            }
+
+            /*
+                Dynamic Script Loader
+
+                This is a really experimental implementation of importing a script from anywhere
+                under the ArozOS web root. This section of code must be written in plain JS to make sure
+                it works without jQuery and other libraries.
+
+                This function try to load jQuery and ao_module from the script folder.
+                Also loading the semantic js and the css main body
+            */
+           /*
+            //The possible location for desktop.system, standard webapp module, SystemAO interfaces and iui sub-interfaces
+            let possibleLocations = ["script/", "../script/", "../../script/", "../../../script/"];
+            let loopCount = Math.min(possibleLocations.length, JSON.parse(JSON.stringify(window.location.toString())).split("/").length - 3);
+            function tryLoad(relpath, filename, successCallback=undefined){
+                var request = new XMLHttpRequest();  
+                request.open('GET', relpath + filename, true);
+                request.onreadystatechange = function(){
+                    if (request.readyState === 4){
+                        if (request.status == 200 || request.status == 304) {  
+                            if (typeof(successCallback) != "undefined"){
+                                successCallback(relpath, filename);
+                            }
+                        }
+                    }
+                };
+                request.send();
+            }
+
+            function injectOtherJavaScriptLibrary(relpath){
+                //Check if ao_module is loaded
+                if (typeof(ao_module_virtualDesktop) == "undefined"){
+                    var script = document.createElement('script');
+                    script.setAttribute('src', relpath + "ao_module.js");
+                    document.getElementsByTagName('head')[0].appendChild(script);
+                }else{
+                    //This routine already run
+                    return;
+                }
+
+                //Inject QR Code library
+                var script = document.createElement('script');
+                script.setAttribute('src', relpath + "qrcode.min.js");
+                document.getElementsByTagName('head')[0].appendChild(script);
+
+                //Inject applocale
+                script = document.createElement('script');
+                script.setAttribute('src', relpath + "applocale.js");
+                document.getElementsByTagName('head')[0].appendChild(script);
+
+                //Inject semmantic css and js anyway
+                var head  = document.getElementsByTagName('head')[0];
+                var link  = document.createElement('link');
+                link.id   = "semantic";
+                link.rel  = 'stylesheet';
+                link.type = 'text/css';
+                link.href = relpath + 'semantic/semantic.min.css';
+                link.media = 'all';
+                head.appendChild(link);
+
+                var script = document.createElement('script');
+                script.setAttribute('src', relpath + "semantic/semantic.min.js");
+                document.getElementsByTagName('head')[0].appendChild(script);
+
+                setTimeout(function(){
+                    PageReady();
+                }, 1000);
+            }
+
+            //Load jQuery first
+            if (typeof(window.jQuery) == "undefined"){
+                //jQuery not found. Load it
+                for (var i = 0; i < loopCount; i++){
+                    var relpath = possibleLocations[i];
+                    tryLoad(relpath, "jquery.min.js", function(relpath, filename){
+                        //Generate the jquery script element
+                        var script = document.createElement('script');
+                        
+                        script.setAttribute('src', relpath + filename);
+                        document.getElementsByTagName('head')[0].appendChild(script);
+                        
+                        doAfterJqueryLoaded(function(){
+                            injectOtherJavaScriptLibrary(relpath);
+                        });
+                        
+                    });
+                }
+            }else{
+                //jQuery exists. Load ao_module
+                injectOtherJavaScriptLibrary();
+            }
+
+            function doAfterJqueryLoaded(callback){
+                setTimeout(function(){
+                    //Wait until it is loaded
+                    if (typeof(window.jQuery) == "undefined"){
+                        doAfterJqueryLoaded(callback);
+                        return
+                    }else{
+                        callback();
+                    }
+                }), 300;
+            }
+            */
+
+            function copyLinkToClipboard(btn){
+                //Copy text
+                const area = document.createElement('textarea');
+                document.body.appendChild(area);
+
+                area.value = fileSharingURL;
+                area.select();
+                document.execCommand('copy');
+
+                document.body.removeChild(area);
+
+                //Do visual feedback
+                let oldContent = $(btn).html();
+                $(btn).html(`<i class="green checkmark icon"></i> ${applocale.getString("button/copied","Copied!")}`);
+                setTimeout(function(){
+                    $(btn).html(oldContent);
+                }, 3000);
+            }
+
+        </script>
+    </body>
 </html>

+ 22 - 0
web/script/ao.css

@@ -11,6 +11,7 @@ body.whiteTheme {
     --text_color: rgb(29, 29, 29);
     --text_color_secondary: rgb(139, 139, 139);
     --text_color_invert: rgb(182, 182, 182);
+    --box_shadow_color: rgba(54, 54, 54, 0.35);
 }
 
 body.darkTheme{
@@ -23,12 +24,33 @@ body.darkTheme{
     --text_color: rgb(241, 241, 241);
     --text_color_secondary: rgb(214, 214, 214);
     --text_color_invert: rgb(63, 63, 63);
+    --box_shadow_color: rgba(54, 54, 54, 0.15);
 }
 
 :root{
     --default_fw_theme: rgba(26, 26, 26, 0.3);
 }
 
+/* darktheme overwrite */
+body.darkTheme .ui.basic.button{
+    color: var(--text_color) !important;
+    border: 1px solid var(--text_color_secondary);
+}
+
+body.darkTheme .ui.basic.button:hover{
+    background-color: var(--body_background_active) !important;
+}
+
+body.darkTheme span:not(.ui.message *):not(.ui.label *):not(.ui.dropdown *), 
+body.darkTheme div:not(.ui.message *):not(.ui.label *):not(.ui.dropdown *), 
+body.darkTheme p:not(.ui.message *):not(.ui.label *):not(.ui.dropdown *), 
+body.darkTheme i:not(.ui.message *):not(.ui.label *):not(.ui.dropdown *){
+   color: var(--text_color);
+}
+
+body.darkTheme .ui.header .sub.header{
+    color: var(--text_color_secondary);
+}
 
 /* floatWindow CSS */
 .floatWindow{

+ 141 - 143
web/script/contextmenu.css

@@ -1,143 +1,141 @@
-/*
-    Context Menu Plugin
-
-    Design for Semantic UI and use with .ui.contextmenu
-    Example Usage: 
-
-    <div id="contextmenu" class="aroz contextmenu" style="font-family: &quot;Microsoft JhengHei&quot;, &quot;SimHei&quot;, &quot;Apple LiGothic Medium&quot;, &quot;STHeiti&quot;; left: 497px; top: 248px;"><div class="item submenu" onclick="newitemmenu(this,event);" payload="">
-            New Item
-            <span class="description">
-                <i class="caret right icon"></i>
-            </span>
-        </div>
-        <div class="item" onclick="" payload="">
-            Refresh
-            <span class="description">
-                <i class="refresh icon"></i>
-            </span>
-        </div>
-        <div class="item" onclick="" payload="">
-            Open File Manager
-        </div>
-        <div class="item" onclick="" payload="">
-            Personalization
-            <span class="description">
-                <i class="paint brush icon"></i>
-            </span>
-        </div>
-        <div class="item submenu" onclick="" payload="">
-            Wallpaper
-            <span class="description">
-                <i class="caret right icon"></i>
-            </span>
-        </div>
-        <div class="item submenu" onclick="" payload="">
-            Icon Size
-            <span class="description">
-                <i class="caret right icon"></i>
-            </span>
-        </div>
-        <div class="item" onclick="" payload="">
-            Full Screen
-            <span class="description">
-                <i class="maximize icon"></i>
-            </span>
-        </div>
-        <div class="item" onclick="" payload="">
-            Logout
-        </div>
-    </div>
-*/
-
-.aroz.contextmenu{
-    position: fixed;
-    box-sizing: border-box;
-    letter-spacing: -.02em;
-    z-index: 3000;
-}
-
-.aroz.contextmenu .item{
-    padding: 0.6em 1em !important;
-}
-
-.aroz.contextmenu .item:hover{
-    background: rgb(247, 247, 247);
-}
-
-.aroz.contextmenu.visible, .ui.contextmenu.hidden.animating {
-    display: block;
-}
-
-.aroz.contextmenu .divider{
-    margin-top: 0;
-    margin-bottom: 0;    
-}
-
-.aroz.contextmenu{
-    cursor: auto;
-    outline: none;
-    min-width: 150px;
-    transform: translateZ(0px);
-    margin: 0em;
-    padding: 0em 0em;
-    background: #fff;
-    font-size: 1em;
-    text-align: left;
-    box-shadow: 0px 2px 3px 0px rgba(160,160,160,0.65);
-    border: 1px solid #d9d9d9;
-    border-radius: .28571rem;
-    z-index: 9;
-    will-change: transform, opacity;
-}
-
-.aroz.contextmenu > .item.item.item.item.item.item {
-    position: relative;
-    cursor: pointer;
-    display: flex;
-    border: none;
-    height: auto;
-    width: auto;
-    text-align: left;
-    border-top: none;
-    line-height: 1em;
-    font-size: 1rem;
-    color: #5a5a5a;
-    padding: .78571rem 1.14286rem !important;
-    text-transform: none;
-    font-weight: normal;
-    box-shadow: none;
-    border-radius: 0;
-    margin-left: 0 !important;
-    margin-right: 0 !important;
-    -webkit-touch-callout: none;
-}
-
-.aroz.contextmenu > .item.item.item.item.item.item > i{
-    font-size: 90%;
-}
-
-.aroz.contextmenu.visible > .item.item:hover {
-    background: #fbfbfb !important;
-    color: #5a5a5a !important;
-    z-index: 11;
-}
-
-.aroz.contextmenu > *{
-    white-space: nowrap;
-}
-
-.aroz.contextmenu > .item{
-    user-select: none;
-}
-
-.aroz.contextmenu > .item > .description {
-    margin: 0em 0em 0em 1em;
-    flex: 1;
-    text-align: right;
-    color: #bfbfbf;
-}
-
-.aroz.contextmenu .header{
-	padding: 0.4em;
-	background-color: rgba(30,30,30,0.05);
-}
+/*
+    Context Menu Plugin
+
+    Design for Semantic UI and use with .ui.contextmenu
+    Example Usage: 
+
+    <div id="contextmenu" class="aroz contextmenu" style="font-family: &quot;Microsoft JhengHei&quot;, &quot;SimHei&quot;, &quot;Apple LiGothic Medium&quot;, &quot;STHeiti&quot;; left: 497px; top: 248px;"><div class="item submenu" onclick="newitemmenu(this,event);" payload="">
+            New Item
+            <span class="description">
+                <i class="caret right icon"></i>
+            </span>
+        </div>
+        <div class="item" onclick="" payload="">
+            Refresh
+            <span class="description">
+                <i class="refresh icon"></i>
+            </span>
+        </div>
+        <div class="item" onclick="" payload="">
+            Open File Manager
+        </div>
+        <div class="item" onclick="" payload="">
+            Personalization
+            <span class="description">
+                <i class="paint brush icon"></i>
+            </span>
+        </div>
+        <div class="item submenu" onclick="" payload="">
+            Wallpaper
+            <span class="description">
+                <i class="caret right icon"></i>
+            </span>
+        </div>
+        <div class="item submenu" onclick="" payload="">
+            Icon Size
+            <span class="description">
+                <i class="caret right icon"></i>
+            </span>
+        </div>
+        <div class="item" onclick="" payload="">
+            Full Screen
+            <span class="description">
+                <i class="maximize icon"></i>
+            </span>
+        </div>
+        <div class="item" onclick="" payload="">
+            Logout
+        </div>
+    </div>
+*/
+
+
+.aroz.contextmenu .item{
+    padding: 0.6em 1em !important;
+}
+
+.aroz.contextmenu .item:hover{
+    background: var(--body_background_active);
+}
+
+.aroz.contextmenu.visible, .ui.contextmenu.hidden.animating {
+    display: block;
+}
+
+.aroz.contextmenu .divider{
+    margin-top: 0;
+    margin-bottom: 0;    
+}
+
+.aroz.contextmenu{
+    position: fixed;
+    box-sizing: border-box;
+    letter-spacing: -.02em;
+    cursor: auto;
+    outline: none;
+    min-width: 150px;
+    transform: translateZ(0px);
+    margin: 0em;
+    padding: 0em 0em;
+    background: var(--body_background);
+    font-size: 1em;
+    text-align: left;
+    box-shadow: 0px 2px 3px 0px var(--box_shadow_color);
+    border: 1px solid var(--divider);
+    border-radius: .28571rem;
+    z-index: 9;
+    will-change: transform, opacity;
+}
+
+
+.aroz.contextmenu > .item.item.item.item.item.item {
+    position: relative;
+    cursor: pointer;
+    display: flex;
+    border: none;
+    height: auto;
+    width: auto;
+    text-align: left;
+    border-top: none;
+    line-height: 1em;
+    font-size: 1rem;
+    color: var(--text_color_secondary);
+    padding: .78571rem 1.14286rem !important;
+    text-transform: none;
+    font-weight: normal;
+    box-shadow: none;
+    border-radius: 0;
+    margin-left: 0 !important;
+    margin-right: 0 !important;
+    -webkit-touch-callout: none;
+}
+
+.aroz.contextmenu > .item.item.item.item.item.item > i{
+    font-size: 90%;
+}
+
+.aroz.contextmenu.visible > .item.item:hover {
+    background: #fbfbfb !important;
+    color: #5a5a5a !important;
+    z-index: 11;
+}
+
+.aroz.contextmenu > *{
+    white-space: nowrap;
+}
+
+.aroz.contextmenu > .item{
+    user-select: none;
+}
+
+.aroz.contextmenu > .item > .description {
+    margin: 0em 0em 0em 1em;
+    flex: 1;
+    text-align: right;
+    color: #bfbfbf;
+}
+
+.aroz.contextmenu .header{
+	padding: 0.4em;
+	background-color: rgba(30,30,30,0.05);
+}