From ecc87a6137181e51fc070bc436538c081a4b0ba6 Mon Sep 17 00:00:00 2001 From: Andrew Date: Tue, 22 Mar 2022 14:24:15 +0000 Subject: [PATCH] Add context menu for iOS + Bug fix --- app/classes/web/ajax_handler.py | 1 + app/classes/web/panel_handler.py | 25 +++- .../templates/panel/server_files.html | 107 +++++++++++++++++- 3 files changed, 127 insertions(+), 6 deletions(-) diff --git a/app/classes/web/ajax_handler.py b/app/classes/web/ajax_handler.py index 3c9c05e5..dc916ed1 100644 --- a/app/classes/web/ajax_handler.py +++ b/app/classes/web/ajax_handler.py @@ -312,6 +312,7 @@ class AjaxHandler(BaseHandler): elif page == "backup_now": server_id = self.get_argument('id', None) if server_id is None: + logger.error("Server ID is none. Canceling backup!") return server = self.controller.get_server_obj(server_id) diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 3fa99fcc..3ceb38e1 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -391,11 +391,6 @@ class PanelHandler(BaseHandler): valid_subpages = ['term', 'logs', 'backup', 'config', 'files', 'admin_controls', 'schedules'] - if subpage not in valid_subpages: - logger.debug('not a valid subpage') - subpage = 'term' - logger.debug(f'Subpage: "{subpage}"') - server = self.controller.get_server_obj(server_id) # server_data isn't needed since the server_stats also pulls server data page_data['server_data'] = self.controller.servers.get_server_data_by_id(server_id) @@ -422,6 +417,26 @@ class PanelHandler(BaseHandler): page_data['user_permissions'] = self.controller.server_perms.get_user_id_permissions_list(exec_user["user_id"], server_id) page_data['server_stats']['crashed'] = self.controller.servers.is_crashed(server_id) page_data['server_stats']['server_type'] = self.controller.servers.get_server_type_by_id(server_id) + if subpage not in valid_subpages: + logger.debug('not a valid subpage') + if not subpage: + if page_data['permissions']['Terminal'] in page_data['user_permissions']: + subpage = 'term' + elif page_data['permissions']['Logs'] in page_data['user_permissions']: + subpage = 'logs' + elif page_data['permissions']['Schedule'] in page_data['user_permissions']: + subpage = 'schedules' + elif page_data['permissions']['Backup'] in page_data['user_permissions']: + subpage = 'backup' + elif page_data['permissions']['Files'] in page_data['user_permissions']: + subpage = 'files' + elif page_data['permissions']['Config'] in page_data['user_permissions']: + subpage = 'config' + elif page_data['permissions']['Players'] in page_data['user_permissions']: + subpage = 'admin_controls' + else: + self.redirect("/panel/error?error=Unauthorized access to Server") + logger.debug(f'Subpage: "{subpage}"') if subpage == 'term': if not page_data['permissions']['Terminal'] in page_data['user_permissions']: diff --git a/app/frontend/templates/panel/server_files.html b/app/frontend/templates/panel/server_files.html index 225f5ba6..87daf416 100644 --- a/app/frontend/templates/panel/server_files.html +++ b/app/frontend/templates/panel/server_files.html @@ -163,7 +163,6 @@ cursor: pointer; user-select: none; /* Prevent text selection */ } - /* Create the caret/arrow with a unicode, and style it */ .tree-caret .fa-folder { display: inline-block; @@ -377,6 +376,99 @@ } } + var onlongtouch; + var timer; + var touchduration = 500; //length of time we want the user to touch before we do something + const longtouch = new Event('longtouch'); + + function touchstart(event) { + if (!timer) { + timer = setTimeout(onlongtouch, touchduration, event); + } + } + + function touchend(event) { + //stops short touches from firing the event + if (timer) { + clearTimeout(timer); + console.log('Timer: ' + timer) + timer = null; + } + } + + onlongtouch = function(e) { + console.log('iOS long touch detected!'); + if([ + 'iPad Simulator', + 'iPhone Simulator', + 'iPod Simulator', + 'iPad', + 'iPhone', + 'iPod' + ].includes(navigator.platform) + // iPad on iOS 13 detection + || (navigator.userAgent.includes("Mac") && "ontouchend" in document)){ + e.preventDefault(); + e.stopImmediatePropagation(); + var ctxmenuPath = e.target.getAttribute('data-path'); + var ctxmenuName = e.target.getAttribute('data-name'); + if (!ctxmenuPath) { + console.log({ 'event.target': e.target, ctxmenuPath }); + return; + } + $('#renameItem').show(); + + var isDir = e.target.classList.contains('files-tree-title'); + $('#createFile').toggle(isDir); + $('#createDir').toggle(isDir); + $('#deleteDir').toggle(isDir); + $('#upload').toggle(isDir); + + var isFile = e.target.classList.contains('tree-file'); + $('#deleteFile').toggle(isFile); + $('#downloadFile').toggle(isFile); + console.log({ 'event.target': e.target, isDir, isFile }); + + if (e.target.classList.contains('root-dir')) { + $('#createFile').show(); + $('#createDir').show(); + $('#renameItem').hide(); + $('#deleteDir').hide(); + $('#deleteFile').hide(); + $('#downloadFile').hide(); + $('#upload').show(); + } + if (e.target.textContent.endsWith('.zip')) { + $('#unzip').show(); + console.log(e.target.textContent) + } else { + $('#unzip').hide(); + } + + var clientX = e.layerX + 2; + var clientY = e.layerY + 5; + + + + document.getElementById('files-tree-nav-content') + .setAttribute('data-path', ctxmenuPath); + document.getElementById('files-tree-nav-content') + .setAttribute('data-name', ctxmenuName); + document.getElementById("files-tree-nav").style.display = "flex"; + document.getElementById("files-tree-nav").style.position = "fixed"; + domRect = document.getElementById("files-tree-nav").getBoundingClientRect(); + sum = (clientY+domRect['height']) - window.innerHeight + if(domRect['height']+clientY > window.innerHeight){ + clientY = clientY - sum; + } + document.getElementById("files-tree-nav").style.top = clientY + 'px'; + document.getElementById("files-tree-nav").style.left = clientX + 'px'; + console.log(window.innerHeight) + timer = null; + }; + } + + setFileName(); $('#editorParent').toggle(false) // show $('#fileError').toggle(false) // hide @@ -739,6 +831,19 @@ for (var i = 0; i < treeItems.length; i++) { var treeItem = treeItems[i]; + if([ + 'iPad Simulator', + 'iPhone Simulator', + 'iPod Simulator', + 'iPad', + 'iPhone', + 'iPod' + ].includes(navigator.platform) + // iPad on iOS 13 detection + || (navigator.userAgent.includes("Mac") && "ontouchend" in document)){ + treeItem.addEventListener("touchstart", touchstart, false); + treeItem.addEventListener("touchend", touchend, false); + } treeItem.addEventListener('contextmenu', function contextListener(event) { event.preventDefault(); var ctxmenuPath = event.target.getAttribute('data-path');