Browse Source

Moves bootstrap loading into base

Improves template replacement bindings
main
Eric Amodio 2 years ago
parent
commit
b2d09b8774
7 changed files with 73 additions and 49 deletions
  1. +26
    -37
      src/webviews/apps/home/home.ts
  2. +1
    -2
      src/webviews/apps/rebase/rebase.ts
  3. +2
    -3
      src/webviews/apps/settings/settings.ts
  4. +4
    -2
      src/webviews/apps/shared/appBase.ts
  5. +2
    -2
      src/webviews/apps/shared/appWithConfigBase.ts
  6. +36
    -0
      src/webviews/apps/shared/dom.ts
  7. +2
    -3
      src/webviews/apps/welcome/welcome.ts

+ 26
- 37
src/webviews/apps/home/home.ts View File

@ -1,4 +1,4 @@
/*global window*/
/*global*/
import './home.scss';
import { provideVSCodeDesignSystem, vsCodeButton, vsCodeDivider } from '@vscode/webview-ui-toolkit';
import { Disposable } from 'vscode';
@ -13,8 +13,7 @@ export class HomeApp extends App {
private $slot2!: HTMLDivElement;
constructor() {
super('HomeApp', (window as any).bootstrap);
(window as any).bootstrap = undefined;
super('HomeApp');
}
protected override onInitialize() {
@ -34,7 +33,7 @@ export class HomeApp extends App {
protected override onBind(): Disposable[] {
const disposables = super.onBind?.() ?? [];
disposables.push(DOM.on('[data-action]', 'click', (e, target: HTMLElement) => this.onClicked(e, target)));
disposables.push(DOM.on('[data-action]', 'click', (e, target: HTMLElement) => this.onActionClicked(e, target)));
return disposables;
}
@ -58,7 +57,7 @@ export class HomeApp extends App {
}
}
private onClicked(e: MouseEvent, target: HTMLElement) {
private onActionClicked(e: MouseEvent, target: HTMLElement) {
const action = target.dataset.action;
if (action?.startsWith('command:')) {
this.sendCommand(ExecuteCommandType, { command: action.slice(8) });
@ -68,8 +67,8 @@ export class HomeApp extends App {
private updateState() {
const { subscription, welcomeVisible } = this.state;
if (subscription.account?.verified === false) {
this.insertTemplate('state:verify-email', this.$slot1);
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
DOM.insertTemplate('state:verify-email', this.$slot1);
DOM.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
return;
}
@ -80,57 +79,47 @@ export class HomeApp extends App {
switch (subscription.state) {
case SubscriptionState.Free:
if (welcomeVisible) {
this.insertTemplate('welcome', this.$slot1);
this.insertTemplate('state:free', this.$slot2);
DOM.insertTemplate('welcome', this.$slot1);
DOM.insertTemplate('state:free', this.$slot2);
} else {
this.insertTemplate('state:free', this.$slot1);
this.insertTemplate('links', this.$slot2);
DOM.insertTemplate('state:free', this.$slot1);
DOM.insertTemplate('links', this.$slot2);
}
break;
case SubscriptionState.FreeInPreview: {
const remaining = getSubscriptionTimeRemaining(subscription, 'days') ?? 0;
this.insertTemplate('state:free-preview', this.$slot1, {
previewDays: `${remaining === 1 ? `${remaining} more day` : `${remaining} more days`}`,
DOM.insertTemplate('state:free-preview', this.$slot1, {
bindings: {
previewDays: `${remaining === 1 ? `${remaining} more day` : `${remaining} more days`}`,
},
});
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
DOM.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
break;
}
case SubscriptionState.FreePreviewExpired:
this.insertTemplate('state:free-preview-expired', this.$slot1);
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
DOM.insertTemplate('state:free-preview-expired', this.$slot1);
DOM.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
break;
case SubscriptionState.FreePlusInTrial: {
const remaining = getSubscriptionTimeRemaining(subscription, 'days') ?? 0;
this.insertTemplate('state:plus-trial', this.$slot1, {
trialDays: `${remaining === 1 ? `${remaining} day` : `${remaining} days`}`,
DOM.insertTemplate('state:plus-trial', this.$slot1, {
bindings: {
trialDays: `${remaining === 1 ? `${remaining} day` : `${remaining} days`}`,
},
});
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
DOM.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
break;
}
case SubscriptionState.FreePlusTrialExpired:
this.insertTemplate('state:plus-trial-expired', this.$slot1);
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
DOM.insertTemplate('state:plus-trial-expired', this.$slot1);
DOM.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
break;
case SubscriptionState.Paid:
this.insertTemplate('state:paid', this.$slot1);
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
DOM.insertTemplate('state:paid', this.$slot1);
DOM.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
break;
}
}
private insertTemplate(id: string, $slot: HTMLDivElement, bindings?: Record<string, unknown>): void {
const $template = (document.getElementById(id) as HTMLTemplateElement)?.content.cloneNode(true);
$slot.replaceChildren($template);
if (bindings != null) {
for (const [key, value] of Object.entries(bindings)) {
const $el = $slot.querySelector(`[data-bind="${key}"]`);
if ($el != null) {
$el.textContent = String(value);
}
}
}
}
}
new HomeApp();

+ 1
- 2
src/webviews/apps/rebase/rebase.ts View File

@ -37,8 +37,7 @@ class RebaseEditor extends App {
private readonly commitTokenRegex = new RegExp(encodeURIComponent(`\${commit}`));
constructor() {
super('RebaseEditor', (window as any).bootstrap);
(window as any).bootstrap = undefined;
super('RebaseEditor');
}
protected override onInitialize() {

+ 2
- 3
src/webviews/apps/settings/settings.ts View File

@ -1,4 +1,4 @@
/*global window document IntersectionObserver*/
/*global document IntersectionObserver*/
import './settings.scss';
import { State } from '../../settings/protocol';
import { AppWithConfig } from '../shared/appWithConfigBase';
@ -15,8 +15,7 @@ export class SettingsApp extends AppWithConfig {
private _sections = new Map<string, boolean>();
constructor() {
super('SettingsApp', (window as any).bootstrap);
(window as any).bootstrap = undefined;
super('SettingsApp');
}
protected override onInitialize() {

+ 4
- 2
src/webviews/apps/shared/appBase.ts View File

@ -34,13 +34,15 @@ export abstract class App {
private readonly _api: VsCodeApi;
protected state: State;
constructor(protected readonly appName: string, state: State) {
constructor(protected readonly appName: string) {
this.log(`${this.appName}.ctor`);
this.state = (window as any).bootstrap;
(window as any).bootstrap = undefined;
this._api = acquireVsCodeApi();
initializeAndWatchThemeColors();
this.state = state;
requestAnimationFrame(() => {
this.log(`${this.appName}.initializing`);

+ 2
- 2
src/webviews/apps/shared/appWithConfigBase.ts View File

@ -27,8 +27,8 @@ export abstract class AppWithConfig extends Ap
private _changes = Object.create(null) as Record<string, any>;
private _updating: boolean = false;
constructor(appName: string, state: State) {
super(appName, state);
constructor(appName: string) {
super(appName);
}
protected override onInitialized() {

+ 36
- 0
src/webviews/apps/shared/dom.ts View File

@ -69,4 +69,40 @@ export namespace DOM {
},
};
}
export function insertTemplate(
id: string,
$slot: HTMLDivElement,
options?: { bindings?: Record<string, unknown>; visible?: Record<string, boolean> },
): void {
const $template = (document.getElementById(id) as HTMLTemplateElement)?.content.cloneNode(true);
$slot.replaceChildren($template);
if (options?.visible != null) {
const $els = $slot.querySelectorAll<HTMLElement>(`[data-visible]`);
for (const $el of $els) {
const key = $el.dataset.visible;
if (!key) continue;
if (options.visible[key]) {
$el.style.display = 'initial';
} else {
$el.style.display = 'none';
}
}
}
if (options?.bindings != null) {
const $els = $slot.querySelectorAll<HTMLElement>(`[data-bind]`);
for (const $el of $els) {
const key = $el.dataset.bind;
if (!key) continue;
const value = options.bindings[key];
if (value == null) continue;
$el.textContent = String(value);
}
}
}
}

+ 2
- 3
src/webviews/apps/welcome/welcome.ts View File

@ -1,4 +1,4 @@
/*global window*/
/*global*/
import './welcome.scss';
import type { State } from '../../welcome/protocol';
import { AppWithConfig } from '../shared/appWithConfigBase';
@ -6,8 +6,7 @@ import { AppWithConfig } from '../shared/appWithConfigBase';
export class WelcomeApp extends AppWithConfig<State> {
constructor() {
super('WelcomeApp', (window as any).bootstrap);
(window as any).bootstrap = undefined;
super('WelcomeApp');
}
}

Loading…
Cancel
Save