From 474a62c061272c5350f0184fbafa1cc8864db9c3 Mon Sep 17 00:00:00 2001 From: Tim Fry Date: Tue, 18 Mar 2025 15:30:02 -0300 Subject: [PATCH 01/12] Floating Script and Editor --- index.php | 1370 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 815 insertions(+), 555 deletions(-) diff --git a/index.php b/index.php index d7d8f53..957b1d6 100644 --- a/index.php +++ b/index.php @@ -1,626 +1,886 @@ - Portions created by the Initial Developer are Copyright (C) 2008-2024 - the Initial Developer. All Rights Reserved. + The Initial Developer of the Original Code is + Mark J Crane + Portions created by the Initial Developer are Copyright (C) 2008-2024 + the Initial Developer. All Rights Reserved. - Contributor(s): - Mark J Crane - James Rose -*/ + Contributor(s): + Mark J Crane + James Rose + */ //includes files - require_once dirname(__DIR__, 2) . "/resources/require.php"; - require_once "resources/check_auth.php"; +require_once dirname(__DIR__, 2) . "/resources/require.php"; +require_once "resources/check_auth.php"; //check permissions - if (permission_exists('edit_view')) { - //access granted - } - else { - echo "access denied"; - exit; - } +if (permission_exists('edit_view')) { + //access granted +} else { + echo "access denied"; + exit; +} //add multi-lingual support - $language = new text; - $text = $language->get(); +$language = new text; +$text = $language->get(); //set the directory title and mode - switch ($_GET["dir"]) { - case 'xml': - $title = 'XML'; - $mode = 'xml'; - $dir = 'xml'; - break; - case 'provision': - $title = 'Provision'; - $mode = 'xml'; - $dir = 'provision'; - break; - case 'php': - $title = 'PHP'; - $mode = 'php'; - $dir = 'php'; - break; - case 'scripts': - $title = 'Scripts'; - $mode = 'lua'; - $dir = 'scripts'; - break; - case 'grammar': - $title = 'Grammar'; - $mode = 'xml'; - $dir = 'grammar'; - break; - default: - $mode = 'text'; - $dir = ''; - } +switch ($_GET["dir"]) { + case 'xml': + $title = 'XML'; + $mode = 'xml'; + $dir = 'xml'; + break; + case 'provision': + $title = 'Provision'; + $mode = 'xml'; + $dir = 'provision'; + break; + case 'php': + $title = 'PHP'; + $mode = 'php'; + $dir = 'php'; + break; + case 'scripts': + $title = 'Scripts'; + $mode = 'lua'; + $dir = 'scripts'; + break; + case 'grammar': + $title = 'Grammar'; + $mode = 'xml'; + $dir = 'grammar'; + break; + default: + $mode = 'text'; + $dir = ''; +} //save the sanitized value - $_SESSION['app']['edit']['dir'] = $dir; +$_SESSION['app']['edit']['dir'] = $dir; //load editor preferences/defaults - $setting_size = $settings->get('editor', 'font_size', '12px'); - $setting_theme = $settings->get('editor', 'theme', 'cobalt'); - $setting_invisibles = $settings->get('editor', 'invisibles','false'); - $setting_indenting = $settings->get('editor', 'indent_guides','false'); - $setting_numbering = $settings->get('editor', 'line_numbers','true'); +$setting_size = $settings->get('editor', 'font_size', '12px'); +$setting_theme = $settings->get('editor', 'theme', 'cobalt'); +$setting_invisibles = $settings->get('editor', 'invisibles', 'false'); +$setting_indenting = $settings->get('editor', 'indent_guides', 'false'); +$setting_numbering = $settings->get('editor', 'line_numbers', 'true'); //get and then set the favicon - $favicon = $settings->get('theme', 'favicon', PROJECT_ROOT .'/themes/default/favicon.ico'); +$favicon = $settings->get('theme', 'favicon', PROJECT_ROOT . '/themes/default/favicon.ico'); //create a token - $key_name = '/app/edit/'.$mode; - $_SESSION['keys'][$key_name] = bin2hex(random_bytes(32)); - $_SESSION['token'] = hash_hmac('sha256', $key_name, $_SESSION['keys'][$key_name]); - - //The buffer must be empty - while(ob_get_level() > 0) - ob_get_clean(); +$key_name = '/app/edit/' . $mode; +$_SESSION['keys'][$key_name] = bin2hex(random_bytes(32)); +$_SESSION['token'] = hash_hmac('sha256', $key_name, $_SESSION['keys'][$key_name]); +//The buffer must be empty +while (ob_get_level() > 0) + ob_get_clean(); ?> - - - <?php echo $title; ?> - - - - + + + + +
+ +
+
+ Loading... +
+
+ Loading... +
+
+
+
+
+
+
+
+
+
+ + +
+
 
+ +
+ + + +
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+ + + + - - - -
- - - - -
- -
- - - -
-
- -
-
- -
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
- -
-
-
- - - - - - + \ No newline at end of file From d3e645bcd13e0f6c66f8f4928a105a04ee7f0d13 Mon Sep 17 00:00:00 2001 From: Tim Fry Date: Sat, 12 Apr 2025 00:24:13 -0300 Subject: [PATCH 02/12] Multi-tab layout with better function detection for auto-complete --- file_list.php | 191 +++-- index.php | 1459 +++++++++++++++------------------ resources/get_php_methods.php | 161 ++-- 3 files changed, 842 insertions(+), 969 deletions(-) diff --git a/file_list.php b/file_list.php index 3e9d6f7..00a7448 100644 --- a/file_list.php +++ b/file_list.php @@ -26,84 +26,101 @@ */ //includes files - require_once dirname(__DIR__, 2) . "/resources/require.php"; - require_once "resources/check_auth.php"; +require_once dirname(__DIR__, 2) . "/resources/require.php"; +require_once "resources/check_auth.php"; //check permissions - if (permission_exists('edit_view')) { - //access granted - } - else { - echo "access denied"; - exit; - } +if (permission_exists('edit_view')) { + //access granted +} else { + echo "access denied"; + exit; +} + +//add multi-lingual support +$language = new text(); +$text = $language->get(); + +//set the domain and user +$domain_uuid = $_SESSION['domain_uuid'] ?? ''; +$user_uuid = $_SESSION['user_uuid'] ?? ''; + +//ensure database and settings objects are created +global $database; +if (empty($database) || !($database instanceof database)) { + $database = database::new(); +} +if (empty($settings) || !($settings instanceof settings)) { + $settings = new settings(['database' => $database, 'domain_uuid' => $domain_uuid, 'user_uuid' => $user_uuid]); +} //add css and javascript - require_once "header.php"; +require_once "header.php"; //define function recur_dir - function recur_dir($dir) { - clearstatcache(); - $html_dir_list = ''; - $html_file_list = ''; - $dir_handle = opendir($dir); - $dir_array = array(); - if (($dir_handle)) { - $x = 0; - while (false !== ($file = readdir($dir_handle))) { - if ($file != "." AND $file != "..") { - $newpath = $dir.'/'.$file; - $level = explode('/',$newpath); - if ( - substr(strtolower($newpath), -4) == ".svn" || - substr(strtolower($newpath), -4) == ".git" || - substr(strtolower($newpath), -3) == ".db" || - substr(strtolower($newpath), -4) == ".jpg" || - substr(strtolower($newpath), -4) == ".gif" || - substr(strtolower($newpath), -4) == ".png" || - substr(strtolower($newpath), -4) == ".ico" || - substr(strtolower($newpath), -4) == ".ttf" - ) { - //ignore certain files (and folders) - } - else { - $dir_array[] = $newpath; - } - if ($x > 1000) { break; } - $x++; +function recur_dir($dir) { + clearstatcache(); + $html_dir_list = ''; + $html_file_list = ''; + $dir_handle = opendir($dir); + $dir_array = array(); + if (($dir_handle)) { + $x = 0; + while (false !== ($file = readdir($dir_handle))) { + if ($file != "." and $file != "..") { + $newpath = $dir . '/' . $file; + $level = explode('/', $newpath); + if ( + substr(strtolower($newpath), -4) == ".svn" || + substr(strtolower($newpath), -4) == ".git" || + substr(strtolower($newpath), -3) == ".db" || + substr(strtolower($newpath), -4) == ".jpg" || + substr(strtolower($newpath), -4) == ".gif" || + substr(strtolower($newpath), -4) == ".png" || + substr(strtolower($newpath), -4) == ".ico" || + substr(strtolower($newpath), -4) == ".ttf" + ) { + //ignore certain files (and folders) + } else { + $dir_array[] = $newpath; } + if ($x > 1000) { + break; + } + $x++; } } + } - asort($dir_array); - foreach ($dir_array as $newpath){ - $level = explode('/',$newpath); - - if (is_dir($newpath)) { - $dirname = end($level); - $html_dir_list .= "
\n"; - $html_dir_list .= "".$dirname.""; - $html_dir_list .= "
".recur_dir($newpath)."
\n"; - $html_dir_list .= "
\n"; - } - else { - $filename = end($level); - $filesize = round(filesize($newpath)/1024, 2); - $newpath = str_replace ('//', '/', $newpath); - $newpath = str_replace ("\\", "/", $newpath); - $html_file_list .= "
\n"; - $html_file_list .= ""; - $html_file_list .= "".$filename."\n"; - $html_file_list .= "
\n"; - } + asort($dir_array); + foreach ($dir_array as $new_path) { + $level = explode('/', $new_path); + + if (is_dir($new_path)) { + $dirname = end($level); + $html_dir_list .= "
\n"; + $html_dir_list .= "folder$dirname"; + $html_dir_list .= "
" . recur_dir($new_path) . "
\n"; + $html_dir_list .= "
\n"; + } else { + $filename = end($level); + $filesize = round(filesize($new_path) / 1024, 2); + $new_path = str_replace('//', '/', $new_path); + $new_path = str_replace("\\", "/", $new_path); + $html_file_list .= "
\n"; + $html_file_list .= ""; + $html_file_list .= "file$filename\n"; + $html_file_list .= "
\n"; } - - closedir($dir_handle); - return $html_dir_list ."\n". $html_file_list; } + closedir($dir_handle); + return $html_dir_list . "\n" . $html_file_list; +} + //get the directory if (!isset($_SESSION)) { session_start(); } + switch ($_SESSION["app"]["edit"]["dir"]) { case 'scripts': $edit_directory = $settings->get('switch', 'scripts'); @@ -119,43 +136,23 @@ function recur_dir($dir) { case "Linux": if (file_exists('/usr/share/fusionpbx/templates/provision')) { $edit_directory = '/usr/share/fusionpbx/templates/provision'; - } - elseif (file_exists('/etc/fusionpbx/resources/templates/provision')) { + } elseif (file_exists('/etc/fusionpbx/resources/templates/provision')) { $edit_directory = '/etc/fusionpbx/resources/templates/provision'; - } - else { - $edit_directory = $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH."/resources/templates/provision"; + } else { + $edit_directory = $_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/resources/templates/provision"; } break; case "FreeBSD": - if (file_exists('/usr/local/share/fusionpbx/templates/provision')) { - $edit_directory = '/usr/share/fusionpbx/templates/provision'; - } - elseif (file_exists('/usr/local/etc/fusionpbx/resources/templates/provision')) { - $edit_directory = '/usr/local/etc/fusionpbx/resources/templates/provision'; - } - else { - $edit_directory = $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH."/resources/templates/provision"; - } - break; - case "NetBSD": - if (file_exists('/usr/local/share/fusionpbx/templates/provision')) { - $edit_directory = '/usr/share/fusionpbx/templates/provision'; - } - else { - $edit_directory = $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH."/resources/templates/provision"; - } - break; case "OpenBSD": + case "NetBSD": if (file_exists('/usr/local/share/fusionpbx/templates/provision')) { $edit_directory = '/usr/share/fusionpbx/templates/provision'; - } - else { - $edit_directory = $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH."/resources/templates/provision"; + } else { + $edit_directory = $_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/resources/templates/provision"; } break; default: - $edit_directory = $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH."/resources/templates/provision/"; + $edit_directory = $_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/resources/templates/provision/"; } break; case 'xml': @@ -167,8 +164,7 @@ function recur_dir($dir) { } // keyboard shortcut bindings -echo "\n"; -echo "\n"; +echo "\n"; //save file key_press('ctrl+s', 'down', 'window', null, null, "$('form#frm_edit').submit(); return false;", true); @@ -182,13 +178,16 @@ function recur_dir($dir) { echo "\n"; echo "\n"; -echo "\n"; +echo "\n"; echo "
\n"; if (file_exists($edit_directory)) { - $edit_html_list = recur_dir($edit_directory); - - echo $edit_html_list; + echo recur_dir($edit_directory); } echo "
\n"; diff --git a/index.php b/index.php index 957b1d6..0517ff4 100644 --- a/index.php +++ b/index.php @@ -23,864 +23,683 @@ Contributor(s): Mark J Crane James Rose - */ +*/ -//includes files +// Include required files and check access require_once dirname(__DIR__, 2) . "/resources/require.php"; require_once "resources/check_auth.php"; -//check permissions -if (permission_exists('edit_view')) { - //access granted -} else { - echo "access denied"; - exit; +if (!permission_exists('edit_view')) { + echo "access denied"; + exit; } -//add multi-lingual support -$language = new text; +$domain_uuid = $_SESSION['domain_uuid'] ?? ''; +$user_uuid = $_SESSION['user_uuid'] ?? ''; + +// Add multi-lingual support +$language = new text(); $text = $language->get(); -//set the directory title and mode +// Set the directory title and mode based on the query parameter switch ($_GET["dir"]) { - case 'xml': - $title = 'XML'; - $mode = 'xml'; - $dir = 'xml'; - break; - case 'provision': - $title = 'Provision'; - $mode = 'xml'; - $dir = 'provision'; - break; - case 'php': - $title = 'PHP'; - $mode = 'php'; - $dir = 'php'; - break; - case 'scripts': - $title = 'Scripts'; - $mode = 'lua'; - $dir = 'scripts'; - break; - case 'grammar': - $title = 'Grammar'; - $mode = 'xml'; - $dir = 'grammar'; - break; - default: - $mode = 'text'; - $dir = ''; + case 'xml': + $title = 'XML'; + $mode = 'xml'; + $dir = 'xml'; + break; + case 'provision': + $title = 'Provision'; + $mode = 'xml'; + $dir = 'provision'; + break; + case 'php': + $title = 'PHP'; + $mode = 'php'; + $dir = 'php'; + break; + case 'scripts': + $title = 'Scripts'; + $mode = 'lua'; + $dir = 'scripts'; + break; + case 'grammar': + $title = 'Grammar'; + $mode = 'xml'; + $dir = 'grammar'; + break; + default: + $mode = 'text'; + $dir = ''; } -//save the sanitized value +// Save the sanitized directory $_SESSION['app']['edit']['dir'] = $dir; -//load editor preferences/defaults +// Ensure the database and settings objects are created +global $database; +if (empty($database) || !($database instanceof database)) { + $database = database::new(); +} +if (empty($settings) || !($settings instanceof settings)) { + $settings = new settings(['database' => $database, 'domain_uuid' => $domain_uuid, 'user_uuid' => $user_uuid]); +} + +// Load editor preferences/defaults $setting_size = $settings->get('editor', 'font_size', '12px'); $setting_theme = $settings->get('editor', 'theme', 'cobalt'); $setting_invisibles = $settings->get('editor', 'invisibles', 'false'); $setting_indenting = $settings->get('editor', 'indent_guides', 'false'); $setting_numbering = $settings->get('editor', 'line_numbers', 'true'); -//get and then set the favicon +// Get the favicon $favicon = $settings->get('theme', 'favicon', PROJECT_ROOT . '/themes/default/favicon.ico'); -//create a token +// Create a token for file saving $key_name = '/app/edit/' . $mode; $_SESSION['keys'][$key_name] = bin2hex(random_bytes(32)); $_SESSION['token'] = hash_hmac('sha256', $key_name, $_SESSION['keys'][$key_name]); -//The buffer must be empty -while (ob_get_level() > 0) - ob_get_clean(); -?> +// Make sure the output buffer is empty +while (ob_get_level() > 0) { + ob_get_clean(); +} +?> + - - - <?php echo $title; ?> - - - - - - - -
- -
-
- Loading... -
-
- Loading... -
-
-
-
-
-
-
-
-
-
- - -
-
 
- -
- - - -
-
- -
-
- -
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
- -
-
- -
-
-
-
-
-
-
-
-
-
- - - - + + + + + + +
+ +
+
Loading file list...
+
Loading clips...
+
+ +
+ +
+
    +
    + + + + + + + +
    +
    + +
    +
    +
    + +
    +   + New File +
    + Line: + Column: +
    +
    + + +
    +
    + + - \ No newline at end of file + } + + + diff --git a/resources/get_php_methods.php b/resources/get_php_methods.php index d531ef7..cf5cbfa 100644 --- a/resources/get_php_methods.php +++ b/resources/get_php_methods.php @@ -1,81 +1,136 @@ [], + 'functions' => [] +]; + +// Get the list of classes and interfaces. $classes_to_scan = $autoload->get_class_list(); $interfaces = array_keys($autoload->get_interfaces()); +// Scan each class. foreach ($classes_to_scan as $class => $path) { - // Skip interfaces - if (in_array($class, $interfaces)) { - continue; - } - // Guard against removed classes - if (!class_exists($class)) { - continue; - } + // Skip interfaces and ensure the class actually exists. + if (in_array($class, $interfaces) || !class_exists($class)) { + continue; + } - // Create the RefectionClass for inspecting class - $ref = new ReflectionClass($class); + $ref = new ReflectionClass($class); - // Skip internal classes - if ($ref->isInternal()) { - continue; - } + // Skip internal PHP classes. + if ($ref->isInternal()) { + continue; + } - $methods = []; - foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { - // Skip __construct - if ($method->getName() === '__construct') { - continue; - } + $methods = []; + // Scan only public methods. + foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { - // Get method parameters - $params = []; - foreach ($method->getParameters() as $param) { - $type = $param->hasType() ? $param->getType() . " " : ""; - $default = ""; - if ($param->isOptional() && $param->isDefaultValueAvailable()) { - $default = " = " . var_export($param->getDefaultValue(), true); - } - $params[] = $type . "$" . $param->getName() . $default; - } + // Skip constructors. + if ($method->getName() === '__construct') { + continue; + } + + // Build a string for all method parameters. + $params = []; + foreach ($method->getParameters() as $param) { + $type = $param->hasType() ? $param->getType() . " " : ""; + $default = ""; + if ($param->isOptional() && $param->isDefaultValueAvailable()) { + $default = " = " . var_export($param->getDefaultValue(), true); + } + $params[] = $type . '$' . $param->getName() . $default; + } // Get the doc comment and clean it up $doc = $method->getDocComment(); if ($doc !== false) { + // Remove the /** and */ markers $doc = trim(preg_replace('/(^\/\*\*|\*\/$)/', '', $doc)); + // Remove the leading asterisks and any whitespace that follows on each line $doc = preg_replace('/^\s*\*\s?/m', '', $doc); + // Remove any additional indentation (leading white space) on each line + $doc = preg_replace('/^\s+/m', '', $doc); } else { - $doc = ""; + $doc = "No documentation found"; } - // Get the return type, if any - $return_type = ""; - if ($method->hasReturnType()) { - $rt = $method->getReturnType(); - $return_type = $rt->getName(); - if ($rt->allowsNull()) { - $return_type = "?" . $return_type; - } - } + // Get the return type string. + $return_type = ""; + if ($method->hasReturnType()) { + $rt = $method->getReturnType(); + $return_type = $rt->getName(); + if ($rt->allowsNull()) { + $return_type = '?' . $return_type; + } + } - $methods[] = [ - "name" => $method->getName(), - "params" => "(" . implode(", ", $params) . ")", - "doc" => $doc, - "static" => $method->isStatic(), - "meta" => $return_type - ]; + $methods[] = [ + "name" => $method->getName(), + "params" => "(" . implode(", ", $params) . ")", + "doc" => "\n" . $doc, + "static" => $method->isStatic(), + "meta" => $return_type + ]; + } + + // Only add the class if it has public methods. + if (!empty($methods)) { + $result['classes'][$class] = $methods; + } +} + +// Add global (user-defined) functions. +$globalFunctions = get_defined_functions()['user']; +foreach ($globalFunctions as $funcName) { + $reflection = new ReflectionFunction($funcName); + + $params = []; + foreach ($reflection->getParameters() as $parameter) { + $type = $parameter->hasType() ? $parameter->getType() . " " : ""; + $default = ""; + if ($parameter->isOptional() && $parameter->isDefaultValueAvailable()) { + $default = " = " . var_export($parameter->getDefaultValue(), true); + } + $params[] = $type . '$' . $parameter->getName() . $default; + } + + $returnType = $reflection->getReturnType(); + $returnTypeName = $returnType ? $returnType->getName() : ''; + + // Get the doc comment and clean it up + $doc = $reflection->getDocComment(); + if ($doc !== false) { + // Remove the /** and */ markers + $doc = trim(preg_replace('/(^\/\*\*|\*\/$)/', '', $doc)); + // Remove the leading asterisks and any whitespace that follows on each line + $doc = preg_replace('/^\s*\*\s?/m', '', $doc); + // Remove any additional indentation (leading white space) on each line + $doc = preg_replace('/^\s+/m', '', $doc); + } else { + $doc = "No documentation found"; } - $class_methods[$class] = $methods; + + $result['functions'][] = [ + "name" => $reflection->getName(), + "params" => "(" . implode(", ", $params) . ")", + "doc" => "\n" . $doc, + "static" => false, // Global functions are not static. + "meta" => $returnTypeName + ]; } header('Content-Type: application/json'); -echo json_encode($class_methods); +echo json_encode($result); +exit(); From 8123cb71d232aa9e8b121a0db36074b2f3d4cd18 Mon Sep 17 00:00:00 2001 From: Tim Fry Date: Sat, 12 Apr 2025 01:28:14 -0300 Subject: [PATCH 03/12] create updateStatusBar function --- index.php | 53 ++++++++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/index.php b/index.php index 0517ff4..9bdc1e2 100644 --- a/index.php +++ b/index.php @@ -471,9 +471,9 @@ function addTab(filePath, content) { //track by the filePath session.id = filePath; - session.message = "Read " + content.length + " bytes"; +// session.message = "Read " + content.length + " bytes"; - loadedFiles.push({filePath: filePath, fileName: fileName, session: session}); + document.getElementById('filepath').value = filePath; var tab = document.createElement('li'); tab.setAttribute('data-file', filePath); tab.innerText = fileName; @@ -494,9 +494,8 @@ function addTab(filePath, content) { }; tab.appendChild(closeBtn); document.getElementById('fileTabs').appendChild(tab); + loadedFiles.push({filePath: filePath, fileName: fileName, session: session, originalContent: content}); activateTab(filePath); - //var file = loadedFiles.find(f => f.filePath === filePath); - //status_message.innerHTML = "Read " + file.content.length + " bytes"; } function updateCursorStatus() { @@ -512,42 +511,38 @@ function activateTab(filePath) { if (activeTab) activeTab.classList.add('active'); var file = loadedFiles.find(f => f.filePath === filePath); if (file) { + document.getElementById('filepath').value = filePath; //switch the editor to the session editor.setSession(file.session); //add a listener - editor.getSession().on('change', function(delta) { - const file = getActiveFile(); - if (file) { - if (editor.getSession().getUndoManager().isClean()) { - status_message.innerHTML = ""; - status_filepath.innerHTML = "New File"; - } else { - file.session.message = "Modified"; - status_message.innerHTML = "Modified"; - file.session.tab.innerText = "*" + file.fileName; - } - //updateCursorStatus(); - } else { - status_message.innerHTML = ""; - status_filepath.innerHTML = "New File"; - } - }); + editor.getSession().on('change', updateStatusBar); //add a cursor position listener editor.selection.on('changeCursor', updateCursorStatus); + } + updateStatusBar(); + } - //set filepath - document.getElementById('filepath').value = file.filePath; - - //show status - status_message.innerHTML = file.session.message; - status_filepath.innerHTML = file.filePath; - } else { + function updateStatusBar(delta) { + const file = getActiveFile(); + if (file) { + if (file.originalContent !== editor.getSession().getValue()) { + file.session.message = "Modified"; + status_message.innerHTML = "Modified"; + status_filepath.innerHTML = file.filePath; + file.session.tab.innerText = "*" + file.fileName; + } else { + status_message.innerHTML = "Read " + file.originalContent.length + " bytes"; + status_filepath.innerHTML = file.filePath; + file.session.tab.innerText = file.fileName; + } + } else { status_message.innerHTML = ""; status_filepath.innerHTML = "New File"; } - } + updateCursorStatus(); + } // Close the tab and remove it // TODO: set a dialog if the isModified is still set From 5afd6fa6e876305cf2f18dea471e9634dd8208e5 Mon Sep 17 00:00:00 2001 From: Tim Fry Date: Sat, 12 Apr 2025 02:05:27 -0300 Subject: [PATCH 04/12] fix * showing on file tab --- index.php | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/index.php b/index.php index 9bdc1e2..d9c3da0 100644 --- a/index.php +++ b/index.php @@ -382,16 +382,16 @@ function submit_check() { function getOptions() { // Set Editor Options return { - mode: 'ace/mode/', + mode: 'ace/mode/', theme: 'ace/theme/' + document.getElementById('theme').value, selectionStyle: 'text', cursorStyle: 'smooth', - showInvisibles: , - displayIndentGuides: , - showLineNumbers: , + showInvisibles: , + displayIndentGuides: , + showLineNumbers: , showGutter: true, scrollPastEnd: true, - fadeFoldWidgets: , + fadeFoldWidgets: , showPrintMargin: false, highlightGutterLine: false, useSoftTabs: false, @@ -402,6 +402,11 @@ function getOptions() { } function save() { + let file = getActiveFile(); + if (file.originalContent === editor.getSession().getValue()) { + status_message.innerHTML = "File Not Modified."; + return; + } let formData = new FormData(); formData.append('filepath', document.getElementById('filepath').value); formData.append('content', editor.getSession().getValue()); @@ -417,7 +422,9 @@ function save() { file.originalContent = editor.getSession().getValue(); file.session.message = "File Saved."; status_message.innerHTML = "File Saved."; - file.session.tab.innerText = file.fileName; + if (file.session.tab.innerText.charAt(0) === "*") { + file.session.tab.innerText = file.session.tab.innerText.slice(1); + } } } else { alert(""); @@ -524,18 +531,23 @@ function activateTab(filePath) { updateStatusBar(); } - function updateStatusBar(delta) { + function updateStatusBar() { const file = getActiveFile(); if (file) { if (file.originalContent !== editor.getSession().getValue()) { file.session.message = "Modified"; status_message.innerHTML = "Modified"; status_filepath.innerHTML = file.filePath; - file.session.tab.innerText = "*" + file.fileName; + if (file.session.tab.innerText.charAt(0) !== "*") { + file.session.tab.innerText = "*" + file.session.tab.innerText; + } } else { status_message.innerHTML = "Read " + file.originalContent.length + " bytes"; status_filepath.innerHTML = file.filePath; - file.session.tab.innerText = file.fileName; + file.session.tab.title = file.fileName; + if (file.session.tab.innerText.charAt(0) === "*") { + file.session.tab.innerText = file.session.tab.innerText.slice(1); + } } } else { status_message.innerHTML = ""; From 8bee6d36f7814beac895c61576b34f47a2492dc5 Mon Sep 17 00:00:00 2001 From: Tim Fry Date: Sat, 12 Apr 2025 02:34:39 -0300 Subject: [PATCH 05/12] fix mode selection when changing file types --- index.php | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/index.php b/index.php index d9c3da0..1e49939 100644 --- a/index.php +++ b/index.php @@ -148,7 +148,7 @@ border-bottom: 1px solid #ccc; } /* Main Content */ - #float_content { + #ace_content { flex: 1; display: flex; flex-direction: column; @@ -247,12 +247,16 @@
    Loading clips...
    -
    +
      + + + + @@ -345,7 +349,7 @@ Column:
      - +
      - + - - + // Get the Ace language tools and set our custom completer. + const langTools = ace.require("ace/ext/language_tools"); + langTools.setCompleters([customCompleter]); + } catch (error) { + console.error("Error loading completions:", error); + } + } + + // Toolbar Functions + function toggle_option(opt) { + switch (opt) { + case 'numbering': + toggle_option_do('showLineNumbers'); + toggle_option_do('fadeFoldWidgets'); + break; + case 'invisibles': + toggle_option_do('showInvisibles'); + break; + case 'indenting': + toggle_option_do('displayIndentGuides'); + break; + } + focus_editor(); + } + + function toggle_option_do(opt_name) { + var opt_val = editor.getOption(opt_name); + editor.setOption(opt_name, ((opt_val) ? false : true)); + } + + function toggle_sidebar() { + var td_sidebar = document.getElementById('float_sidebar'); + if (td_sidebar.style.display === '') { + //document.getElementById('td_save').style.paddingLeft = '12px'; + td_sidebar.style.display = 'none'; + } else { + //document.getElementById('td_save').style.paddingLeft = '0'; + td_sidebar.style.display = ''; + } + focus_editor(); + } + + function focus_editor() { + editor.focus(); + } + + // Call the async functions + loadFileList(); + loadClipList(); + loadAndRegisterCompletions(); + + // Setup the editor styling + editor.setOptions(getOptions()); + document.getElementById('editor').style.fontSize = document.getElementById('size').value; + + From d727a4bf69289c962ebe9065ba5e139b83edb22d Mon Sep 17 00:00:00 2001 From: Tim Fry Date: Thu, 17 Apr 2025 15:20:43 -0300 Subject: [PATCH 10/12] Put back Javascript function Toggle from accidental removal --- index.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/index.php b/index.php index 62f72cc..16c5b49 100644 --- a/index.php +++ b/index.php @@ -815,6 +815,23 @@ function focus_editor() { editor.focus(); } + // --------------------------------------------- + // --- http://www.codeproject.com/jscript/dhtml_treeview.asp + // --- Name: Easy DHTML Treeview -- + // --- Author: D.D. de Kerf -- + // --- Version: 0.2 Date: 13-6-2001 -- + // --------------------------------------------- + function Toggle(node) { + // Unfold the branch if it isn't visible + if (node.nextSibling.style.display === 'none') { + node.nextSibling.style.display = 'block'; + } + // Collapse the branch if it IS visible + else { + node.nextSibling.style.display = 'none'; + } + } + // Call the async functions loadFileList(); loadClipList(); From 5eca7486d9c2a5b448d9c3c8f434c3eb73bb263e Mon Sep 17 00:00:00 2001 From: Tim Fry Date: Thu, 17 Apr 2025 15:21:09 -0300 Subject: [PATCH 11/12] More comments and code cleanup --- file_list.php | 69 +++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/file_list.php b/file_list.php index 00a7448..cd0c0a9 100644 --- a/file_list.php +++ b/file_list.php @@ -64,35 +64,40 @@ function recur_dir($dir) { $html_file_list = ''; $dir_handle = opendir($dir); $dir_array = array(); - if (($dir_handle)) { - $x = 0; - while (false !== ($file = readdir($dir_handle))) { - if ($file != "." and $file != "..") { - $newpath = $dir . '/' . $file; - $level = explode('/', $newpath); - if ( - substr(strtolower($newpath), -4) == ".svn" || - substr(strtolower($newpath), -4) == ".git" || - substr(strtolower($newpath), -3) == ".db" || - substr(strtolower($newpath), -4) == ".jpg" || - substr(strtolower($newpath), -4) == ".gif" || - substr(strtolower($newpath), -4) == ".png" || - substr(strtolower($newpath), -4) == ".ico" || - substr(strtolower($newpath), -4) == ".ttf" - ) { - //ignore certain files (and folders) - } else { - $dir_array[] = $newpath; - } - if ($x > 1000) { - break; - } - $x++; - } + if (!($dir_handle)) { + return; + } + $x = 0; + while (false !== ($file = readdir($dir_handle))) { + if ($file === '.' || $file === '..') { + continue; + } + $newpath = $dir . '/' . $file; + $level = explode('/', $newpath); + if ( + substr(strtolower($newpath), -4) == ".svn" || + substr(strtolower($newpath), -4) == ".git" || + substr(strtolower($newpath), -3) == ".db" || + substr(strtolower($newpath), -4) == ".jpg" || + substr(strtolower($newpath), -4) == ".gif" || + substr(strtolower($newpath), -4) == ".png" || + substr(strtolower($newpath), -4) == ".ico" || + substr(strtolower($newpath), -4) == ".ttf" + ) { + //ignore certain files (and folders) + continue; } + $dir_array[] = $newpath; + //only allow up to 1000 files + if (++$x > 1000) { break; } } + //finished with directory + closedir($dir_handle); + + //sort directories asort($dir_array); + foreach ($dir_array as $new_path) { $level = explode('/', $new_path); @@ -114,7 +119,7 @@ function recur_dir($dir) { } } - closedir($dir_handle); + //return completed html return $html_dir_list . "\n" . $html_file_list; } @@ -123,13 +128,13 @@ function recur_dir($dir) { switch ($_SESSION["app"]["edit"]["dir"]) { case 'scripts': - $edit_directory = $settings->get('switch', 'scripts'); + $edit_directory = $settings->get('switch', 'scripts', '/usr/share/freeswitch/scripts'); break; case 'php': $edit_directory = dirname(__DIR__, 2); break; case 'grammar': - $edit_directory = $settings->get('switch', 'grammar'); + $edit_directory = $settings->get('switch', 'grammar', '/usr/share/freeswitch/grammar'); break; case 'provision': switch (PHP_OS) { @@ -139,7 +144,7 @@ function recur_dir($dir) { } elseif (file_exists('/etc/fusionpbx/resources/templates/provision')) { $edit_directory = '/etc/fusionpbx/resources/templates/provision'; } else { - $edit_directory = $_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/resources/templates/provision"; + $edit_directory = dirname(__DIR__, 2) . "/resources/templates/provision"; } break; case "FreeBSD": @@ -148,15 +153,15 @@ function recur_dir($dir) { if (file_exists('/usr/local/share/fusionpbx/templates/provision')) { $edit_directory = '/usr/share/fusionpbx/templates/provision'; } else { - $edit_directory = $_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/resources/templates/provision"; + $edit_directory = dirname(__DIR__, 2) . "/resources/templates/provision"; } break; default: - $edit_directory = $_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/resources/templates/provision/"; + $edit_directory = dirname(__DIR__, 2) . "/resources/templates/provision/"; } break; case 'xml': - $edit_directory = $settings->get('switch', 'conf'); + $edit_directory = $settings->get('switch', 'conf', '/etc/freeswitch/autoload_configs'); break; default: //do not allow unknown settings From 260f4878ed7c31bf9ae33d3717c44948917da407 Mon Sep 17 00:00:00 2001 From: Tim Fry Date: Thu, 17 Apr 2025 15:27:28 -0300 Subject: [PATCH 12/12] fix image and text to align on same pixel line --- file_list.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/file_list.php b/file_list.php index cd0c0a9..66ef744 100644 --- a/file_list.php +++ b/file_list.php @@ -104,7 +104,7 @@ function recur_dir($dir) { if (is_dir($new_path)) { $dirname = end($level); $html_dir_list .= "
      \n"; - $html_dir_list .= "folder$dirname"; + $html_dir_list .= "folder$dirname"; $html_dir_list .= "
      " . recur_dir($new_path) . "
      \n"; $html_dir_list .= "
      \n"; } else { @@ -114,7 +114,7 @@ function recur_dir($dir) { $new_path = str_replace("\\", "/", $new_path); $html_file_list .= "
      \n"; $html_file_list .= ""; - $html_file_list .= "file$filename\n"; + $html_file_list .= "file$filename\n"; $html_file_list .= "
      \n"; } }