diff --git a/package.json b/package.json index dea9dbc..bc88893 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,9 @@ "@angular/core": "19.2.0", "@angular/forms": "19.2.0", "@angular/platform-browser": "19.2.0", - "ace-builds": "1.41.0", - "ace-linters": "1.5.3", + "ace-builds": "1.43.0", + "ace-diff": "3.0.3", + "ace-linters": "1.7.0", "bootstrap": "5.3.6", "bootstrap-icons": "1.12.1", "chokidar": "4.0.3", @@ -73,7 +74,7 @@ "karma-coverage": "2.2.0", "karma-jasmine": "5.1.0", "karma-jasmine-html-reporter": "2.1.0", - "typescript": "5.7.2", - "tslib": "2.3.0" + "tslib": "2.3.0", + "typescript": "5.7.2" } } \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 2948efc..0a1cf7c 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -3,7 +3,7 @@ import { Component } from '@angular/core'; import { InfoBarComponent } from './editor/info-bar/info-bar.component'; import { TabsComponent } from './editor/tabs/tabs.component'; import { EditorsComponent } from './editor/editors.component'; -import { FilesModalComponent } from "./common/components/modals/files-modal.component"; +import { FilesModalComponent } from "./common/components/modals/files/files-modal.component"; diff --git a/src/app/common/components/modals/files-modal.component.css b/src/app/common/components/modals/diffs/diff-modal.component.css similarity index 100% rename from src/app/common/components/modals/files-modal.component.css rename to src/app/common/components/modals/diffs/diff-modal.component.css diff --git a/src/app/common/components/modals/diffs/diff-modal.component.html b/src/app/common/components/modals/diffs/diff-modal.component.html new file mode 100644 index 0000000..856b298 --- /dev/null +++ b/src/app/common/components/modals/diffs/diff-modal.component.html @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/src/app/common/components/modals/diffs/diff-modal.component.ts b/src/app/common/components/modals/diffs/diff-modal.component.ts new file mode 100644 index 0000000..fac35da --- /dev/null +++ b/src/app/common/components/modals/diffs/diff-modal.component.ts @@ -0,0 +1,69 @@ +import { Component, inject } from "@angular/core"; +import { CommonModule } from "@angular/common"; + +import { Subject, takeUntil } from 'rxjs'; + +import * as bootstrap from "bootstrap"; + +import AceDiff from 'ace-diff'; + +import 'ace-diff/dist/ace-diff.min.css'; +import 'ace-diff/dist/ace-diff-dark.min.css'; + + + +@Component({ + selector: 'diff-modal', + standalone: true, + imports: [ + CommonModule + ], + templateUrl: './diff-modal.component.html', + styleUrl: './diff-modal.component.css', + host: { + 'class': '' + } +}) +export class DiffModalComponent { + + diffModal!: bootstrap.Modal; + + + constructor() { + } + + + private ngAfterViewInit(): void { + this.loadDiffView(); + this.loadSubscribers(); + } + + private loadDiffView() { + // Notes: https://github.com/ace-diff/ace-diff + // https://ajaxorg.github.io/ace-api-docs/classes/src_ext_diff_diff_view.DiffView.html#scrollB + /* + const differ = new AceDiff({ + ace: window.ace + element: '.diff-view', + left: { + content: 'your first file content here', + }, + right: { + content: 'your second file content here', + }, + }); + */ + } + + private loadSubscribers() { + } + + private createModal() { + this.diffModal = new bootstrap.Modal("#diffModal", {}); + } + + public showModal() { + this.diffModal?.toggle(); + } + +} \ No newline at end of file diff --git a/src/app/common/components/modals/files/files-modal.component.css b/src/app/common/components/modals/files/files-modal.component.css new file mode 100644 index 0000000..0f2a2b5 --- /dev/null +++ b/src/app/common/components/modals/files/files-modal.component.css @@ -0,0 +1,16 @@ +.modal-column { + min-height: 24em; + max-height: 24em; + overflow: auto; +} + +.close-button { + background: rgba(116, 0, 0, 0.64); + border-style: solid; + border-color: rgba(0, 0, 0, 0.64); + border-width: 1px; +} + +.close-button:hover { + background: rgba(256, 0, 0, 0.64); +} \ No newline at end of file diff --git a/src/app/common/components/modals/files-modal.component.html b/src/app/common/components/modals/files/files-modal.component.html similarity index 100% rename from src/app/common/components/modals/files-modal.component.html rename to src/app/common/components/modals/files/files-modal.component.html diff --git a/src/app/common/components/modals/files-modal.component.ts b/src/app/common/components/modals/files/files-modal.component.ts similarity index 89% rename from src/app/common/components/modals/files-modal.component.ts rename to src/app/common/components/modals/files/files-modal.component.ts index 1973c7e..069a1c1 100644 --- a/src/app/common/components/modals/files-modal.component.ts +++ b/src/app/common/components/modals/files/files-modal.component.ts @@ -5,10 +5,10 @@ import { Subject, takeUntil } from 'rxjs'; import * as bootstrap from "bootstrap"; -import { FilesModalService } from "../../services/editor/modals/files-modal.service"; -import { TabsService } from '../../services/editor/tabs/tabs.service'; +import { FilesModalService } from "../../../services/editor/modals/files-modal.service"; +import { TabsService } from '../../../services/editor/tabs/tabs.service'; -import { ServiceMessage } from '../../types/service-message.type'; +import { ServiceMessage } from '../../../types/service-message.type'; diff --git a/src/app/common/configs/editor.config.ts b/src/app/common/configs/editor.config.ts index 764686a..a92a2a2 100644 --- a/src/app/common/configs/editor.config.ts +++ b/src/app/common/configs/editor.config.ts @@ -6,10 +6,12 @@ export const EditorSettings: any = { KEYBINDINGS: Keybindings, CONFIG: { behavioursEnabled: true, + wrapBehavioursEnabled: true, fontSize: "12px", theme: "ace/theme/gruvbox", mode: "ace/mode/text", printMarginColumn: 80, + enableCodeLens: true, enableBasicAutocompletion: true, enableLiveAutocompletion: true, enableSnippets: true, @@ -19,11 +21,10 @@ export const EditorSettings: any = { tabSize: 4, navigateWithinSoftTabs: true, tooltipFollowsMouse: true, - wrapBehavioursEnabled: false, scrollPastEnd: 0.5, mergeUndoDeltas: false, showGutter: true, - customScrollbar: true, + // customScrollbar: true, scrollSpeed: 5 } }; \ No newline at end of file diff --git a/src/app/common/configs/keybindings.config.ts b/src/app/common/configs/keybindings.config.ts index f8bdf81..1584717 100644 --- a/src/app/common/configs/keybindings.config.ts +++ b/src/app/common/configs/keybindings.config.ts @@ -29,9 +29,13 @@ export const Keybindings: Array<{}> = [ bindKey: {win: "ctrl-shift-l", mac: "ctrl-shift-l"}, readOnly: false }, { - name: "search", + name: "searchPopup", bindKey: {win: "ctrl-f", mac: "ctrl-f"}, readOnly: true + }, { + name: "replacePopup", + bindKey: {win: "ctrl-r", mac: "ctrl-r"}, + readOnly: false }, { name: "newSession", bindKey: {win: "ctrl-t", mac: "ctrl-t"}, diff --git a/src/app/common/services/editor/editors.service.ts b/src/app/common/services/editor/editors.service.ts index 8efe5ba..844444d 100644 --- a/src/app/common/services/editor/editors.service.ts +++ b/src/app/common/services/editor/editors.service.ts @@ -45,11 +45,11 @@ export class EditorsService { this.editors.set(uuid, component); - if (Object.keys(this.editors).length < 1) return; + if (Array.from(this.editors.keys()).length <= 1) return; + let _editors = this.getEditorsAsArray(); let leftEditor = null; let rightEditor = null; - let _editors = this.getEditorsAsArray(); for (let i = 0; i < _editors.length; i++) { if (_editors[i].uuid !== uuid) continue; @@ -66,14 +66,9 @@ export class EditorsService { public async setSession(file: NewtonFile | undefined | null) { if ( !file ) return; - let editorComponent = this.getActiveEditorComponent(); - let editor = editorComponent.editor; - - editorComponent.activeFile = file; - this.miniMapView.activeFile = file; - - editor.setSession(file.session); - this.miniMapView.editor.setSession(file.session); + let editorComponent = this.getActiveEditorComponent(); + editorComponent.assignSession(file); + this.miniMapView.cloneSession(file); } public getSession() { @@ -89,19 +84,13 @@ export class EditorsService { if (!this.miniMapView) return; - this.miniMapView.activeFile = editorComponent.activeFile; - this.miniMapView.editor.setSession(editorComponent.editor.getSession()); + this.miniMapView.cloneSession(editorComponent.activeFile); } public getActiveEditorComponent(): any { return this.get(this.activeEditor); } - public clearminiMapView() { - this.miniMapView.newSession(); - this.miniMapView.activeFile = null; - } - protected getActiveEditor(): any { let editorComponent = this.get(this.activeEditor); let editor = editorComponent.editor; diff --git a/src/app/editor/code-view/view.base.ts b/src/app/editor/code-view/view.base.ts index 278c456..ae6785d 100644 --- a/src/app/editor/code-view/view.base.ts +++ b/src/app/editor/code-view/view.base.ts @@ -90,8 +90,12 @@ export class CodeViewBase { this.editor.showKeyboardShortcuts(); } - public search() { - console.log(this.editor.session.getMode()["$id"]); + public searchPopup() { + this.editor.execCommand("find"); + } + + public replacePopup() { + this.editor.execCommand("replace"); } public showFilesList() { @@ -161,8 +165,30 @@ export class CodeViewBase { this.editor.setHighlightGutterLine(false); this.editor.setShowFoldWidgets(false); this.editor.setShowPrintMargin(false); + + this.editorElm.nativeElement.parentElement.classList.remove("scroller"); this.editorElm.nativeElement.parentElement.classList.add("col-1"); this.editorElm.nativeElement.parentElement.classList.add("zero-margin-padding"); + + this.editor.on("click", (event) => { + event.preventDefault(); + event.stopPropagation(); + + let editorComponent = this.editorsService.getActiveEditorComponent(); + let pos = this.editor.getCursorPosition(); + + editorComponent.editor.moveCursorToPosition(pos); + editorComponent.editor.clearSelection(); + editorComponent.editor.renderer.scrollCursorIntoView(); + }); + + this.editor.on("mousewheel", (event) => { + event.preventDefault(); + event.stopPropagation(); + + let editorComponent = this.editorsService.getActiveEditorComponent(); + editorComponent.editor.renderer.scrollBy(null, event.domEvent.deltaY); + }); } public zoomIn() { @@ -223,4 +249,4 @@ export class CodeViewBase { private quit() { window.main.quit(); } -} \ No newline at end of file +} diff --git a/src/app/editor/code-view/view.component.ts b/src/app/editor/code-view/view.component.ts index 221ca59..b1739f7 100644 --- a/src/app/editor/code-view/view.component.ts +++ b/src/app/editor/code-view/view.component.ts @@ -6,6 +6,8 @@ import "ace-builds/src-noconflict/ext-settings_menu"; import "ace-builds/src-noconflict/ext-keybinding_menu"; import "ace-builds/src-noconflict/ext-command_bar"; import "ace-builds/src-noconflict/ext-prompt"; +import "ace-builds/src-noconflict/ext-code_lens"; +import "ace-builds/src-noconflict/ext-searchbox"; import "ace-builds/src-noconflict/ext-language_tools"; //import "ace-builds/src-noconflict/theme-one_dark"; //import "ace-builds/src-noconflict/theme-penguins_in_space"; @@ -26,7 +28,7 @@ import { ServiceMessage } from '../../common/types/service-message.type'; templateUrl: './view.component.html', styleUrl: './view.component.css', host: { - 'class': 'col zero-margin-padding' + 'class': 'col zero-margin-padding scroller' } }) export class CodeViewComponent extends CodeViewBase { @@ -157,6 +159,23 @@ export class CodeViewComponent extends CodeViewBase { this.editor.setSession(session); } + public assignSession(file: NewtonFile) { + if (!file) return; + + this.activeFile = file; + this.editor.setSession(file.session); + } + + public cloneSession(file: NewtonFile) { + if (!file) return; + + this.activeFile = file; + let session = ace.createEditSession(file.session.getValue()); + + session.setMode( file.session.getMode()["$id"] ); + this.editor.setSession(session); + } + protected openFiles() { let startDir = ""; if (this.activeFile) { diff --git a/src/app/editor/editors.component.ts b/src/app/editor/editors.component.ts index 3cb485a..7e5bf24 100644 --- a/src/app/editor/editors.component.ts +++ b/src/app/editor/editors.component.ts @@ -75,8 +75,7 @@ export class EditorsComponent { if (session == siblingSession) return; - siblingComponent.editor.setSession(session); - siblingComponent.activeFile = editorComponent.activeFile; + siblingComponent.assignSession(editorComponent.activeFile); editorComponent.newSession(); siblingComponent.editor.focus() @@ -90,8 +89,7 @@ export class EditorsComponent { if (session == siblingSession) return; - siblingComponent.editor.setSession(session); - siblingComponent.activeFile = editorComponent.activeFile; + siblingComponent.assignSession(editorComponent.activeFile); editorComponent.newSession(); siblingComponent.editor.focus() @@ -104,10 +102,8 @@ export class EditorsComponent { let editorComponent = this.editorsService.getActiveEditorComponent(); let editor = editorComponent.editor; - editorComponent.activeFile = file; - editor.setSession(file.session); - this.editorsService.miniMapView.editor.setSession(file.session); - this.editorsService.miniMapView.activeFile = file; + editorComponent.assignSession(file); + this.editorsService.miniMapView.cloneSession(file); } else if (message.action === "close-tab") { let file = this.filesService.get(message.filePath); let editors = this.editorsService.getEditorsAsArray(); diff --git a/src/assets/css/styles.css b/src/assets/css/styles.css index a215ddf..e3db070 100644 --- a/src/assets/css/styles.css +++ b/src/assets/css/styles.css @@ -10,7 +10,8 @@ html { } body { - background-color: rgba(64, 64, 64, 0.0) + background-color: rgba(64, 64, 64, 0.0); + overflow: hidden; }