From 2c2f7bdf4eedca3995b6877bf974c76a07ba8ef5 Mon Sep 17 00:00:00 2001 From: Emi Wu <169206128+wu-emi@users.noreply.github.com> Date: Wed, 21 Aug 2024 12:00:12 -0400 Subject: [PATCH 1/4] Adding Project Menu to Play (#33) --- package.json | 4 +- .../play-icon/icons/upload-outline.svg | 1 + src/elements/play-icon/play-icon.ts | 4 +- src/elements/play-pen-header.ts | 22 +- src/elements/play-project-button.test.ts | 7 + src/elements/play-project-button.ts | 197 ++++++++++++++++++ 6 files changed, 223 insertions(+), 12 deletions(-) create mode 100644 src/elements/play-icon/icons/upload-outline.svg create mode 100644 src/elements/play-project-button.test.ts create mode 100644 src/elements/play-project-button.ts diff --git a/package.json b/package.json index 8cbc113..7feb650 100644 --- a/package.json +++ b/package.json @@ -60,8 +60,8 @@ "gzip": "3.5 KB" }, "dist/play-pen.js": { - "none": "31900 KB", - "gzip": "5150 KB" + "none": "32100 KB", + "gzip": "5190 KB" } }, "typesVersions": { diff --git a/src/elements/play-icon/icons/upload-outline.svg b/src/elements/play-icon/icons/upload-outline.svg new file mode 100644 index 0000000..8691190 --- /dev/null +++ b/src/elements/play-icon/icons/upload-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/elements/play-icon/play-icon.ts b/src/elements/play-icon/play-icon.ts index 2b25704..8fd63e0 100644 --- a/src/elements/play-icon/play-icon.ts +++ b/src/elements/play-icon/play-icon.ts @@ -35,6 +35,7 @@ import resizeHorizontalOutline from './icons/resize-horizontal-outline.svg' import restartOutline from './icons/restart-outline.svg' import shareNewOutline from './icons/share-new-outline.svg' import unmountOutline from './icons/unmount-outline.svg' +import uploadOutline from './icons/upload-outline.svg' export type PlayIconSVG = keyof typeof icons @@ -62,7 +63,8 @@ const icons = { 'resize-horizontal-outline': resizeHorizontalOutline, 'restart-outline': restartOutline, 'share-ios-outline': unmountOutline, - 'share-new-outline': shareNewOutline + 'share-new-outline': shareNewOutline, + 'upload-outline': uploadOutline } declare global { diff --git a/src/elements/play-pen-header.ts b/src/elements/play-pen-header.ts index 0d2d23a..e12c7ba 100644 --- a/src/elements/play-pen-header.ts +++ b/src/elements/play-pen-header.ts @@ -10,7 +10,6 @@ import {defaultSettings} from '../storage/settings-save.js' import {Bubble} from '../utils/bubble.js' import {cssReset} from '../utils/css-reset.js' import {openURL} from '../utils/open-url.js' -import type {PlayExportDialog} from './play-export-dialog.js' import type {PlaySettingsDialog} from './play-settings-dialog.js' import type {PlayAssetsDialog} from './play-assets-dialog.js' @@ -19,10 +18,12 @@ import './play-export-dialog.js' import './play-icon/play-icon.js' import './play-logo/play-logo.js' import './play-new-pen-button.js' +import './play-project-button.js' import './play-resizable-text-input.js' import './play-settings-dialog.js' import './play-assets-dialog.js' import {type AssetsState, emptyAssetsState} from './play-assets/play-assets.js' +import type {PlayExportDialog} from './play-export-dialog.js' declare global { interface HTMLElementEventMap { @@ -124,6 +125,12 @@ export class PlayPenHeader extends LitElement { @query('play-settings-dialog') private _settings!: PlaySettingsDialog + protected override firstUpdated(): void { + this.addEventListener('open-export-dialog', () => { + this._export.open() + }) + } + protected override render(): TemplateResult { return html`
@@ -149,14 +156,11 @@ export class PlayPenHeader extends LitElement { label="Docs" @click=${() => openURL('https://developers.reddit.com/docs')} > this._export.open()} - > { + const el = document.createElement('play-project-button') + assert.instanceOf(el, PlayProjectButton) +}) diff --git a/src/elements/play-project-button.ts b/src/elements/play-project-button.ts new file mode 100644 index 0000000..fc2a29b --- /dev/null +++ b/src/elements/play-project-button.ts @@ -0,0 +1,197 @@ +import { + LitElement, + css, + html, + type CSSResultGroup, + type TemplateResult +} from 'lit' +import {customElement, property} from 'lit/decorators.js' +import {Bubble} from '../utils/bubble.js' + +import {cssReset} from '../utils/css-reset.js' +import './play-dropdown-menu.js' +import './play-icon/play-icon.js' +import './play-list-item.js' + +export type SizeOptions = 'small' | 'medium' +const iconSizes: {[key in SizeOptions]: string} = { + small: '16px', + medium: '20px' +} + +declare global { + interface HTMLElementEventMap { + 'edit-src': CustomEvent + } + interface HTMLElementTagNameMap { + 'play-project-button': PlayProjectButton + } +} + +@customElement('play-project-button') +export class PlayProjectButton extends LitElement { + static override readonly styles: CSSResultGroup = css` + ${cssReset} + + .container { + display: flex; + flex-direction: row; + column-gap: 0; + justify-content: space-between; + align-items: center; + box-shadow: inset 0px 0px 0px var(--border-width) + var(--color-secondary-border); + border-radius: var(--radius-full); + } + + button { + font-family: var(--font-family-sans); + color: var(--color-secondary-plain); + background-color: transparent; + border: none; + cursor: pointer; + } + + :host([size='small']) button { + font-size: 12px; + font-style: normal; + font-weight: 600; + line-height: 16px; + letter-spacing: -0.1px; + } + + :host([size='medium']) button { + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 20px; + letter-spacing: -0.3px; + } + + .project-pen { + display: flex; + flex-direction: row; + } + + :host([size='small']) .project-pen { + column-gap: 8px; + padding-top: 8px; + padding-right: 8px; + padding-bottom: 8px; + padding-left: 12px; + border-top-left-radius: 16px; + border-bottom-left-radius: 16px; + } + + :host([size='medium']) .project-pen { + column-gap: 8px; + padding-top: 10px; + padding-right: 12px; + padding-bottom: 10px; + padding-left: 16px; + border-top-left-radius: 20px; + border-bottom-left-radius: 20px; + } + + :host([size='small']) .new-from-template { + padding-top: 8px; + padding-right: 8px; + padding-bottom: 8px; + padding-left: 8px; + border-top-right-radius: 16px; + border-bottom-right-radius: 16px; + } + + :host([size='medium']) .project-options { + padding-top: 10px; + padding-right: 10px; + padding-bottom: 10px; + padding-left: 8px; + border-top-right-radius: 20px; + border-bottom-right-radius: 20px; + } + + .project-options:hover, + .project-template:hover { + background-color: var(--color-secondary-background-hovered); + } + + .project-pen:active, + .project-options:active { + background-color: var(--color-secondary-background-active); + } + + .project-pen:focus, + .project-options:focus { + outline-color: var(--color-brand-background); + } + + .divider { + width: 1px; + background-color: var(--color-secondary-background-decor); + } + + :host([size='small']) .divider { + height: 16px; + } + + :host([size='medium']) .divider { + height: 20px; + } + ` + @property({attribute: false}) srcByLabel?: {readonly [key: string]: string} + @property() size: SizeOptions = 'medium' + + protected override render(): TemplateResult { + return html` +
+ +
+ +
+ +
+
+ + + + + + + + + + this.dispatchEvent( + new CustomEvent('open-export-dialog', { + bubbles: true, + composed: true + }) + )} + > +
+
+
+ ` + } +} From 3143a78fc6832a4c49cfcef989e88627037abf83 Mon Sep 17 00:00:00 2001 From: Andrew Gunsch Date: Wed, 21 Aug 2024 09:17:03 -0700 Subject: [PATCH 2/4] Add slot for account button. (#34) Adds a slot for account button in play-pen-header, that can be specified via play-pen. --- src/elements/play-pen-header.ts | 3 ++- src/elements/play-pen/play-pen.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/elements/play-pen-header.ts b/src/elements/play-pen-header.ts index e12c7ba..9fe3b15 100644 --- a/src/elements/play-pen-header.ts +++ b/src/elements/play-pen-header.ts @@ -184,7 +184,8 @@ export class PlayPenHeader extends LitElement { label="Share" @click=${() => this.dispatchEvent(Bubble('share', undefined))} - >
+ >
) => this._assets.onVirtualFileChange(ev.detail)} @share=${this.#onShare} + >
Date: Thu, 22 Aug 2024 11:42:23 -0700 Subject: [PATCH 3/4] Implements project saving and loading in Play (#35) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 💸 TL;DR Implements Project-level saving and loading in Play. ## Details This includes: * Adding the Save/Load buttons in the Project menu * Dialogs for both Save and Load flows * Logic that proxies the actual storage to something behind the `ProjectStorageClient` interface, which can be swapped out later * Storing the current project in `sessionStorage`, so that it persists across reload but not across tabs * Making sure "New" projects clear the current stored project * Making sure we can load/save projects several times * Using the Pen title as the project name (both when saving and loading) --- src/elements/play-dialog/play-dialog.ts | 3 + src/elements/play-new-pen-button.ts | 7 +- src/elements/play-pen-header.ts | 74 ++++++- src/elements/play-pen/play-pen.ts | 21 +- src/elements/play-project-button.ts | 82 +++----- src/elements/play-project-load-dialog.test.ts | 7 + src/elements/play-project-load-dialog.ts | 181 ++++++++++++++++++ src/elements/play-project-save-dialog.test.ts | 7 + src/elements/play-project-save-dialog.ts | 140 ++++++++++++++ src/storage/local-project-storage-client.ts | 118 ++++++++++++ src/storage/project-manager.ts | 75 ++++++++ src/storage/project-storage-client.ts | 35 ++++ 12 files changed, 683 insertions(+), 67 deletions(-) create mode 100644 src/elements/play-project-load-dialog.test.ts create mode 100644 src/elements/play-project-load-dialog.ts create mode 100644 src/elements/play-project-save-dialog.test.ts create mode 100644 src/elements/play-project-save-dialog.ts create mode 100644 src/storage/local-project-storage-client.ts create mode 100644 src/storage/project-manager.ts create mode 100644 src/storage/project-storage-client.ts diff --git a/src/elements/play-dialog/play-dialog.ts b/src/elements/play-dialog/play-dialog.ts index ccc13c0..6933a99 100644 --- a/src/elements/play-dialog/play-dialog.ts +++ b/src/elements/play-dialog/play-dialog.ts @@ -99,6 +99,9 @@ export class PlayDialog extends LitElement implements PlayDialogLike { close(): void { this._dialog.close() + this.dispatchEvent( + new CustomEvent('closed', {bubbles: true, composed: true}) + ) } protected override render(): TemplateResult { diff --git a/src/elements/play-new-pen-button.ts b/src/elements/play-new-pen-button.ts index d36cd1b..f639426 100644 --- a/src/elements/play-new-pen-button.ts +++ b/src/elements/play-new-pen-button.ts @@ -150,10 +150,12 @@ export class PlayNewPenButton extends LitElement {
-
-
- - - - - - - - + + this.dispatchEvent( + new CustomEvent('save-project', { + bubbles: true, + composed: true + }) + )} + > + + this.dispatchEvent( + new CustomEvent('load-project', { + bubbles: true, + composed: true + }) + )} + > { + const el = document.createElement('play-project-load-dialog') + assert.instanceOf(el, PlayProjectLoadDialog) +}) diff --git a/src/elements/play-project-load-dialog.ts b/src/elements/play-project-load-dialog.ts new file mode 100644 index 0000000..e4d99ff --- /dev/null +++ b/src/elements/play-project-load-dialog.ts @@ -0,0 +1,181 @@ +import { + css, + type CSSResultGroup, + html, + LitElement, + type TemplateResult +} from 'lit' +import {customElement, property, query, state} from 'lit/decorators.js' +import {PlayDialog} from './play-dialog/play-dialog.js' +import {cssReset} from '../utils/css-reset.js' + +import './play-button.js' +import './play-dialog/play-dialog.js' +import './play-toast.js' +import type {PlayProject} from '../storage/project-storage-client.js' +import {ProjectManager} from '../storage/project-manager.js' + +declare global { + interface HTMLElementTagNameMap { + 'play-project-load-dialog': PlayProjectLoadDialog + } +} + +@customElement('play-project-load-dialog') +export class PlayProjectLoadDialog extends LitElement { + static override readonly styles: CSSResultGroup = css` + ${cssReset} + + legend { + font-weight: bold; + } + + ol { + margin-bottom: 0; + padding-left: 0; + + /* Moves the numbers inside the element */ + list-style-position: inside; + } + + li { + margin-top: var(--space); + } + + pre { + overflow-y: auto; + word-break: break-all; + white-space: pre-line; + max-height: 100px; + font-family: var(--font-family-mono); + font-size: 14px; + line-height: 1.5; + background-color: var(--color-secondary-background); + color: inherit; + + border-radius: var(--radius); + padding: var(--space); + margin-top: var(--space); + margin-bottom: var(--space); + } + + p, + li { + color: inherit; + /* RPL/Body Regular/14-BodyReg */ + font-family: var(--font-family-sans); + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 20px; + } + + a, + a:visited { + color: var(--color-link); + } + + a:hover { + color: var(--color-link-hovered); + } + + select { + width: 100%; + font-family: var(--font-family-sans); + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.2px; + } + ` + + @property() src: string = '' + + @state() private _loading = false + @state() private _projects: PlayProject[] = [] + + @query('#project-select') + private _projectSelect!: HTMLSelectElement + + @query('play-dialog', true) + private _dialog!: PlayDialog + + @property({attribute: 'project-manager', type: ProjectManager}) + projectManager!: ProjectManager + + async open(): Promise { + this._loading = true + this._dialog.open() + this._projects = await this.projectManager.getProjectList() + this._loading = false + } + + close(): void { + this._dialog.close() + } + + async _load(): Promise { + const projectId = this._projectSelect.value + if (!projectId) return + const project = await this.projectManager.loadProject(projectId) + + // TODO: this assumes just one file for Play. + const fileContent = + (project.files || []).length > 0 + ? new TextDecoder().decode(project.files[0]?.content) + : '' + + this.dispatchEvent( + new CustomEvent('edit-src', { + detail: fileContent, + bubbles: true, + composed: true + }) + ) + this.dispatchEvent( + new CustomEvent('edit-name', { + detail: project.name, + bubbles: true, + composed: true + }) + ) + this.close() + } + + protected override render(): TemplateResult { + return html` + + ${this._loading + ? html`

Loading projects...

` + : html`

Choose a project to load:

+ ${this._projects.length > 0 + ? html` +
+ +
+ ` + : html`

No projects available

`}`} + +
+ this._load()} + /> +
+
+ ` + } +} diff --git a/src/elements/play-project-save-dialog.test.ts b/src/elements/play-project-save-dialog.test.ts new file mode 100644 index 0000000..ec06325 --- /dev/null +++ b/src/elements/play-project-save-dialog.test.ts @@ -0,0 +1,7 @@ +import {assert} from '@esm-bundle/chai' +import {PlayProjectSaveDialog} from './play-project-save-dialog.js' + +test('tag is defined', () => { + const el = document.createElement('play-project-save-dialog') + assert.instanceOf(el, PlayProjectSaveDialog) +}) diff --git a/src/elements/play-project-save-dialog.ts b/src/elements/play-project-save-dialog.ts new file mode 100644 index 0000000..49a678d --- /dev/null +++ b/src/elements/play-project-save-dialog.ts @@ -0,0 +1,140 @@ +import { + css, + type CSSResultGroup, + html, + LitElement, + type TemplateResult +} from 'lit' +import {customElement, property, query} from 'lit/decorators.js' +import {PlayDialog} from './play-dialog/play-dialog.js' +import {cssReset} from '../utils/css-reset.js' + +import './play-button.js' +import './play-dialog/play-dialog.js' +import './play-toast.js' +import {Bubble} from '../utils/bubble.js' + +declare global { + interface HTMLElementTagNameMap { + 'play-project-save-dialog': PlayProjectSaveDialog + } +} + +@customElement('play-project-save-dialog') +export class PlayProjectSaveDialog extends LitElement { + static override readonly styles: CSSResultGroup = css` + ${cssReset} + + legend { + font-weight: bold; + } + + ol { + margin-bottom: 0; + padding-left: 0; + + /* Moves the numbers inside the element */ + list-style-position: inside; + } + + li { + margin-top: var(--space); + } + + pre { + overflow-y: auto; + word-break: break-all; + white-space: pre-line; + max-height: 100px; + font-family: var(--font-family-mono); + font-size: 14px; + line-height: 1.5; + background-color: var(--color-secondary-background); + color: inherit; + + border-radius: var(--radius); + padding: var(--space); + margin-top: var(--space); + margin-bottom: var(--space); + } + + p, + li { + color: inherit; + /* RPL/Body Regular/14-BodyReg */ + font-family: var(--font-family-sans); + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 20px; + } + + a, + a:visited { + color: var(--color-link); + } + + a:hover { + color: var(--color-link-hovered); + } + ` + + @property() src: string = '' + + @query('#project-title', true) + private _nameInput!: HTMLInputElement + + @query('#save-button', true) + private _saveButton!: HTMLInputElement + + @query('play-dialog', true) + private _dialog!: PlayDialog + + open(name: string): void { + this._nameInput.value = name || '' + this._saveButton.disabled = this._nameInput.value === '' + this._dialog.open() + this._nameInput.focus() + } + + close(): void { + this._dialog.close() + } + + _save(): void { + if (!this._nameInput.value) { + return + } + this._saveButton.disabled = true + this.dispatchEvent( + Bubble('save-dialog-submit', this._nameInput.value) + ) + } + + protected override render(): TemplateResult { + return html` + + { + this._saveButton.disabled = !this._nameInput.value + if (e.key === 'Enter') { + this._save() + } + }} + /> + this._save()} + /> + + ` + } +} diff --git a/src/storage/local-project-storage-client.ts b/src/storage/local-project-storage-client.ts new file mode 100644 index 0000000..de24da8 --- /dev/null +++ b/src/storage/local-project-storage-client.ts @@ -0,0 +1,118 @@ +// Implementation of ProjectStorageClient backed by IndexedDB, +// for storing play project data and files locally in the browser. +// +// This is fairly primitive, and doesn't bother with relational data --- +// it simply stores the entire Project objects, ProjectFiles attached. + +import type { + PlayProject, + ProjectStorageClient +} from './project-storage-client.js' + +const DB_NAME = 'PlayProjectDB' +const DB_VERSION = 1 +const PROJECT_STORE = 'projects' + +function openDB(): Promise { + return new Promise((resolve, reject) => { + const request = indexedDB.open(DB_NAME, DB_VERSION) + + request.onupgradeneeded = () => { + const db = request.result + if (!db.objectStoreNames.contains(PROJECT_STORE)) { + db.createObjectStore(PROJECT_STORE, {keyPath: 'id'}) + } + } + + request.onsuccess = () => { + resolve(request.result) + } + + request.onerror = () => { + reject(request.error) + } + }) +} + +/** Browser-local implementation of ProjectStorageClient. */ +export class LocalProjectStorageClient implements ProjectStorageClient { + async CreateProject(name: string): Promise { + const db = await openDB() + const transaction = db.transaction([PROJECT_STORE], 'readwrite') + const store = transaction.objectStore(PROJECT_STORE) + + const id = crypto.randomUUID() + const project: PlayProject = { + id, + name, + createdAt: new Date(), + updatedAt: new Date(), + authorId: '', + files: [] + } + + return new Promise((resolve, reject) => { + const request = store.add(project) + request.onsuccess = () => { + resolve(project) + } + request.onerror = () => { + reject(request.error) + } + }) + } + + async UpdateProject(project: PlayProject): Promise { + const db = await openDB() + const transaction = db.transaction([PROJECT_STORE], 'readwrite') + const store = transaction.objectStore(PROJECT_STORE) + + project.updatedAt = new Date() + + return new Promise((resolve, reject) => { + const request = store.put(project) + request.onsuccess = () => { + resolve() + } + request.onerror = () => { + reject(request.error) + } + }) + } + + async GetProject(id: string): Promise { + const db = await openDB() + const transaction = db.transaction([PROJECT_STORE], 'readonly') + const store = transaction.objectStore(PROJECT_STORE) + + return new Promise((resolve, reject) => { + const request = store.get(id) + request.onsuccess = () => { + if (request.result) { + resolve(request.result) + } else { + reject(new Error('Project not found')) + } + } + request.onerror = () => { + reject(request.error) + } + }) + } + + async ListProjects(): Promise { + const db = await openDB() + const transaction = db.transaction([PROJECT_STORE], 'readonly') + const store = transaction.objectStore(PROJECT_STORE) + + return new Promise((resolve, reject) => { + const request = store.getAll() + request.onsuccess = () => { + resolve(request.result) + } + request.onerror = () => { + reject(request.error) + } + }) + } +} diff --git a/src/storage/project-manager.ts b/src/storage/project-manager.ts new file mode 100644 index 0000000..daf39e3 --- /dev/null +++ b/src/storage/project-manager.ts @@ -0,0 +1,75 @@ +import type { + PlayProject, + ProjectStorageClient +} from './project-storage-client.js' + +const SESSION_PROJECT_ID = 'SESSION_PROJECT_ID' + +/** + * Operator for saving and loading projects. Handles logic for when and how to save. + * + * The underlying storage mechanism is abstracted away by the injected storage client. + */ +export class ProjectManager { + private projectStorageClient: ProjectStorageClient + private currentProject: PlayProject | undefined + + constructor(projectStorageClient: ProjectStorageClient) { + this.projectStorageClient = projectStorageClient + + const restoredProjectStr = + globalThis.sessionStorage.getItem(SESSION_PROJECT_ID) + if (restoredProjectStr) { + try { + this.currentProject = JSON.parse(restoredProjectStr) + } catch (e) { + // fall-through --- invalid data, just ignore it. + } + } + } + + getCurrentProject(): PlayProject | undefined { + return this.currentProject + } + + async saveProject(name: string, src: string): Promise { + let project = this.getCurrentProject() + if (project === undefined) { + project = await this.projectStorageClient.CreateProject(name) + } + + project.files = [{name: 'main.tsx', content: new TextEncoder().encode(src)}] + project.name = name + project.updatedAt = new Date() + await this.projectStorageClient.UpdateProject(project) + + // Store the project in memory and in sessionStorage + this.setCurrentProject(project) + } + + async getProjectList(): Promise { + return this.projectStorageClient.ListProjects() + } + + async loadProject(id: string): Promise { + const project = await this.projectStorageClient.GetProject(id) + this.setCurrentProject(project) + return project + } + + clearCurrentProject(): void { + this.setCurrentProject(undefined) + } + + private setCurrentProject(project: PlayProject | undefined): void { + this.currentProject = project + if (project) { + globalThis.sessionStorage.setItem( + SESSION_PROJECT_ID, + JSON.stringify(project) + ) + } else { + globalThis.sessionStorage.removeItem(SESSION_PROJECT_ID) + } + } +} diff --git a/src/storage/project-storage-client.ts b/src/storage/project-storage-client.ts new file mode 100644 index 0000000..0bc1713 --- /dev/null +++ b/src/storage/project-storage-client.ts @@ -0,0 +1,35 @@ +/** + * Interface for a client that can store and retrieve PlayProjects. + * + * This can be injected into play-pen to provide a different implementation. + */ +export interface ProjectStorageClient { + CreateProject(name: string): Promise + UpdateProject(project: PlayProject): Promise + GetProject(id: string): Promise + ListProjects(): Promise +} + +export interface PlayProject { + /** readonly */ + id?: string | undefined + name: string + /** readonly */ + createdAt?: Date | undefined + /** readonly */ + updatedAt?: Date | undefined + /** t2_ id of the user who created a note */ + authorId?: string | undefined + files: PlayProjectFile[] +} + +export interface PlayProjectFile { + /** readonly */ + id?: string | undefined + name: string + content: Uint8Array + /** readonly */ + createdAt?: Date | undefined + /** readonly */ + updatedAt?: Date | undefined +} From 8db352cdf479fc8a13001a16955b71fdbcac463e Mon Sep 17 00:00:00 2001 From: Andrew Gunsch Date: Fri, 27 Sep 2024 11:57:50 -0700 Subject: [PATCH 4/4] pre-pr review cleanup --- src/elements/play-dialog/play-dialog.ts | 3 -- src/elements/play-pen-header.ts | 12 +++--- src/elements/play-pen/play-pen.ts | 2 - src/elements/play-project-button.ts | 13 ------ src/elements/play-project-load-dialog.ts | 46 +------------------- src/elements/play-project-save-dialog.ts | 53 ------------------------ 6 files changed, 7 insertions(+), 122 deletions(-) diff --git a/src/elements/play-dialog/play-dialog.ts b/src/elements/play-dialog/play-dialog.ts index 6933a99..ccc13c0 100644 --- a/src/elements/play-dialog/play-dialog.ts +++ b/src/elements/play-dialog/play-dialog.ts @@ -99,9 +99,6 @@ export class PlayDialog extends LitElement implements PlayDialogLike { close(): void { this._dialog.close() - this.dispatchEvent( - new CustomEvent('closed', {bubbles: true, composed: true}) - ) } protected override render(): TemplateResult { diff --git a/src/elements/play-pen-header.ts b/src/elements/play-pen-header.ts index e3fd7e8..f81e172 100644 --- a/src/elements/play-pen-header.ts +++ b/src/elements/play-pen-header.ts @@ -7,6 +7,7 @@ import { } from 'lit' import {customElement, property, query} from 'lit/decorators.js' import {ifDefined} from 'lit/directives/if-defined.js' +import {ProjectManager} from '../storage/project-manager.js' import {defaultSettings} from '../storage/settings-save.js' import {Bubble} from '../utils/bubble.js' import {cssReset} from '../utils/css-reset.js' @@ -30,7 +31,6 @@ import './play-project-load-dialog.js' import './play-project-save-dialog.js' import './play-resizable-text-input.js' import './play-settings-dialog.js' -import {ProjectManager} from '../storage/project-manager.js' declare global { interface HTMLElementEventMap { @@ -203,11 +203,11 @@ export class PlayPenHeader extends LitElement { @click=${() => openURL('https://developers.reddit.com/docs')} > this._export.open()} - @save-project=${() => this.openSaveDialog()} - @load-project=${() => this.loadProject()} + size="small" + .srcByLabel=${this.srcByLabel} + @open-export-dialog=${() => this._export.open()} + @save-project=${() => this.openSaveDialog()} + @load-project=${() => this.loadProject()} > ` : html`

No projects available

`}`} -