From 9d3eb76960195693dfab10c223df65bd0961725b Mon Sep 17 00:00:00 2001
From: itdominator <1itdominator@gmail.com>
Date: Thu, 12 Jun 2025 20:31:08 -0500
Subject: [PATCH] Add system try; refactored editor naming

---
 newton/app.js                                 | 12 +++--
 newton/fs.js                                  |  7 +--
 newton/system-tray.js                         | 49 +++++++++++++++++++
 package.json                                  |  3 +-
 src/app/editor/editors.component.ts           | 10 ++--
 .../newton-editor.base.ts}                    |  6 ++-
 .../newton-editor.component.css}              |  0
 .../newton-editor.component.html}             |  0
 .../newton-editor.component.ts}               | 27 +++++++---
 src/assets/css/ace-overrides.css              | 31 ++++++++++++
 10 files changed, 124 insertions(+), 21 deletions(-)
 create mode 100644 newton/system-tray.js
 rename src/app/editor/{ace/ace-editor.base.ts => newton-editor/newton-editor.base.ts} (96%)
 rename src/app/editor/{ace/ace-editor.component.css => newton-editor/newton-editor.component.css} (100%)
 rename src/app/editor/{ace/ace-editor.component.html => newton-editor/newton-editor.component.html} (100%)
 rename src/app/editor/{ace/ace-editor.component.ts => newton-editor/newton-editor.component.ts} (88%)

diff --git a/newton/app.js b/newton/app.js
index 76370db..c5f98da 100644
--- a/newton/app.js
+++ b/newton/app.js
@@ -1,10 +1,11 @@
-const { BrowserWindow } = require('electron');
-const path = require('node:path');
+const { BrowserWindow }   = require('electron');
+const path                = require('node:path');
 
-const { menu } = require('./menu');
-const { argsParser } = require('./args-parser');
+const { menu }            = require('./menu');
+const { systemTray }      = require('./system-tray');
+const { argsParser }      = require('./args-parser');
 const { settingsManager } = require('./settings-manager');
-const { newtonFs } = require('./fs');
+const { newtonFs }        = require('./fs');
 
 
 const BASE_PATH = '../build/app';
@@ -47,6 +48,7 @@ const createWindow = (startType = "build", debug = false, args = []) => {
     });
 
     menu.load(win);
+    systemTray.load(menu.menuStruct);
 
     // win.setAutoHideMenuBar(true)
 
diff --git a/newton/fs.js b/newton/fs.js
index 7eefacb..70c7927 100644
--- a/newton/fs.js
+++ b/newton/fs.js
@@ -1,7 +1,8 @@
 const { dialog } = require('electron');
-const path = require('node:path');
-const fs   = require('node:fs');
-const os   = require('os')
+const path       = require('node:path');
+const fs         = require('node:fs');
+const os         = require('os')
+const chokidar   = require('chokidar');
 
 
 
diff --git a/newton/system-tray.js b/newton/system-tray.js
new file mode 100644
index 0000000..e9a79c5
--- /dev/null
+++ b/newton/system-tray.js
@@ -0,0 +1,49 @@
+const { Tray, Menu } = require('electron')
+const { newtonFs }   = require('./fs');
+
+
+
+const load = (win) => {
+    let trayIcon = new Tray( newtonFs.getIconPath() );
+
+    const trayMenuTemplate = [
+        {
+            label: "File",
+            submenu: [
+                {
+                    label: 'New',
+                    click: () => win.webContents.send('menu-actions', "new-file")
+                }, {
+                    label: 'Open',
+                    click: () => win.webContents.send('menu-actions', "open-files")
+                }, {
+                    label: 'save',
+                    click: () => win.webContents.send('menu-actions', "save-file")
+                }, {
+                    label: 'Save As',
+                    click: () => win.webContents.send('menu-actions', "save-file-as")
+                }, {
+                    label: 'Terminal',
+                    click: () => {}
+                }
+            ]
+        }, {
+            label: 'Settings',
+            click: () => win.webContents.send('menu-actions', "open-settings")
+        }, {
+            label: 'Help',
+            click: () => win.webContents.send('menu-actions', "show-about")
+        }
+    ];
+     
+    trayIcon.setContextMenu(
+        Menu.buildFromTemplate(trayMenuTemplate)
+    );
+}
+
+
+module.exports = {
+    systemTray: {
+        load: load,
+    }
+};
\ No newline at end of file
diff --git a/package.json b/package.json
index 6639892..06a53c2 100644
--- a/package.json
+++ b/package.json
@@ -54,6 +54,7 @@
         "ace-linters": "1.5.3",
         "bootstrap": "5.3.6",
         "bootstrap-icons": "1.12.1",
+        "chokidar": "4.0.3",
         "express": "4.18.2",
         "rxjs": "7.8.0",
         "tslib": "2.3.0",
@@ -68,8 +69,8 @@
         "@types/jasmine": "5.1.0",
         "@types/node": "18.18.0",
         "concurrently": "9.1.2",
-        "electron-builder": "26.0.12",
         "electron": "36.2.0",
+        "electron-builder": "26.0.12",
         "electron-reloader": "1.2.3",
         "jasmine-core": "5.6.0",
         "karma": "6.4.0",
diff --git a/src/app/editor/editors.component.ts b/src/app/editor/editors.component.ts
index b45c825..6bbcc63 100644
--- a/src/app/editor/editors.component.ts
+++ b/src/app/editor/editors.component.ts
@@ -4,7 +4,7 @@ import { Subject, takeUntil } from 'rxjs';
 import { EditSession } from 'ace-builds';
 import { getModeForPath } from 'ace-builds/src-noconflict/ext-modelist';
 
-import { AceEditorComponent } from "./ace/ace-editor.component";
+import { NewtonEditorComponent } from "./newton-editor/newton-editor.component";
 import { EditorsService } from '../common/services/editor/editors.service';
 import { TabsService } from '../common/services/editor/tabs/tabs.service';
 
@@ -31,7 +31,7 @@ export class EditorsComponent {
     private unsubscribe = new Subject<void>();
 
     @ViewChild('containerRef', {read: ViewContainerRef}) containerRef!: ViewContainerRef;
-    editors: Map<string, ComponentRef<AceEditorComponent>>;
+    editors: Map<string, ComponentRef<NewtonEditorComponent>>;
     editorSettings: typeof EditorSettings;
     files: Map<string, NewtonFile>;
     activeEditor!: string;
@@ -43,7 +43,7 @@ export class EditorsComponent {
         private tabsService: TabsService
     ) {
         this.editorSettings = EditorSettings;
-        this.editors = new Map<string, ComponentRef<AceEditorComponent>>();
+        this.editors = new Map<string, ComponentRef<NewtonEditorComponent>>();
         this.files   = new Map<string, NewtonFile>();
     }
 
@@ -141,6 +141,8 @@ export class EditorsComponent {
                 case "zoom-out":
                     editorComponent.zoomOut()
                     break;
+                case "open-settings":
+                    editor.showSettingsMenu();
                 case "show-about":
                     break;
                 default:
@@ -155,7 +157,7 @@ export class EditorsComponent {
     }
 
     private createEditor() {
-        const component = this.containerRef.createComponent(AceEditorComponent);
+        const component = this.containerRef.createComponent(NewtonEditorComponent);
         component.instance.editorSettings = this.editorSettings;
         this.editors.set(component.instance.uuid, component)
 
diff --git a/src/app/editor/ace/ace-editor.base.ts b/src/app/editor/newton-editor/newton-editor.base.ts
similarity index 96%
rename from src/app/editor/ace/ace-editor.base.ts
rename to src/app/editor/newton-editor/newton-editor.base.ts
index 6c27a4e..893b9c0 100644
--- a/src/app/editor/ace/ace-editor.base.ts
+++ b/src/app/editor/newton-editor/newton-editor.base.ts
@@ -7,7 +7,7 @@ import { NewtonFile } from '../../common/types/file.type';
 
 
 @Directive()
-export class AceEditorBase {
+export class NewtonEditorBase {
     @ViewChild('editor') editorElm!: ElementRef;
     @Input() editorSettings!: typeof EditorSettings;
     editor!: any;
@@ -32,6 +32,10 @@ export class AceEditorBase {
         this.editorElm.nativeElement.classList.remove("active-editor")
     }
 
+    public commander() {
+        this.editor.execCommand("openCommandPalette");
+    }
+
     protected search() {
         console.log(this.editor.session.getMode()["$id"]);
     }
diff --git a/src/app/editor/ace/ace-editor.component.css b/src/app/editor/newton-editor/newton-editor.component.css
similarity index 100%
rename from src/app/editor/ace/ace-editor.component.css
rename to src/app/editor/newton-editor/newton-editor.component.css
diff --git a/src/app/editor/ace/ace-editor.component.html b/src/app/editor/newton-editor/newton-editor.component.html
similarity index 100%
rename from src/app/editor/ace/ace-editor.component.html
rename to src/app/editor/newton-editor/newton-editor.component.html
diff --git a/src/app/editor/ace/ace-editor.component.ts b/src/app/editor/newton-editor/newton-editor.component.ts
similarity index 88%
rename from src/app/editor/ace/ace-editor.component.ts
rename to src/app/editor/newton-editor/newton-editor.component.ts
index 60fe7d8..69ad9d9 100644
--- a/src/app/editor/ace/ace-editor.component.ts
+++ b/src/app/editor/newton-editor/newton-editor.component.ts
@@ -2,30 +2,32 @@ import { Component } from "@angular/core";
 
 // Import Ace and its modes/themes so that `ace` global is defined
 import * as ace from "ace-builds/src-noconflict/ace";
+import "ace-builds/src-noconflict/ext-settings_menu";
+import "ace-builds/src-noconflict/ext-command_bar";
+import "ace-builds/src-noconflict/ext-language_tools";
 import "ace-builds/src-noconflict/theme-one_dark";
 import "ace-builds/src-noconflict/theme-dracula";
-import "ace-builds/src-noconflict/ext-language_tools";
 
 import { InfoBarService } from '../../common/services/editor/info-bar/info-bar.service';
 import { EditorsService } from '../../common/services/editor/editors.service';
 import { LSPService } from '../../common/services/lsp.service';
 
-import { AceEditorBase } from './ace-editor.base';
+import { NewtonEditorBase } from './newton-editor.base';
 
 
 
 @Component({
-    selector: 'ace-editor',
+    selector: 'newton-editor',
     standalone: true,
     imports: [
     ],
-    templateUrl: './ace-editor.component.html',
-    styleUrl: './ace-editor.component.css',
+    templateUrl: './newton-editor.component.html',
+    styleUrl: './newton-editor.component.css',
     host: {
         'class': 'col'
     }
 })
-export class AceEditorComponent extends AceEditorBase {
+export class NewtonEditorComponent extends NewtonEditorBase {
 
 
     constructor(
@@ -52,7 +54,14 @@ export class AceEditorComponent extends AceEditorBase {
         this.editor.setOptions( this.editorSettings.CONFIG );
         // this.editor.commands.addCommands( this.editorSettings.KEYBINDINGS );
         this.editor.commands.addCommands([
-             {
+            {
+                name: "openCommandPalette2",
+                bindKey: {linux: "Command-Shift-/|F1", win: "Ctrl-Shift-/|F1"},
+                exec: () => {
+                    this.commander();
+                },
+                 readOnly: false
+            }, {
                  name: "search",
                  bindKey: {win: "ctrl-f", mac: "ctrl-f"},
                  exec: () => {
@@ -142,6 +151,10 @@ export class AceEditorComponent extends AceEditorBase {
 
 
         // Note:  https://ajaxorg.github.io/ace-api-docs/interfaces/ace.Ace.EditorEvents.html
+        this.editor.on("changeStatus", (e) => {
+            console.log(e);
+        });
+
         this.editor.on("click", () => {
             this.updateInfoBar();
         });
diff --git a/src/assets/css/ace-overrides.css b/src/assets/css/ace-overrides.css
index 7619370..0be79dc 100644
--- a/src/assets/css/ace-overrides.css
+++ b/src/assets/css/ace-overrides.css
@@ -2,6 +2,20 @@
 
 
 /* IDs */
+#ace_settingsmenu, #kbshortcutmenu {
+    background-color: rgba(0, 0, 0, 0.0);
+    color: rgba(255, 255, 255, 1.0);
+    box-shadow: -1px 4px 5px rgba(124, 124, 124, 0.64);
+    padding: 1em 0.5em 2em 1em;
+    overflow: auto;
+    position: absolute;
+    margin: 0;
+    bottom: 0;
+    right: 0;
+    top: 0;
+    z-index: 9991;
+    cursor: default;
+}
 
 
 /* CLASSES */
@@ -13,6 +27,23 @@
     background-color: #25282c !important;
 }
 
+.ace_editor.ace_autocomplete {
+    width: 300px;
+    z-index: 200000;
+    border: 1px lightgray solid;
+    position: fixed;
+    box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+    line-height: 1.4;
+    background-color: rgba(0, 0, 0, 0.0);
+    color: rgba(255, 255, 255, 1.0);
+}
+
+.ace_selected {
+    background: rgba(249, 148, 6, 0.64);
+    color: rgba(0, 0, 0, 1.0);
+    /* color: rgba(255, 255, 255, 1.0); */
+}
+
 .ace_sb-v,
 .ace_sb-h {
     width: 0.8em !important;