Skip to content

Commit

Permalink
wip, advanced project drawer
Browse files Browse the repository at this point in the history
  • Loading branch information
heapwolf committed Feb 29, 2024
1 parent 535d614 commit 34e28df
Show file tree
Hide file tree
Showing 17 changed files with 475 additions and 42 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ node_modules/
# Default output directory
dist/
build/
.DS_Store

package-lock.json

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"@socketsupply/tonic": "^15.1.2",
"esbuild": "^0.20.0",
"monaco-editor": "^0.46.0",
"standard": "^16.0.4",
"standard": "^17.1.0",
"xterm": "^5.3.0",
"xterm-addon-fit": "^0.8.0",
"xterm-addon-search": "^0.13.0"
Expand Down
4 changes: 4 additions & 0 deletions src/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ header {
border-right: 1px solid var(--tonic-border);
}

.monaco-editor .margin-view-overlays .line-numbers {
color: var(--tonic-info);
}

.monaco-editor .scroll-decoration {
box-shadow: var(--vscode-scrollbar-shadow) 0 6px 10px -12px inset;
}
40 changes: 39 additions & 1 deletion src/css/project.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,35 @@ app-project .children {
display: block;
}

app-project #tree-item-placeholder {
position: fixed;
display: inline-grid;
align-content: center;
align-items: center;
z-index: -1;
opacity: 0;
width: auto;
height: 28px;
padding: 4px 8px;
border-radius: 6px;
color: var(--tonic-window);
background: var(--tonic-primary);
}

app-project[dragging="true"] #tree-item-placeholder {
opacity: 1;
z-index: 1000;
}

app-project input[data-event="rename"] {
border: none;
font-size: 14px;
padding: 2px;
color: var(--tonic-info);
background-color: transparent;
outline: none;
}

app-project .node-data {
display: flex;
padding: 2 4px 0;
Expand All @@ -51,6 +80,11 @@ app-project .region {
padding-right: 20px;
}

app-project [data-path].hover {
outline: 1px solid var(--tonic-accent);
outline-offset: -1px;
}

app-project .item .node-data .label {
text-overflow: ellipsis;
white-space: nowrap;
Expand All @@ -65,7 +99,11 @@ app-project .item .node-data .label {
font-weight: 100;
}

app-project .item .handle:hover {
app-project[dragging] {
cursor: grab;
}

app-project:not([dragging]) .item .handle:hover {
background: var(--tonic-shadow);
cursor: pointer;
}
Expand Down
50 changes: 39 additions & 11 deletions src/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,27 @@ class AppEditor extends Tonic {
async loadProjectNode (projectNode) {
if (!projectNode) return

const parent = this.props.parent
const ext = path.extname(projectNode.id)
const type = await lookup(ext.slice(1))

if (type.length) {
if (/image/.test(type[0].mime)) {

// Display a preview for this type.
return
}
}

this.projectNode = projectNode

const fileName = projectNode.label
const imagePreview = this.querySelector('.image-preview')

if (fileName.endsWith('.assets')) {
const blob = new Blob([projectNode.data], { type: 'image/png' })
if (projectNode.isDirectory && fileName === 'icons') {
const iconPath = path.join(projectNode.id, 'icon.png')
const data = await fs.promises.readFile(iconPath)
const blob = new Blob([data], { type: 'image/png' })
const url = URL.createObjectURL(blob)
;[...imagePreview.querySelectorAll('img')].forEach(img => (img.src = url))
imagePreview.classList.add('show')
Expand All @@ -128,14 +142,18 @@ class AppEditor extends Tonic {

imagePreview.classList.remove('show')

if (this.editor) {
let languageHint = path.extname(projectNode.id).slice(1)
if (languageHint === 'js') languageHint = 'javascript'
if (languageHint === 'hh') languageHint = 'cpp'
if (languageHint === 'cc') languageHint = 'cpp'
if (languageHint === 'c') languageHint = 'cpp'
monaco.editor.setModelLanguage(this.editor.getModel(), languageHint)
const data = await fs.promises.readFile(projectNode.id, 'utf8')
if (!projectNode.isDirectory && this.editor) {
const ext = path.extname(projectNode.id)
const mappings = parent.state.settings.extensionLanguageMappings
const lang = mappings[ext] || ext.slice(1)
monaco.editor.setModelLanguage(this.editor.getModel(), lang)
let data = await fs.promises.readFile(projectNode.id, 'utf8')

if (path.extname(projectNode.id) === '.json') {
try {
data = JSON.stringify(JSON.parse(data), null, 2)
} catch {}
}
this.editor.setValue(data)
}
}
Expand Down Expand Up @@ -220,8 +238,14 @@ class AppEditor extends Tonic {
}
}

async refreshSettings () {
let parent = this.props.parent
this.editor.updateOptions(parent.state.settings?.editorOptions || {})
}

connected () {
let theme
let parent = this.props.parent

this.editor = monaco.editor.create(this.querySelector('.editor'), {
value: '',
Expand All @@ -234,7 +258,11 @@ class AppEditor extends Tonic {
renderLineHighlight: 'none'
})

this.editor.getModel().onDidChangeContent(() => {
this.refreshSettings()

const model = this.editor.getModel()

model.onDidChangeContent(async () => {
clearTimeout(this.writeDebounce)

if (!this.projectNode) return
Expand Down
5 changes: 5 additions & 0 deletions src/examples.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const examples = {
}

export default examples
export { examples }
80 changes: 67 additions & 13 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,44 @@ import { AppProject } from './project.js'
import { AppProperties } from './properties.js'
import { AppSprite } from './sprite.js'
import { AppEditor } from './editor.js'
import { settings as defaultSettings } from './settings.js'

components(Tonic)

class AppView extends Tonic {
constructor () {
super()
this.editors = {}
this.init()
}

async installTemplates () {
const readDir = async (dirPath) => {
const entries = await fs.promises.readdir(dirPath, { withFileTypes: true })

for (const entry of entries) {
const fullPath = path.join(dirPath, entry.name)

if (entry.isDirectory()) {
try {
await readDir(fullPath)
} catch (err) {
console.error(`Error reading directory ${fullPath}:`, err)
}
} else {
const file = await fs.promises.readFile(fullPath)
const basePath = path.relative('templates', fullPath)
const destPath = path.join(this.state.cwd, basePath)
await fs.promises.mkdir(path.dirname(destPath), { recursive: true })
await fs.promises.writeFile(destPath, file)
}
}
}

try {
await readDir('templates')
} catch (err) {
console.error('Error initiating read directory operation:', err)
}
}

async init () {
Expand All @@ -30,21 +60,41 @@ class AppView extends Tonic {
//
this.state.cwd = path.join(process.env.HOME, '.local', 'share', 'socket-app-studio')

const exists = await fs.promises.stat(path.join(this.state.cwd, 'socket.ini'))
let projectExists

if (!exists) {
const settingsFile = path.join(this.state.cwd, 'settings.json')
const notifications = document.querySelector('#notifications')

try {
projectExists = await fs.promises.stat(path.join(this.state.cwd, 'socket.ini'))
} catch {}

if (!projectExists) {
await fs.promises.mkdir(path.join(this.state.cwd, 'src'), { recursive: true })

this.state.settings = defaultSettings
await fs.promises.writeFile(settingsFile, JSON.stringify(defaultSettings))
await this.installTemplates()
}

if (projectExists) {
try {
await fs.promises.cp('templates', this.statea.cwd, { recursive: true })
const str = await fs.promises.readFile(settingsFile, 'utf8')
this.state.settings = JSON.parse(str)

fs.watch(settingsFile, async () => {
const editor = document.querySelector('app-editor')
if (editor) {
this.state.settings = await fs.promises.readFile(settingsFile, 'utf8')
editor.refreshSettings()
}
})
} catch (err) {
const notifications = docuent.querySelector('#notifications')
notifications.create({
type: 'error',
title: 'Unable to initialize directory',
title: 'Unable to read settings from ${settingsFile}',
message: err.message
})

return
}
}
Expand Down Expand Up @@ -151,6 +201,8 @@ class AppView extends Tonic {
File:
Export Project: s + CommandOrControl
New Folder: n + CommandOrControl
New File: N + CommandOrControl
---
Reset Project: _
;
Expand Down Expand Up @@ -178,7 +230,7 @@ class AppView extends Tonic {
;
Build & Run:
Evaluate Editor Source: E + CommandOrControl + Shift
Evaluate Editor Source: r + CommandOrControl + Shift
---
Android: s + CommandOrControl
iOS: s + CommandOrControl
Expand Down Expand Up @@ -426,7 +478,9 @@ class AppView extends Tonic {
editor.loadProjectNode(node.children[0].children[2]) */
}

render () {
async render () {
await this.init()

return this.html`
<header>
<tonic-button type="icon" size="18px" symbol-id="play" title="Build & Run The Project" data-event="run">
Expand All @@ -448,24 +502,24 @@ class AppView extends Tonic {
<tonic-split-left width="80%">
<tonic-split id="split-editor" type="vertical">
<tonic-split-left width="25%">
<app-project id="app-project"></app-project>
<app-project id="app-project" parent=${this}></app-project>
</tonic-split-left>
<tonic-split-right width="75%">
<tonic-split id="split-input" type="horizontal">
<tonic-split-top height="80%">
<app-editor id="editor"></app-editor>
<app-editor id="editor" parent=${this}></app-editor>
</tonic-split-top>
<tonic-split-bottom height="20%">
<app-terminal id="app-terminal"></app-terminal>
<app-terminal id="app-terminal" parent=${this}></app-terminal>
</tonic-split-bottom>
</tonic-split>
</tonic-split-right>
</tonic-split>
</tonic-split-left>
<tonic-split-right width="20%">
<app-properties id="app-properties"></app-properties>
<app-properties id="app-properties" parent=${this}></app-properties>
</tonic-split-right>
</tonic-split>
<app-sprite></app-sprite>
Expand Down
Loading

0 comments on commit 34e28df

Please sign in to comment.