From 5c7ff7c2870cbb1c4e26e0fb91aa4b0b71b0655b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 6 Apr 2024 21:15:32 -0700 Subject: [PATCH] share dialog is back --- www/src/js/app/app.ts | 37 ++++++--- www/src/js/app/index.ts | 3 +- www/src/js/app/nav.ts | 9 ++- www/src/js/app/share.ts | 49 ++++++++++++ www/src/js/editor/ace.ts | 1 + www/src/js/editor/ic10_mode.ts | 1 - www/src/js/editor/index.ts | 123 +++++++++++++++++++++--------- www/src/js/editor/shortcuts-ui.ts | 78 +++++++++++++++++++ www/src/js/editor/styles.ts | 2 +- www/webpack.config.js | 16 +++- 10 files changed, 262 insertions(+), 57 deletions(-) create mode 100644 www/src/js/app/share.ts create mode 100644 www/src/js/editor/shortcuts-ui.ts diff --git a/www/src/js/app/app.ts b/www/src/js/app/app.ts index be46920..1a59c3e 100644 --- a/www/src/js/app/app.ts +++ b/www/src/js/app/app.ts @@ -1,7 +1,14 @@ import { HTMLTemplateResult, html, css, CSSResultGroup } from "lit"; import { customElement, property, query } from "lit/decorators.js"; import { BaseElement, defaultCss } from "../components"; -import "./nav.ts"; +import "./nav"; +import "./share"; +import { ShareSessionDialog } from "./share"; + +import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path.js'; + +// Set the base path to the folder you copied Shoelace's assets to +setBasePath('/shoelace'); import "@shoelace-style/shoelace/dist/components/split-panel/split-panel.js"; @@ -29,9 +36,9 @@ export class App extends BaseElement { flex-grow: 1; // z-index: auto; } - .z-fix { - z-index: 900; - } + // .z-fix { + // z-index: 900; + // } sl-split-panel { height: 100%; } @@ -40,9 +47,12 @@ export class App extends BaseElement { editorSettings: { fontSize: number; relativeLineNumbers: boolean }; - get editor() { - return this.renderRoot.querySelector("ace-ic10") as IC10Editor; - } + @query('ace-ic10') accessor editor: IC10Editor; + @query('session-share-dialog') accessor shareDialog: ShareSessionDialog; + + // get editor() { + // return this.renderRoot.querySelector("ace-ic10") as IC10Editor; + // } vm!: VirtualMachine; session!: Session; @@ -57,16 +67,16 @@ export class App extends BaseElement { protected createRenderRoot(): HTMLElement | DocumentFragment { const root = super.createRenderRoot(); - root.addEventListener('app-share-session', this._handleShare); - root.addEventListener('app-open-file', this._handleOpenFile); - root.addEventListener('app-save-as', this._handleSaveAs); + root.addEventListener('app-share-session', this._handleShare.bind(this)); + root.addEventListener('app-open-file', this._handleOpenFile.bind(this)); + root.addEventListener('app-save-as', this._handleSaveAs.bind(this)); return root; } protected render(): HTMLTemplateResult { return html`
- +
- +
Controls
+
`; } @@ -87,6 +98,8 @@ export class App extends BaseElement { _handleShare(_e: Event) { // TODO: + this.shareDialog.link = window.location.href; + this.shareDialog.show(); } _handleSaveAs(_e: Event) { diff --git a/www/src/js/app/index.ts b/www/src/js/app/index.ts index 1c7efc7..fa6f33c 100644 --- a/www/src/js/app/index.ts +++ b/www/src/js/app/index.ts @@ -1,4 +1,5 @@ import { App } from "./app"; import { Nav } from "./nav"; +import { ShareSessionDialog } from "./share"; import "./icons"; -export { App, Nav } +export { App, Nav, ShareSessionDialog } diff --git a/www/src/js/app/nav.ts b/www/src/js/app/nav.ts index beb5d39..1fbe901 100644 --- a/www/src/js/app/nav.ts +++ b/www/src/js/app/nav.ts @@ -1,6 +1,8 @@ import { HTMLTemplateResult, html, css } from "lit"; import { customElement, property } from "lit/decorators.js"; import { BaseElement, defaultCss } from "../components"; + +import '@shoelace-style/shoelace/dist/components/icon/icon.js'; import "@shoelace-style/shoelace/dist/components/icon-button/icon-button.js"; import "@shoelace-style/shoelace/dist/components/menu/menu.js"; import "@shoelace-style/shoelace/dist/components/divider/divider.js"; @@ -79,6 +81,7 @@ export class Nav extends BaseElement { position: relative; top: 50%; transform: translateY(-50%); + z-index: 100; } nav { border-bottom: 1px solid rgb(108, 117, 125); @@ -101,7 +104,7 @@ export class Nav extends BaseElement { label="Main Menu" > - + Share Open File Save As @@ -180,10 +183,10 @@ export class Nav extends BaseElement { this.dispatchEvent(new CustomEvent("app-save-as", { bubbles: true })); break; case "editorSettings": - window.Editor?.settingDialog.show(); + window.Editor.settingDialog.show(); break; case "keyboardShortcuts": - // TODO: bind + window.Editor.kbShortcuts.show(); break; default: console.log("Unknown main menu item", item.value); diff --git a/www/src/js/app/share.ts b/www/src/js/app/share.ts new file mode 100644 index 0000000..a254b3d --- /dev/null +++ b/www/src/js/app/share.ts @@ -0,0 +1,49 @@ +import { HTMLTemplateResult, html, css } from "lit"; +import { customElement, property, query } from "lit/decorators.js"; +import { BaseElement, defaultCss } from "../components"; + +import "@shoelace-style/shoelace/dist/components/dialog/dialog.js"; +import "@shoelace-style/shoelace/dist/components/input/input.js"; +import "@shoelace-style/shoelace/dist/components/icon/icon.js"; +import "@shoelace-style/shoelace/dist/components/icon-button/icon-button.js"; +import "@shoelace-style/shoelace/dist/components/copy-button/copy-button.js"; +import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.js"; +import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js"; + +@customElement("session-share-dialog") +export class ShareSessionDialog extends BaseElement { + @query(".dialog") accessor dialog: SlDialog; + @query(".input") accessor input: SlInput; + @property({ type: String }) accessor link: string; + + constructor() { + super(); + } + + protected render() { + return html` + + + + + + + + + + + `; + } + + show() { + this.dialog.show(); + } + + hide() { + this.dialog.hide(); + } + + _handleCopyClick() { + this.input.value; + } +} diff --git a/www/src/js/editor/ace.ts b/www/src/js/editor/ace.ts index b420071..7aa4549 100644 --- a/www/src/js/editor/ace.ts +++ b/www/src/js/editor/ace.ts @@ -21,6 +21,7 @@ export async function setupLspWorker() { } export import EditSession = ace.Ace.EditSession; +export import Editor = ace.Ace.Editor; import { Range } from "ace-builds"; export { ace, TextMode, Range, AceLanguageClient } diff --git a/www/src/js/editor/ic10_mode.ts b/www/src/js/editor/ic10_mode.ts index 6977e05..6a81103 100644 --- a/www/src/js/editor/ic10_mode.ts +++ b/www/src/js/editor/ic10_mode.ts @@ -4,7 +4,6 @@ import { rules as highlightRules } from "./ic10_highlight_rules"; //Support function to create Ace mode function createAceMode(modeName: string, highlighterObj: ace.Ace.HighlightRulesMap) { (ace as any).define(modeName, ["require", "exports", "module"], function (require: any, exports: any, module: any) { - console.log(require); var oop = require("ace/lib/oop"); var TextMode = require("ace/mode/text").Mode; var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules; diff --git a/www/src/js/editor/index.ts b/www/src/js/editor/index.ts index 68e3465..2d21c65 100644 --- a/www/src/js/editor/index.ts +++ b/www/src/js/editor/index.ts @@ -1,5 +1,6 @@ import { ace, + Editor, EditSession, Range, AceLanguageClient, @@ -14,7 +15,7 @@ import "@shoelace-style/shoelace/dist/components/button/button.js"; import "@shoelace-style/shoelace/dist/components/input/input.js"; import "@shoelace-style/shoelace/dist/components/radio-button/radio-button.js"; import "@shoelace-style/shoelace/dist/components/radio-group/radio-group.js"; -import '@shoelace-style/shoelace/dist/components/switch/switch.js'; +import "@shoelace-style/shoelace/dist/components/switch/switch.js"; import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.js"; import SlRadioGroup from "@shoelace-style/shoelace/dist/components/radio-group/radio-group.js"; import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js"; @@ -28,8 +29,11 @@ declare global { import { BaseElement, defaultCss } from "../components"; import { html } from "lit"; -import { customElement, property } from "lit/decorators.js"; +import { Ref, createRef, ref } from "lit/directives/ref.js"; +import { customElement, property, query } from "lit/decorators.js"; import { editorStyles } from "./styles"; +import "./shortcuts-ui"; +import { AceKeyboardShortcuts } from "./shortcuts-ui"; @customElement("ace-ic10") export class IC10Editor extends BaseElement { @@ -55,7 +59,7 @@ export class IC10Editor extends BaseElement { editorDiv: HTMLElement; editorContainerDiv: HTMLElement; editorStatusbarDiv: HTMLElement; - editor: ace.Ace.Editor; + editor: Editor; statusBar: any; snippetManager: any; observer: ResizeObserver; @@ -67,9 +71,9 @@ export class IC10Editor extends BaseElement { stylesAdded: string[]; tooltipObserver: MutationObserver; - get settingDialog() { - return this.shadowRoot?.querySelector('sl-dialog') as SlDialog - } + @query('.e-kb-shortcuts') accessor kbShortcuts: AceKeyboardShortcuts; + + @query('.e-settings-dialog') accessor settingDialog: SlDialog; constructor() { super(); @@ -95,32 +99,53 @@ export class IC10Editor extends BaseElement { const result = html`
>
- - + + Ace Vim Emacs Sublime VS Code - + Ace Slim Smooth Smooth And Slim Wide - - Relative Line Numbers + + Relative Line Numbers + `; return result; } @@ -242,6 +267,8 @@ export class IC10Editor extends BaseElement { }); this.observer.observe(this.editorContainerDiv); + this.kbShortcuts.editor = this.editor; + this.kbShortcuts.requestUpdate(); this.initializeEditor(); } @@ -324,37 +351,57 @@ export class IC10Editor extends BaseElement { this.shadowRoot!.querySelector(".ace_scrollbar-h")!, ); - editor.commands.addCommands([{ - name: "showSettingsMenu", - // description: "Show settings menu", - bindKey: { win: "Ctrl-,", mac: "Command-,"}, - exec: (_editor: ace.Ace.Editor) => { - that.settingDialog.show(); + editor.commands.addCommands([ + { + name: "showSettingsMenu", + // description: "Show settings menu", + bindKey: { win: "Ctrl-,", mac: "Command-," }, + exec: (_editor: Editor) => { + that.settingDialog.show(); + }, }, - }]); + { + name: "showKeyboardShortcuts", + bindKey: { + win: "Ctrl-Alt-h", + mac: "Command-Alt-h", + }, + exec: (_editor: Editor) => { + that.kbShortcuts.show(); + }, + }, + ]); this.updateEditorSettings(); - const keyboardRadio = this.renderRoot.querySelector("#editorKeyboardRadio")! as SlRadioGroup; - const cursorRadio = this.renderRoot.querySelector("#editorCursorRadio")! as SlRadioGroup; - const fontSize = this.renderRoot.querySelector("#editorFontSize")! as SlInput; - const relativeLineNumbers = this.renderRoot.querySelector("#editorRelativeLineNumbers")! as SlSwitch; + const keyboardRadio = this.renderRoot.querySelector( + "#editorKeyboardRadio", + )! as SlRadioGroup; + const cursorRadio = this.renderRoot.querySelector( + "#editorCursorRadio", + )! as SlRadioGroup; + const fontSize = this.renderRoot.querySelector( + "#editorFontSize", + )! as SlInput; + const relativeLineNumbers = this.renderRoot.querySelector( + "#editorRelativeLineNumbers", + )! as SlSwitch; - keyboardRadio.addEventListener("sl-change", _e => { + keyboardRadio.addEventListener("sl-change", (_e) => { that.settings.keyboard = keyboardRadio.value; that.updateEditorSettings(); that.saveEditorSettings(); }); - cursorRadio?.addEventListener("sl-change", _e => { + cursorRadio?.addEventListener("sl-change", (_e) => { that.settings.cursor = cursorRadio.value; that.updateEditorSettings(); that.saveEditorSettings(); }); - fontSize?.addEventListener("sl-change", _e => { - that.settings.fontSize = parseInt(fontSize.value) + fontSize?.addEventListener("sl-change", (_e) => { + that.settings.fontSize = parseInt(fontSize.value); that.updateEditorSettings(); that.saveEditorSettings(); }); - relativeLineNumbers?.addEventListener("sl-change", _e => { + relativeLineNumbers?.addEventListener("sl-change", (_e) => { that.settings.relativeLineNumbers = relativeLineNumbers.checked; that.updateEditorSettings(); that.saveEditorSettings(); @@ -505,14 +552,20 @@ export class IC10Editor extends BaseElement { } updateEditorSettings() { - if (this.settings.keyboard === 'ace') { - this.editor.setOption('keyboardHandler', null); + if (this.settings.keyboard === "ace") { + this.editor.setOption("keyboardHandler", null); } else { - this.editor.setOption('keyboardHandler', `ace/keyboard/${this.settings.keyboard}`); + this.editor.setOption( + "keyboardHandler", + `ace/keyboard/${this.settings.keyboard}`, + ); } - this.editor.setOption('cursorStyle', this.settings.cursor as any); - this.editor.setOption('fontSize', this.settings.fontSize); - this.editor.setOption('relativeLineNumbers', this.settings.relativeLineNumbers); + this.editor.setOption("cursorStyle", this.settings.cursor as any); + this.editor.setOption("fontSize", this.settings.fontSize); + this.editor.setOption( + "relativeLineNumbers", + this.settings.relativeLineNumbers, + ); } destroySession(session_id: number) { diff --git a/www/src/js/editor/shortcuts-ui.ts b/www/src/js/editor/shortcuts-ui.ts new file mode 100644 index 0000000..dee8087 --- /dev/null +++ b/www/src/js/editor/shortcuts-ui.ts @@ -0,0 +1,78 @@ +import { BaseElement, defaultCss } from "../components"; +import { html, css, PropertyValueMap } from "lit"; +import { customElement, property, query } from "lit/decorators.js"; +import { ace, Editor } from "./ace"; + +import "@shoelace-style/shoelace/dist/components/drawer/drawer.js"; + +import { SlDrawer } from "@shoelace-style/shoelace"; +import { Ref, createRef, ref } from "lit/directives/ref.js"; + +@customElement("ace-kb-menu") +export class AceKeyboardShortcuts extends BaseElement { + static styles = [ + defaultCss, + css` + .command { + color: #c678dd; + font-weight: normal; + } + .entry:hover { + background-color: var(--sl-color-neutral-100); + transition: all 0.3s; + } + .key { + color: var(--sl-color-neutral-1000); + font-weight: bold; + } + `, + ]; + + editor?: Editor; + @query('.drawer') accessor drawer: SlDrawer; + + constructor() { + super(); + } + + // protected shouldUpdate(_changedProperties: PropertyValueMap | Map): boolean { + // return true; + // } + + protected async firstUpdated() { + if (!ace.require("ace/ext/menu_tools/get_editor_keyboard_shortcuts")) { + await import("ace-builds/src-noconflict/ext-keybinding_menu"); + } + } + + protected render() { + var kbs: any[] = []; + if (this.editor) { + const getEditorKeybordShortcuts = ace.require( + "ace/ext/menu_tools/get_editor_keyboard_shortcuts", + ).getEditorKeybordShortcuts; + kbs = getEditorKeybordShortcuts(this.editor); + } + return html` + +
+ ${kbs.map( + (kb: any) => + html`
+ ${kb.command} : + ${kb.key} +
`, + )} +
+
+ `; + } + + show() { + this.drawer.show(); + } + + hide() { + this.drawer.hide(); + } +} diff --git a/www/src/js/editor/styles.ts b/www/src/js/editor/styles.ts index b3d919b..2e2bd36 100644 --- a/www/src/js/editor/styles.ts +++ b/www/src/js/editor/styles.ts @@ -8,7 +8,7 @@ export const editorStyles = css` #editor { // border: 1px solid; // border-radius: 4px; - @apply --ace-widget-editor; + // @apply --ace-widget-editor; } #editorStatusbar { z-index: 9 !important; diff --git a/www/webpack.config.js b/www/webpack.config.js index 3985e5f..415273c 100644 --- a/www/webpack.config.js +++ b/www/webpack.config.js @@ -25,6 +25,14 @@ module.exports = { "img/*.png", "img/*/*.png", { from: "data/database.json", to: "data" }, + // Copy Shoelace assets to dist/shoelace + { + from: path.resolve( + __dirname, + "node_modules/@shoelace-style/shoelace/dist/assets", + ), + to: path.resolve(__dirname, "dist/shoelace/assets"), + }, ], }), new HtmlWebpackPlugin({ template: "./src/index.html" }), @@ -52,8 +60,8 @@ module.exports = { // translates CSS into CommonJS modules loader: "css-loader", options: { - sourceMap: true - } + sourceMap: true, + }, }, { // Run postcss actions @@ -73,8 +81,8 @@ module.exports = { // compiles Sass to CSS loader: "sass-loader", options: { - sourceMap: true - } + sourceMap: true, + }, }, ], // parser: {