mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Merge branch 'dev' into dev-BetterDisplayMobile
This commit is contained in:
commit
3797d5430f
@ -96,9 +96,13 @@ class Users_Controller:
|
|||||||
users_helper.update_user(user_id, up_data)
|
users_helper.update_user(user_id, up_data)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add_user(username, password=None, email="default@example.com", enabled: bool = True, superuser: bool = False):
|
def add_user(username, password, email="default@example.com", enabled: bool = True, superuser: bool = False):
|
||||||
return users_helper.add_user(username, password=password, email=email, enabled=enabled, superuser=superuser)
|
return users_helper.add_user(username, password=password, email=email, enabled=enabled, superuser=superuser)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_rawpass_user(username, password, email="default@example.com", enabled: bool = True, superuser: bool = False):
|
||||||
|
return users_helper.add_rawpass_user(username, password=password, email=email, enabled=enabled, superuser=superuser)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def remove_user(user_id):
|
def remove_user(user_id):
|
||||||
return users_helper.remove_user(user_id)
|
return users_helper.remove_user(user_id)
|
||||||
|
@ -147,7 +147,7 @@ class helper_users:
|
|||||||
return user
|
return user
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add_user(username: str, password: Optional[str] = None, email: Optional[str] = None, enabled: bool = True, superuser: bool = False) -> str:
|
def add_user(username: str, password: str = None, email: Optional[str] = None, enabled: bool = True, superuser: bool = False) -> str:
|
||||||
if password is not None:
|
if password is not None:
|
||||||
pw_enc = helper.encode_pass(password)
|
pw_enc = helper.encode_pass(password)
|
||||||
else:
|
else:
|
||||||
@ -162,6 +162,18 @@ class helper_users:
|
|||||||
}).execute()
|
}).execute()
|
||||||
return user_id
|
return user_id
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_rawpass_user(username: str, password: str = None, email: Optional[str] = None, enabled: bool = True, superuser: bool = False) -> str:
|
||||||
|
user_id = Users.insert({
|
||||||
|
Users.username: username.lower(),
|
||||||
|
Users.password: password,
|
||||||
|
Users.email: email,
|
||||||
|
Users.enabled: enabled,
|
||||||
|
Users.superuser: superuser,
|
||||||
|
Users.created: helper.get_time_as_string()
|
||||||
|
}).execute()
|
||||||
|
return user_id
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_user(user_id, up_data=None):
|
def update_user(user_id, up_data=None):
|
||||||
if up_data is None:
|
if up_data is None:
|
||||||
|
@ -6,6 +6,7 @@ import logging
|
|||||||
|
|
||||||
from app.classes.shared.console import console
|
from app.classes.shared.console import console
|
||||||
from app.classes.shared.helpers import helper
|
from app.classes.shared.helpers import helper
|
||||||
|
from app.classes.shared.import3 import import3
|
||||||
from app.classes.web.websocket_helper import websocket_helper
|
from app.classes.web.websocket_helper import websocket_helper
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -58,6 +59,9 @@ class MainPrompt(cmd.Cmd):
|
|||||||
else:
|
else:
|
||||||
print(f'Name: {thread.name} Identifier: {thread.ident}')
|
print(f'Name: {thread.name} Identifier: {thread.ident}')
|
||||||
|
|
||||||
|
def do_import3(self, _line):
|
||||||
|
import3.start_import()
|
||||||
|
|
||||||
def universal_exit(self):
|
def universal_exit(self):
|
||||||
logger.info("Stopping all server daemons / threads")
|
logger.info("Stopping all server daemons / threads")
|
||||||
console.info("Stopping all server daemons / threads - This may take a few seconds")
|
console.info("Stopping all server daemons / threads - This may take a few seconds")
|
||||||
@ -75,3 +79,7 @@ class MainPrompt(cmd.Cmd):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def help_migrations():
|
def help_migrations():
|
||||||
console.help("Only for advanced users. Use with caution")
|
console.help("Only for advanced users. Use with caution")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def help_import3():
|
||||||
|
console.help("Import users and servers from Crafty 3")
|
||||||
|
58
app/classes/shared/import3.py
Normal file
58
app/classes/shared/import3.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from app.classes.controllers.users_controller import users_helper
|
||||||
|
from app.classes.shared.main_controller import Controller
|
||||||
|
from app.classes.shared.console import console
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class import3:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.controller = Controller()
|
||||||
|
|
||||||
|
def start_import(self):
|
||||||
|
folder = os.path.normpath(input("Please input the path to the migrations folder in your installation of Crafty 3: "))
|
||||||
|
if not os.path.exists(folder):
|
||||||
|
console.info("Crafty cannot find the path you entered. Does Crafty's user have permission to access it?")
|
||||||
|
console.info("Please run the import3 command again and enter a valid path.")
|
||||||
|
else:
|
||||||
|
with open (os.path.join(folder, "users.json"), encoding="utf-8") as f:
|
||||||
|
user_json = json.loads(f.read())
|
||||||
|
with open (os.path.join(folder, "mc_settings.json"), encoding="utf-8") as f:
|
||||||
|
servers_json = json.loads(f.read())
|
||||||
|
self.import_users(user_json)
|
||||||
|
self.import_servers(servers_json, self.controller)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def import_users(json_data):
|
||||||
|
# If there is only one user to import json needs to call the data differently
|
||||||
|
if isinstance(json_data, list):
|
||||||
|
for user in json_data:
|
||||||
|
users_helper.add_rawpass_user(user['username'], user['password'])
|
||||||
|
console.info(f"Imported user {user['username']} from Crafty 3")
|
||||||
|
logger.info(f"Imported user {user['username']} from Crafty 3")
|
||||||
|
else:
|
||||||
|
console.info("There is only one user detected. Cannot create duplicate Admin account.")
|
||||||
|
logger.info("There is only one user detected. Cannot create duplicate Admin account.")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def import_servers(json_data, controller):
|
||||||
|
# If there is only one server to import json needs to call the data differently
|
||||||
|
if isinstance(json_data, list):
|
||||||
|
for server in json_data:
|
||||||
|
new_server_id = controller.import_jar_server(server_name=server['server_name'], server_path=server['server_path'],
|
||||||
|
server_jar=server['server_jar'], min_mem=(int(server['memory_min'])/1000),
|
||||||
|
max_mem=(int(server['memory_max'])/1000), port=server['server_port'])
|
||||||
|
console.info(f"Imported server {server['server_name']}[{server['id']}] from Crafty 3 to new server id {new_server_id}")
|
||||||
|
logger.info(f"Imported server {server['server_name']}[{server['id']}] from Crafty 3 to new server id {new_server_id}")
|
||||||
|
else:
|
||||||
|
new_server_id = controller.import_jar_server(server_name=json_data['server_name'], server_path=json_data['server_path'],
|
||||||
|
server_jar=json_data['server_jar'], min_mem=(int(json_data['memory_min'])/1000),
|
||||||
|
max_mem=(int(json_data['memory_max'])/1000), port=json_data['server_port'])
|
||||||
|
console.info(f"Imported server {json_data['server_name']}[{json_data['id']}] from Crafty 3 to new server id {new_server_id}")
|
||||||
|
logger.info(f"Imported server {json_data['server_name']}[{json_data['id']}] from Crafty 3 to new server id {new_server_id}")
|
||||||
|
|
||||||
|
import3 = import3()
|
@ -312,6 +312,7 @@ class AjaxHandler(BaseHandler):
|
|||||||
elif page == "backup_now":
|
elif page == "backup_now":
|
||||||
server_id = self.get_argument('id', None)
|
server_id = self.get_argument('id', None)
|
||||||
if server_id is None:
|
if server_id is None:
|
||||||
|
logger.error("Server ID is none. Canceling backup!")
|
||||||
return
|
return
|
||||||
|
|
||||||
server = self.controller.get_server_obj(server_id)
|
server = self.controller.get_server_obj(server_id)
|
||||||
|
@ -181,10 +181,8 @@ class PanelHandler(BaseHandler):
|
|||||||
now = time.time()
|
now = time.time()
|
||||||
formatted_time = str(datetime.datetime.fromtimestamp(now).strftime('%Y-%m-%d %H:%M:%S'))
|
formatted_time = str(datetime.datetime.fromtimestamp(now).strftime('%Y-%m-%d %H:%M:%S'))
|
||||||
|
|
||||||
# pylint: disable=unused-variable
|
api_key, _token_data, exec_user = self.current_user
|
||||||
api_key, token_data, exec_user = self.current_user
|
|
||||||
superuser = exec_user['superuser']
|
superuser = exec_user['superuser']
|
||||||
print()
|
|
||||||
if api_key is not None:
|
if api_key is not None:
|
||||||
superuser = superuser and api_key.superuser
|
superuser = superuser and api_key.superuser
|
||||||
|
|
||||||
@ -393,11 +391,6 @@ class PanelHandler(BaseHandler):
|
|||||||
|
|
||||||
valid_subpages = ['term', 'logs', 'backup', 'config', 'files', 'admin_controls', 'schedules']
|
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 = self.controller.get_server_obj(server_id)
|
||||||
# server_data isn't needed since the server_stats also pulls server data
|
# 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)
|
page_data['server_data'] = self.controller.servers.get_server_data_by_id(server_id)
|
||||||
@ -424,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['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']['crashed'] = self.controller.servers.is_crashed(server_id)
|
||||||
page_data['server_stats']['server_type'] = self.controller.servers.get_server_type_by_id(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 subpage == 'term':
|
||||||
if not page_data['permissions']['Terminal'] in page_data['user_permissions']:
|
if not page_data['permissions']['Terminal'] in page_data['user_permissions']:
|
||||||
@ -532,8 +545,6 @@ class PanelHandler(BaseHandler):
|
|||||||
elif page == 'panel_config':
|
elif page == 'panel_config':
|
||||||
auth_servers = {}
|
auth_servers = {}
|
||||||
auth_role_servers = {}
|
auth_role_servers = {}
|
||||||
users_list = []
|
|
||||||
role_users = {}
|
|
||||||
roles = self.controller.roles.get_all_roles()
|
roles = self.controller.roles.get_all_roles()
|
||||||
user_roles = {}
|
user_roles = {}
|
||||||
for user in self.controller.users.get_all_users():
|
for user in self.controller.users.get_all_users():
|
||||||
@ -952,8 +963,7 @@ class PanelHandler(BaseHandler):
|
|||||||
|
|
||||||
@tornado.web.authenticated
|
@tornado.web.authenticated
|
||||||
def post(self, page):
|
def post(self, page):
|
||||||
# pylint: disable=unused-variable
|
api_key, _token_data, exec_user = self.current_user
|
||||||
api_key, token_data, exec_user = self.current_user
|
|
||||||
superuser = exec_user['superuser']
|
superuser = exec_user['superuser']
|
||||||
if api_key is not None:
|
if api_key is not None:
|
||||||
superuser = superuser and api_key.superuser
|
superuser = superuser and api_key.superuser
|
||||||
@ -1037,7 +1047,6 @@ class PanelHandler(BaseHandler):
|
|||||||
server_obj.path = server_obj.path
|
server_obj.path = server_obj.path
|
||||||
server_obj.log_path = server_obj.log_path
|
server_obj.log_path = server_obj.log_path
|
||||||
server_obj.executable = server_obj.executable
|
server_obj.executable = server_obj.executable
|
||||||
print(server_obj.execution_command)
|
|
||||||
server_obj.execution_command = server_obj.execution_command
|
server_obj.execution_command = server_obj.execution_command
|
||||||
server_obj.server_ip = server_obj.server_ip
|
server_obj.server_ip = server_obj.server_ip
|
||||||
server_obj.server_port = server_obj.server_port
|
server_obj.server_port = server_obj.server_port
|
||||||
@ -1683,8 +1692,7 @@ class PanelHandler(BaseHandler):
|
|||||||
|
|
||||||
@tornado.web.authenticated
|
@tornado.web.authenticated
|
||||||
def delete(self, page):
|
def delete(self, page):
|
||||||
# pylint: disable=unused-variable
|
api_key, _token_data, exec_user = self.current_user
|
||||||
api_key, token_data, exec_user = self.current_user
|
|
||||||
superuser = exec_user['superuser']
|
superuser = exec_user['superuser']
|
||||||
if api_key is not None:
|
if api_key is not None:
|
||||||
superuser = superuser and api_key.superuser
|
superuser = superuser and api_key.superuser
|
||||||
|
@ -423,6 +423,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- content-wrapper ends -->
|
<!-- content-wrapper ends -->
|
||||||
|
<div id="mobile"></div>
|
||||||
<style>
|
<style>
|
||||||
.popover-body {
|
.popover-body {
|
||||||
color: white !important;
|
color: white !important;
|
||||||
@ -760,6 +761,19 @@
|
|||||||
<script src="/static/assets/js/jquery-ui.js"></script>
|
<script src="/static/assets/js/jquery-ui.js"></script>
|
||||||
<link rel="stylesheet" href="/static/assets/css/jquery-ui.css">
|
<link rel="stylesheet" href="/static/assets/css/jquery-ui.css">
|
||||||
<link rel="stylesheet" href="/static/assets/css/jquery-ui.structure.css">
|
<link rel="stylesheet" href="/static/assets/css/jquery-ui.structure.css">
|
||||||
|
<style>
|
||||||
|
@media only screen and (max-width: 760px) {
|
||||||
|
#mobile { display: none; }
|
||||||
|
}
|
||||||
|
.ui-sortable-handle {
|
||||||
|
cursor: default;
|
||||||
|
padding:2px;
|
||||||
|
}
|
||||||
|
.ui-sortable-handle:hover {
|
||||||
|
cursor: grab !important;
|
||||||
|
padding:2px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
/* Search Bar */
|
/* Search Bar */
|
||||||
@ -775,8 +789,9 @@
|
|||||||
|
|
||||||
$(document).on("mousedown keyup click", function(event) {
|
$(document).on("mousedown keyup click", function(event) {
|
||||||
const value = $('.dataTables_filter input').val();
|
const value = $('.dataTables_filter input').val();
|
||||||
|
const is_mobile = $('#mobile').css('display')=='none';
|
||||||
|
|
||||||
if ($("table#servers_table tbody").sortable("toArray").length > 1 && value === '') {
|
if ($("table#servers_table tbody").sortable("toArray").length > 1 && value === '' && !is_mobile) {
|
||||||
$("table#servers_table tbody").sortable("enable");
|
$("table#servers_table tbody").sortable("enable");
|
||||||
} else {
|
} else {
|
||||||
$("table#servers_table tbody").sortable("disable");
|
$("table#servers_table tbody").sortable("disable");
|
||||||
@ -805,9 +820,10 @@ $(document).ready(function() {
|
|||||||
$("table#servers_table tbody")
|
$("table#servers_table tbody")
|
||||||
.sortable({
|
.sortable({
|
||||||
items: '> tr',
|
items: '> tr',
|
||||||
cursor: "move",
|
cursor: "grabbing",
|
||||||
axis: "y",
|
axis: "y",
|
||||||
revert: true,
|
revert: true,
|
||||||
|
handle:"i.fas.fa-server,a",
|
||||||
forcePlaceholderSize: true,
|
forcePlaceholderSize: true,
|
||||||
placeholder:'table-placeholder',
|
placeholder:'table-placeholder',
|
||||||
deactivate: function(event, ui) {
|
deactivate: function(event, ui) {
|
||||||
@ -831,7 +847,10 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Fixes the appearance of a scrollbar when a user tries to drag an item too low
|
// Fixes the appearance of a scrollbar when a user tries to drag an item too low
|
||||||
$("div#servers_table_wrapper").css({ overflow: "hidden" });
|
// Disabled on mobile since sorting is disabled on mobile
|
||||||
|
if($('#mobile').css('display') != 'none'){
|
||||||
|
$("div#servers_table_wrapper").css({ overflow: "hidden" });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -163,7 +163,6 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none; /* Prevent text selection */
|
user-select: none; /* Prevent text selection */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the caret/arrow with a unicode, and style it */
|
/* Create the caret/arrow with a unicode, and style it */
|
||||||
.tree-caret .fa-folder {
|
.tree-caret .fa-folder {
|
||||||
display: inline-block;
|
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();
|
setFileName();
|
||||||
$('#editorParent').toggle(false) // show
|
$('#editorParent').toggle(false) // show
|
||||||
$('#fileError').toggle(false) // hide
|
$('#fileError').toggle(false) // hide
|
||||||
@ -739,6 +831,19 @@
|
|||||||
|
|
||||||
for (var i = 0; i < treeItems.length; i++) {
|
for (var i = 0; i < treeItems.length; i++) {
|
||||||
var treeItem = treeItems[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) {
|
treeItem.addEventListener('contextmenu', function contextListener(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var ctxmenuPath = event.target.getAttribute('data-path');
|
var ctxmenuPath = event.target.getAttribute('data-path');
|
||||||
|
Loading…
Reference in New Issue
Block a user