[⚡] Added ability to create and write files
This commit is contained in:
parent
92670a1cc9
commit
355b7e7142
9 changed files with 142 additions and 36 deletions
6
package-lock.json
generated
6
package-lock.json
generated
|
|
@ -10,7 +10,6 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ptkdev/logger": "^1.8.0",
|
"@ptkdev/logger": "^1.8.0",
|
||||||
"brace": "^0.11.1",
|
|
||||||
"filer": "^1.4.1",
|
"filer": "^1.4.1",
|
||||||
"prism-code-editor": "^1.2.2",
|
"prism-code-editor": "^1.2.2",
|
||||||
"prismjs": "^1.29.0",
|
"prismjs": "^1.29.0",
|
||||||
|
|
@ -1319,11 +1318,6 @@
|
||||||
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
|
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/brace": {
|
|
||||||
"version": "0.11.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace/-/brace-0.11.1.tgz",
|
|
||||||
"integrity": "sha512-Fc8Ne62jJlKHiG/ajlonC4Sd66Pq68fFwK4ihJGNZpGqboc324SQk+lRvMzpPRuJOmfrJefdG8/7JdWX4bzJ2Q=="
|
|
||||||
},
|
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ptkdev/logger": "^1.8.0",
|
"@ptkdev/logger": "^1.8.0",
|
||||||
"brace": "^0.11.1",
|
|
||||||
"filer": "^1.4.1",
|
"filer": "^1.4.1",
|
||||||
"prism-code-editor": "^1.2.2",
|
"prism-code-editor": "^1.2.2",
|
||||||
"prismjs": "^1.29.0",
|
"prismjs": "^1.29.0",
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,7 @@ export default class EditorApp implements App {
|
||||||
version = '1.0.0'
|
version = '1.0.0'
|
||||||
|
|
||||||
async open (data?: EditorConfig): Promise<FlowWindow> {
|
async open (data?: EditorConfig): Promise<FlowWindow> {
|
||||||
const fs = new (window as any).Filer.FileSystem()
|
const win = window.wm.createWindow({
|
||||||
|
|
||||||
const win = (window as any).wm.createWindow({
|
|
||||||
title: this.name,
|
title: this.name,
|
||||||
icon,
|
icon,
|
||||||
width: 500,
|
width: 500,
|
||||||
|
|
@ -38,19 +36,114 @@ export default class EditorApp implements App {
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
win.setTitle('Editor - ' + data.path)
|
win.setTitle('Editor - ' + data.path)
|
||||||
|
|
||||||
const value = (await fs.promises.readFile(data.path)).toString()
|
win.content.style.display = 'flex'
|
||||||
|
win.content.style.flexDirection = 'column'
|
||||||
|
win.content.innerHTML = `
|
||||||
|
<div style="padding: 5px;display: flex;align-items: center;gap: 5px;">
|
||||||
|
<div id="file-open">File</div>
|
||||||
|
<div id="edit-open">Edit</div>
|
||||||
|
|
||||||
|
<div class="dropdown" id="file">
|
||||||
|
<a id="save">
|
||||||
|
<i class='bx bxs-save' style="font-size: 1.1rem;"></i>
|
||||||
|
Save
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="dropdown" id="edit">
|
||||||
|
<a id="find">
|
||||||
|
<i class='bx bxs-save' style="font-size: 1.1rem;"></i>
|
||||||
|
Find
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="editor" style="flex:1;"></div>
|
||||||
|
<style>
|
||||||
|
.dropdown {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 100;
|
||||||
|
width: 150px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
margin-top: 80px;
|
||||||
|
background: var(--surface-0);
|
||||||
|
transition: all 0.1s cubic-bezier(0.16, 1, 0.5, 1);
|
||||||
|
|
||||||
|
transform: translateY(0.5rem);
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.show {
|
||||||
|
transform: translateY(0rem);
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown a:hover {
|
||||||
|
background-color: var(--base);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`
|
||||||
|
|
||||||
|
const fileBtn = win.content.querySelector('#file-open')
|
||||||
|
const editBtn = win.content.querySelector('#edit-open')
|
||||||
|
|
||||||
|
const toggleDropdown = function (id: string): void {
|
||||||
|
const el = win.content.querySelector(`#${id}`)
|
||||||
|
el?.classList.toggle('show')
|
||||||
|
}
|
||||||
|
|
||||||
|
fileBtn?.addEventListener('click', function (e) {
|
||||||
|
e.stopPropagation()
|
||||||
|
toggleDropdown('file')
|
||||||
|
})
|
||||||
|
|
||||||
|
editBtn?.addEventListener('click', function (e) {
|
||||||
|
e.stopPropagation()
|
||||||
|
toggleDropdown('edit')
|
||||||
|
})
|
||||||
|
|
||||||
|
win.content.addEventListener('click', function () {
|
||||||
|
const file = win.content.querySelector('#file')
|
||||||
|
const edit = win.content.querySelector('#edit')
|
||||||
|
if (file !== null) {
|
||||||
|
if (file.classList.contains('show')) {
|
||||||
|
toggleDropdown('file')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (edit !== null) {
|
||||||
|
if (edit.classList.contains('show')) {
|
||||||
|
toggleDropdown('edit')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const value = (await window.fs.promises.readFile(data.path)).toString()
|
||||||
const editor = fullEditor(
|
const editor = fullEditor(
|
||||||
Prism,
|
Prism,
|
||||||
win.content,
|
win.content.querySelector('.editor'),
|
||||||
{
|
{
|
||||||
language: data.path.split('.').at(-1),
|
language: data.path.split('.').at(-1),
|
||||||
theme: 'github-dark',
|
theme: 'github-dark',
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const style = document.createElement('style')
|
const style = document.createElement('style')
|
||||||
style.innerHTML = `
|
style.innerHTML = `
|
||||||
.prism-editor {
|
.prism-editor {
|
||||||
|
border-radius: 10px 10px 0 0;
|
||||||
caret-color: var(--text);
|
caret-color: var(--text);
|
||||||
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
||||||
--editor__bg: var(--base);
|
--editor__bg: var(--base);
|
||||||
|
|
@ -80,7 +173,13 @@ export default class EditorApp implements App {
|
||||||
font-family: 'Satoshi', sans-serif;
|
font-family: 'Satoshi', sans-serif;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
editor.scrollContainer.appendChild(style)
|
editor.scrollContainer.appendChild(style);
|
||||||
|
(win.content.querySelector('#find') as HTMLElement).onclick = () => {
|
||||||
|
editor.extensions.searchWidget.open()
|
||||||
|
}
|
||||||
|
(win.content.querySelector('#save') as HTMLElement).onclick = async () => {
|
||||||
|
await window.fs.promises.writeFile(data.path, editor.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return win
|
return win
|
||||||
|
|
|
||||||
|
|
@ -13,34 +13,26 @@ export default class FilesApp implements App {
|
||||||
version = '1.0.0'
|
version = '1.0.0'
|
||||||
|
|
||||||
async open (): Promise<FlowWindow> {
|
async open (): Promise<FlowWindow> {
|
||||||
const fs = new (window as any).Filer.FileSystem()
|
const win = window.wm.createWindow({
|
||||||
|
|
||||||
const win = (window as any).wm.createWindow({
|
|
||||||
title: this.name,
|
title: this.name,
|
||||||
icon,
|
icon,
|
||||||
width: 500,
|
width: 500,
|
||||||
height: 400
|
height: 400
|
||||||
})
|
})
|
||||||
|
|
||||||
try {
|
|
||||||
await fs.mkdir('/home', () => {})
|
|
||||||
await fs.mkdir('/home/meow', () => {})
|
|
||||||
} catch (e) {}
|
|
||||||
try {
|
|
||||||
await fs.writeFile('/home/owo1.txt', 'sussy', () => {})
|
|
||||||
await fs.writeFile('/home/owo2.html', '<body></body>', () => {})
|
|
||||||
await fs.writeFile('/home/owo.js', 'alert(`hi`)', () => {})
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
win.content.style.display = 'flex'
|
win.content.style.display = 'flex'
|
||||||
win.content.style.flexDirection = 'column'
|
win.content.style.flexDirection = 'column'
|
||||||
|
|
||||||
async function setDir (dir: string): Promise<void> {
|
async function setDir (dir: string): Promise<void> {
|
||||||
await fs.readdir(dir, (e: NodeJS.ErrnoException, files: string[]) => {
|
await window.fs.readdir(dir, (e: NodeJS.ErrnoException, files: string[]) => {
|
||||||
const back = dir === '/' ? '<i class=\'bx bx-arrow-to-left\'></i>' : '<i class=\'back bx bx-left-arrow-alt\'></i>'
|
const back = dir === '/' ? '<i class=\'bx bx-arrow-to-left\'></i>' : '<i class=\'back bx bx-left-arrow-alt\'></i>'
|
||||||
|
|
||||||
win.content.innerHTML = `
|
win.content.innerHTML = `
|
||||||
<div style="padding: 5px;display: flex;align-items: center;">${back}${dir}</div>
|
<div style="padding: 5px;display: flex;align-items: center;gap: 5px;">
|
||||||
|
${back}${dir}
|
||||||
|
<div style="flex:1;"></div>
|
||||||
|
<i class='folder bx bxs-folder-plus' style="font-size: 17.5px;"></i><i class='file bx bxs-file-plus' style="font-size: 17.5px;"></i>
|
||||||
|
</div>
|
||||||
<div class="files" style="background: var(--base);flex: 1;border-radius: 10px;display: flex;flex-direction: column;"></div>
|
<div class="files" style="background: var(--base);flex: 1;border-radius: 10px;display: flex;flex-direction: column;"></div>
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
@ -54,9 +46,21 @@ export default class FilesApp implements App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(win.content.querySelector('.file') as HTMLElement).onclick = async () => {
|
||||||
|
const title: string = prompt('Enter file name') ?? 'new-file.txt'
|
||||||
|
await window.fs.promises.open(dir + '/' + title, 'w')
|
||||||
|
await setDir(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
(win.content.querySelector('.folder') as HTMLElement).onclick = async () => {
|
||||||
|
const title: string = prompt('Enter folder name') ?? 'new-folder'
|
||||||
|
await window.fs.promises.mkdir(dir + '/' + title)
|
||||||
|
await setDir(dir)
|
||||||
|
}
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const separator = dir === '/' ? '' : '/'
|
const separator = dir === '/' ? '' : '/'
|
||||||
fs.stat(dir + separator + file, (e: NodeJS.ErrnoException, fileStat: Stats) => {
|
window.fs.stat(dir + separator + file, (e: NodeJS.ErrnoException, fileStat: Stats) => {
|
||||||
const element = document.createElement('div')
|
const element = document.createElement('div')
|
||||||
element.setAttribute('style', 'padding: 5px;border-bottom: 1px solid var(--text);display:flex;align-items:center;gap: 5px;')
|
element.setAttribute('style', 'padding: 5px;border-bottom: 1px solid var(--text);display:flex;align-items:center;gap: 5px;')
|
||||||
|
|
||||||
|
|
@ -120,7 +124,7 @@ export default class FilesApp implements App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
win.content.querySelector('.files').appendChild(element)
|
win.content.querySelector('.files')?.appendChild(element)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ export default class MusicApp implements App {
|
||||||
version = '1.0.0'
|
version = '1.0.0'
|
||||||
|
|
||||||
async open (): Promise<FlowWindow> {
|
async open (): Promise<FlowWindow> {
|
||||||
const win = (window as any).wm.createWindow({
|
const win = window.wm.createWindow({
|
||||||
title: this.name,
|
title: this.name,
|
||||||
icon
|
icon
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ export default class SettingsApp implements App {
|
||||||
version = '1.0.0'
|
version = '1.0.0'
|
||||||
|
|
||||||
async open (): Promise<FlowWindow> {
|
async open (): Promise<FlowWindow> {
|
||||||
const win = (window as any).wm.createWindow({
|
const win = window.wm.createWindow({
|
||||||
title: this.name,
|
title: this.name,
|
||||||
icon,
|
icon,
|
||||||
width: 700,
|
width: 700,
|
||||||
|
|
|
||||||
1
src/filer.d.ts
vendored
1
src/filer.d.ts
vendored
|
|
@ -1 +0,0 @@
|
||||||
declare module 'filer'
|
|
||||||
15
src/index.ts
15
src/index.ts
|
|
@ -3,5 +3,16 @@ import './style.less'
|
||||||
import StatusBar from './statusbar.ts'
|
import StatusBar from './statusbar.ts'
|
||||||
import WM from './wm.ts'
|
import WM from './wm.ts'
|
||||||
|
|
||||||
(window as any).statusBar = new StatusBar();
|
import * as fs from 'fs'
|
||||||
(window as any).wm = new WM()
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
statusBar: StatusBar
|
||||||
|
wm: WM
|
||||||
|
fs: typeof fs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.statusBar = new StatusBar()
|
||||||
|
window.wm = new WM()
|
||||||
|
window.fs = new (window as any).Filer.FileSystem()
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,6 @@ export const run = (element: HTMLDivElement): void => {
|
||||||
element.innerHTML = '<i class=\'bx bx-rocket\'></i>'
|
element.innerHTML = '<i class=\'bx bx-rocket\'></i>'
|
||||||
|
|
||||||
element.onclick = () => {
|
element.onclick = () => {
|
||||||
(window as any).wm.toggleLauncher()
|
window.wm.toggleLauncher()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue