Constructed menu; moved files to sub newton folder; WIP save system added
This commit is contained in:
parent
ae43722881
commit
82e2afa601
79
newton/app.js
Normal file
79
newton/app.js
Normal file
@ -0,0 +1,79 @@
|
||||
const { BrowserWindow } = require('electron');
|
||||
const path = require('node:path');
|
||||
|
||||
const { menu } = require('./menu');
|
||||
const { newtonFs } = require('./fs');
|
||||
|
||||
|
||||
const BASE_PATH = '../dist/app';
|
||||
const ICON_PATH = `${BASE_PATH}/resources/newton.png`;
|
||||
|
||||
let args = [];
|
||||
|
||||
|
||||
|
||||
// Note: https://tinydew4.gitbooks.io/electron/content/api/browser-window.html
|
||||
const createWindow = (startType = "build", debug = false, args = []) => {
|
||||
this.args = args;
|
||||
|
||||
const win = new BrowserWindow({
|
||||
title: "Newton",
|
||||
width: 800,
|
||||
height: 600,
|
||||
minWidth: 800,
|
||||
minHeight: 600,
|
||||
show: false,
|
||||
transparent: true,
|
||||
icon: path.join(__dirname, ICON_PATH),
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
contextIsolation: true,
|
||||
enableRemoteModule: false,
|
||||
plugins: true,
|
||||
webSecurity: true,
|
||||
sandbox: true,
|
||||
}
|
||||
});
|
||||
|
||||
win.once('ready-to-show', () => {
|
||||
win.show()
|
||||
});
|
||||
|
||||
menu.load(win);
|
||||
|
||||
// win.setAutoHideMenuBar(true)
|
||||
|
||||
if (debug == true) {
|
||||
win.webContents.openDevTools();
|
||||
}
|
||||
|
||||
if (startType === "build") {
|
||||
win.loadFile(
|
||||
path.join(__dirname, `${BASE_PATH}/index.html`)
|
||||
);
|
||||
}
|
||||
|
||||
if (startType === "ng-serve") {
|
||||
win.loadURL('http://localhost:4200');
|
||||
}
|
||||
|
||||
// const child = new BrowserWindow({parent: win, modal: true, show: false})
|
||||
// child.loadFile(
|
||||
// path.join(__dirname, `${BASE_PATH}/index.html`)
|
||||
// );
|
||||
// child.once('ready-to-show', () => {
|
||||
// child.show()
|
||||
// });
|
||||
|
||||
return win;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
newton: {
|
||||
createWindow: createWindow,
|
||||
fs: newtonFs,
|
||||
}
|
||||
};
|
96
newton/fs.js
Normal file
96
newton/fs.js
Normal file
@ -0,0 +1,96 @@
|
||||
const { dialog } = require('electron');
|
||||
const path = require('node:path');
|
||||
const fs = require('node:fs');
|
||||
const os = require('os')
|
||||
|
||||
|
||||
|
||||
const BASE_PATH = '../dist/app';
|
||||
const LSP_CONFIG_PATH = `${BASE_PATH}/resources/lsp-servers-config.json`;
|
||||
let window = null;
|
||||
|
||||
|
||||
|
||||
const getFileContents = (_path, useRelativePath = false) => {
|
||||
console.log(`Getting Contents For: ${_path}`);
|
||||
|
||||
try {
|
||||
if (!useRelativePath) {
|
||||
return fs.readFileSync(_path, 'utf8');
|
||||
} else {
|
||||
return fs.readFileSync(path.join(__dirname, _path), 'utf8');
|
||||
}
|
||||
} catch(err) {
|
||||
return `{"message": {"type": "error", "text": "Error: Could not read ${_path}"}}`;
|
||||
}
|
||||
}
|
||||
|
||||
const getLspConfigData = () => {
|
||||
const config = getFileContents(LSP_CONFIG_PATH, true);
|
||||
return config.replaceAll("{user.home}", os.homedir());
|
||||
}
|
||||
|
||||
const saveFile = (fpath, content) => {
|
||||
fs.writeFile(fpath, content, (err) => {
|
||||
if (!err) return
|
||||
console.error("An error ocurred writing to the file " + err.message)
|
||||
});
|
||||
}
|
||||
|
||||
const saveFileAs = (content) => {
|
||||
dialog.showSaveDialog().then((response) => {
|
||||
if (response.canceled) {
|
||||
console.log("You didn't save the file");
|
||||
return;
|
||||
}
|
||||
|
||||
saveFile(response.filePath, content);
|
||||
});
|
||||
}
|
||||
|
||||
const openFiles = (startPath) => {
|
||||
dialog.showOpenDialog(
|
||||
{
|
||||
title: "Open File(s):",
|
||||
defaultPath: (startPath) ? startPath : os.homedir(),
|
||||
filters: [
|
||||
{"c": [".h", ".c"]},
|
||||
{"cpp": ["hpp", "cpp"]},
|
||||
{"html": ["js", "css", "scss", "html", "ts"]},
|
||||
{"java": ["java"]},
|
||||
{"python": ["py", "pyc"]},
|
||||
{"rust": ["r", "rc"]},
|
||||
{"text": ["txt", "log", "md"]},
|
||||
{"go": ["go"]},
|
||||
],
|
||||
properties: [
|
||||
'openFile',
|
||||
'multiSelections'
|
||||
]
|
||||
}
|
||||
).then((response) => {
|
||||
if (response.canceled) {
|
||||
console.log("Canceled file open request...");
|
||||
return;
|
||||
}
|
||||
|
||||
window.webContents.send('load-files', response.filePaths);
|
||||
});
|
||||
}
|
||||
|
||||
const setWindow = (win) => {
|
||||
window = win;
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
newtonFs: {
|
||||
openFiles: openFiles,
|
||||
saveFile: saveFile,
|
||||
saveFileAs: saveFileAs,
|
||||
getFileContents: getFileContents,
|
||||
getLspConfigData: getLspConfigData,
|
||||
setWindow: setWindow
|
||||
}
|
||||
};
|
@ -3,11 +3,9 @@ try {
|
||||
} catch {}
|
||||
|
||||
|
||||
const { app, ipcMain } = require('electron');
|
||||
|
||||
const { app, ipcMain, dialog } = require('electron');
|
||||
const { newton } = require('./app');
|
||||
const path = require('node:path');
|
||||
const fs = require('node:fs');
|
||||
|
||||
|
||||
|
||||
@ -39,45 +37,24 @@ const loadArgs = () => {
|
||||
console.log(index + ': ' + val);
|
||||
console.log();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const saveFile = (path, content) => {
|
||||
console.log("...");
|
||||
}
|
||||
|
||||
const saveFileAs = (content) => {
|
||||
console.log(content);
|
||||
dialog.showSaveDialog((fileName) => {
|
||||
console.log(fileName);
|
||||
|
||||
if (fileName === undefined){
|
||||
console.log("You didn't save the file");
|
||||
return;
|
||||
}
|
||||
|
||||
// fileName is a string that contains the path and filename created in the save file dialog.
|
||||
fs.writeFile(fileName, content, (err) => {
|
||||
if(err){
|
||||
alert("An error ocurred creating the file "+ err.message)
|
||||
}
|
||||
|
||||
alert("The file has been succesfully saved");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const loadHandlers = () => {
|
||||
ipcMain.handle('getLspConfigData', (eve) => newton.getLspConfigData());
|
||||
ipcMain.handle('getFileContents', (eve, file) => newton.getFileContents(file));
|
||||
ipcMain.handle('saveFile', (eve, path, content) => saveFile(path, "Some text to save into the file"));
|
||||
ipcMain.handle('saveFileAs', (eve, content) => saveFileAs("Some text to save into the file"));
|
||||
ipcMain.handle('getLspConfigData', (eve) => newton.fs.getLspConfigData());
|
||||
ipcMain.handle('getFileContents', (eve, file) => newton.fs.getFileContents(file));
|
||||
ipcMain.handle('openFiles', (eve, startPath) => newton.fs.openFiles(startPath));
|
||||
ipcMain.handle('saveFile', (eve, path, content) => newton.fs.saveFile(path, content));
|
||||
ipcMain.handle('saveFileAs', (eve, content) => newton.fs.saveFileAs(content));
|
||||
}
|
||||
|
||||
|
||||
app.whenReady().then(() => {
|
||||
loadArgs();
|
||||
loadHandlers();
|
||||
newton.createWindow(startType, isDebug, args);
|
||||
|
||||
let window = newton.createWindow(startType, isDebug, args);
|
||||
|
||||
newton.fs.setWindow(window);
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
@ -1,53 +1,8 @@
|
||||
const { BrowserWindow, Menu } = require('electron');
|
||||
const path = require('node:path');
|
||||
const fs = require('node:fs');
|
||||
const os = require('os')
|
||||
const { Menu } = require('electron');
|
||||
|
||||
|
||||
|
||||
// const BASE_PATH = 'dist/app/browser';
|
||||
const BASE_PATH = 'dist/app';
|
||||
const ICON_PATH = `${BASE_PATH}/resources/newton.png`;
|
||||
const LSP_CONFIG_PATH = `${BASE_PATH}/resources/lsp-servers-config.json`;
|
||||
let args = [];
|
||||
|
||||
|
||||
|
||||
const createWindow = (startType = "build", debug = false, args = []) => {
|
||||
this.args = args;
|
||||
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
transparent: true,
|
||||
icon: path.join(__dirname, ICON_PATH),
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
contextIsolation: true,
|
||||
enableRemoteModule: false,
|
||||
}
|
||||
});
|
||||
|
||||
setupMenu(win);
|
||||
|
||||
// win.setAutoHideMenuBar(true)
|
||||
|
||||
if (debug == true) {
|
||||
win.webContents.openDevTools();
|
||||
}
|
||||
|
||||
if (startType === "build") {
|
||||
win.loadFile(
|
||||
path.join(__dirname, `${BASE_PATH}/index.html`)
|
||||
);
|
||||
}
|
||||
|
||||
if (startType === "ng-serve") {
|
||||
win.loadURL('http://localhost:4200');
|
||||
}
|
||||
}
|
||||
|
||||
const setupMenu = (win) => {
|
||||
const load = (win) => {
|
||||
const menu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: "File",
|
||||
@ -57,16 +12,16 @@ const setupMenu = (win) => {
|
||||
click: () => win.webContents.send('menu-actions', "new-file")
|
||||
}, {
|
||||
label: 'Open',
|
||||
click: () => win.webContents.send('load-files', [path.join(__dirname, `${BASE_PATH}/index.html`)])
|
||||
}, {
|
||||
label: 'Terminal',
|
||||
click: () => {}
|
||||
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: () => {}
|
||||
}
|
||||
]
|
||||
}, {
|
||||
@ -140,31 +95,10 @@ const setupMenu = (win) => {
|
||||
Menu.setApplicationMenu(menu)
|
||||
}
|
||||
|
||||
const getFileContents = (_path, useRelativePath = false) => {
|
||||
console.log(`Getting Contents For: ${_path}`);
|
||||
|
||||
try {
|
||||
if (!useRelativePath) {
|
||||
return fs.readFileSync(_path, 'utf8');
|
||||
} else {
|
||||
return fs.readFileSync(path.join(__dirname, _path), 'utf8');
|
||||
}
|
||||
} catch(err) {
|
||||
return `{"message": {"type": "error", "text": "Error: Could not read ${_path}"}}`;
|
||||
}
|
||||
}
|
||||
|
||||
const getLspConfigData = () => {
|
||||
const config = getFileContents(LSP_CONFIG_PATH, true);
|
||||
return config.replaceAll("{user.home}", os.homedir());
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
newton: {
|
||||
createWindow: createWindow,
|
||||
getFileContents: getFileContents,
|
||||
getLspConfigData: getLspConfigData
|
||||
menu: {
|
||||
load: load
|
||||
}
|
||||
};
|
@ -13,8 +13,9 @@ contextBridge.exposeInMainWorld('main', {
|
||||
contextBridge.exposeInMainWorld('fs', {
|
||||
getLspConfigData: () => ipcRenderer.invoke("getLspConfigData"),
|
||||
getFileContents: (file) => ipcRenderer.invoke("getFileContents", file),
|
||||
openFiles: (startPath) => ipcRenderer.invoke("openFiles", startPath),
|
||||
saveFile: (path, content) => ipcRenderer.invoke("saveFile", path, content),
|
||||
saveFileAs: (content) => ipcRenderer.invoke("saveFileAs", content),
|
||||
getPathForFile: (file) => webUtils.getPathForFile(file),
|
||||
onLoadFiles: (callback) => ipcRenderer.on('load-files', (_event, files) => callback(files)),
|
||||
});
|
||||
});
|
@ -2,7 +2,7 @@
|
||||
"name": "Newton Editor",
|
||||
"version": "0.0.1",
|
||||
"description": "A uniquly simple quasi-IDE for hardcore developers.",
|
||||
"main": "main.js",
|
||||
"main": "newton/main.js",
|
||||
"scripts": {
|
||||
"app": "ng build --base-href ./ && electron . --trace-warnings --start-as=build",
|
||||
"electron-build": "electron . --trace-warnings --start-as=build",
|
||||
|
@ -19,6 +19,7 @@ declare global {
|
||||
fs: {
|
||||
getLspConfigData: () => Promise<string>,
|
||||
getFileContents: (arg0: any) => Promise<string>,
|
||||
openFiles: (arg0) => Promise<string>,
|
||||
saveFile: (arg0: any, arg1: any) => Promise<string>,
|
||||
saveFileAs: (arg0: any) => Promise<string>,
|
||||
getPathForFile: any,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Directive, ElementRef, Input, ViewChild } from '@angular/core';
|
||||
|
||||
import { EditorSettings } from "../../common/configs/editor.config";
|
||||
import { NewtonFile } from '../../common/types/file.type';
|
||||
|
||||
|
||||
|
||||
@ -12,6 +13,7 @@ export class AceEditorBase {
|
||||
uuid!: string;
|
||||
cutBuffer: string = "";
|
||||
timerId: number = -1;
|
||||
activeFile!: NewtonFile;
|
||||
|
||||
|
||||
constructor(
|
||||
@ -22,9 +24,25 @@ export class AceEditorBase {
|
||||
console.log(this.editor.getSession()["$modeId"])
|
||||
}
|
||||
|
||||
protected openFiles() {
|
||||
let startDir = "";
|
||||
if (this.activeFile) {
|
||||
let pathParts = this.activeFile.path.split("/");
|
||||
pathParts.pop();
|
||||
startDir = pathParts.join( '/' );
|
||||
}
|
||||
|
||||
window.fs.openFiles(startDir);
|
||||
}
|
||||
|
||||
protected saveFile() {
|
||||
const text = this.editor.session.getValue();
|
||||
// window.fs.saveFile(text);
|
||||
if (!this.activeFile) {
|
||||
this.saveFileAs();
|
||||
return;
|
||||
}
|
||||
|
||||
const text = this.activeFile.session.getValue();
|
||||
window.fs.saveFile(this.activeFile.path, text);
|
||||
}
|
||||
|
||||
protected saveFileAs() {
|
||||
|
@ -109,6 +109,13 @@ export class AceEditorComponent extends AceEditorBase {
|
||||
this.editor.session.destroy();
|
||||
},
|
||||
readOnly: true
|
||||
}, {
|
||||
name: "openFiles",
|
||||
bindKey: {win: "ctrl-o", mac: "ctrl-o"},
|
||||
exec: () => {
|
||||
this.openFiles();
|
||||
},
|
||||
readOnly: true
|
||||
}, {
|
||||
name: "saveFile",
|
||||
bindKey: {win: "ctrl-s", mac: "ctrl-s"},
|
||||
|
@ -75,8 +75,8 @@ export class EditorsComponent {
|
||||
this.addTab(file);
|
||||
}
|
||||
|
||||
let session = this.files.get(paths[ paths.length - 1 ]).session;
|
||||
this.setSession(session);
|
||||
let file = this.files.get(paths[ paths.length - 1 ]);
|
||||
this.setSession(file);
|
||||
});
|
||||
|
||||
window.main.onMenuActions(async (action: string) => {
|
||||
@ -86,6 +86,9 @@ export class EditorsComponent {
|
||||
switch ( action ) {
|
||||
case "new-file":
|
||||
break;
|
||||
case "open-files":
|
||||
editorComponent.openFiles();
|
||||
break;
|
||||
case "save-file":
|
||||
editorComponent.saveFile();
|
||||
break;
|
||||
@ -130,23 +133,25 @@ export class EditorsComponent {
|
||||
}
|
||||
|
||||
protected onFileDropped(files: any) {
|
||||
this.loadFilesList(files).then((session: EditSession | undefined | null) => {
|
||||
this.setSession(session);
|
||||
this.loadFilesList(files).then((file: NewtonFile | undefined | null) => {
|
||||
this.setSession(file);
|
||||
});
|
||||
}
|
||||
|
||||
private async setSession(session: EditSession | undefined | null) {
|
||||
if ( !session ) return;
|
||||
private async setSession(file: NewtonFile | undefined | null) {
|
||||
if ( !file ) return;
|
||||
let editorComponent = this.getActiveEditorComponent();
|
||||
let editor = editorComponent.editor;
|
||||
|
||||
let editor = this.getActiveEditor();
|
||||
editor?.setSession(session);
|
||||
editorComponent.activeFile = file;
|
||||
editor.setSession(file.session);
|
||||
}
|
||||
|
||||
private getSession() {
|
||||
let editorComponent = this.editors.get(this.activeEditor)?.instance;
|
||||
let editor = editorComponent.editor;
|
||||
|
||||
return editor?.getSession();
|
||||
return editor.getSession();
|
||||
}
|
||||
|
||||
private getActiveEditorComponent(): any {
|
||||
@ -159,7 +164,7 @@ export class EditorsComponent {
|
||||
return editor;
|
||||
}
|
||||
|
||||
private async loadFilesList(files: Array<NewtonFile>): Promise<EditSession | undefined | null> {
|
||||
private async loadFilesList(files: Array<NewtonFile>): Promise<NewtonFile | undefined | null> {
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
const path = window.fs.getPathForFile(file);
|
||||
@ -171,7 +176,7 @@ export class EditorsComponent {
|
||||
this.addTab(file);
|
||||
}
|
||||
|
||||
return files[ files.length - 1 ].session;
|
||||
return files[ files.length - 1 ];
|
||||
}
|
||||
|
||||
private async addFile(path: string, file: NewtonFile): Promise<void> {
|
||||
|
Loading…
Reference in New Issue
Block a user