changelog dialog

This commit is contained in:
Rachel Powers
2024-04-21 00:31:44 -07:00
parent cf1f3e15af
commit 55aa3cf4aa
9 changed files with 1293 additions and 4 deletions

26
CHANGELOG.md Normal file
View File

@@ -0,0 +1,26 @@
## v0.2.0
### Share VM State!
New in this release is the ability to share the entire VM with you share a link. This means code; connected devices and their state; as well as the state of the stack, registers, and line number of the active IC!
Additionally you can now save and load any number of sessions in your browser. Access this functionality from the main menu.
Also! the project has officially moved to https://ic10emu.dev . Old share links *should* redirect, but if not simply copy the fragment (the part of the url starting with the `#` symbol)
#### List of changes
- Move build system from Webpack to [Rsbuild](https://rsbuild.dev/) (way faster build times).
- VM now supports exporting and restoring a frozen state.
- Share links updates to use frozen vm state.
- Save and load sessions from the browser's IndexedDB storage.
- project now includes tailwindcss to make frontend dev easier.
- Changelog dialog to notify users of updates.
## v0.1.0
### **Initial Release**:
IC10emu is released to the public! edit and share your IC10 scripts!
- view and edit stack and registers

View File

@@ -62,6 +62,7 @@
"jquery": "^3.7.1",
"lit": "^3.1.3",
"lzma-web": "^3.0.1",
"marked": "^12.0.2",
"stream-browserify": "^3.0.0",
"uuid": "^9.0.1",
"vm-browserify": "^1.1.2"

9
www/pnpm-lock.yaml generated
View File

@@ -53,6 +53,9 @@ dependencies:
lzma-web:
specifier: ^3.0.1
version: 3.0.1
marked:
specifier: ^12.0.2
version: 12.0.2
stream-browserify:
specifier: ^3.0.0
version: 3.0.0
@@ -2920,6 +2923,12 @@ packages:
resolution: {integrity: sha512-sb5cdfd+PLNljK/HUgYzvnz4G7r0GFK8sonyGrqJS0FVyUQjFYcnmU2LqTWFi6r48lH1ZBstnxyLWepKM/t7QA==}
dev: false
/marked@12.0.2:
resolution: {integrity: sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==}
engines: {node: '>= 18'}
hasBin: true
dev: false
/md5.js@1.3.5:
resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==}
dependencies:

View File

@@ -37,6 +37,13 @@ export default defineConfig({
),
to: "shoelace/assets",
},
{
from: path.resolve(
__dirname,
"../CHANGELOG.md"
),
to: "static/",
}
],
}),
new CssExtractRspackPlugin(),

View File

@@ -21,6 +21,8 @@ import { openFile, saveFile } from "../utils";
import "../virtual_machine/ui";
import "./save";
import { SaveDialog } from "./save";
import "./welcome";
import { AppWelcome } from "./welcome";
declare global {
const __COMMIT_HASH__: string;
@@ -61,6 +63,7 @@ export class App extends BaseElement {
@query("ace-ic10") editor: IC10Editor;
@query("session-share-dialog") shareDialog: ShareSessionDialog;
@query("save-dialog") saveDialog: SaveDialog;
@query("app-welcome") appWelcome: AppWelcome;
// get editor() {
// return this.renderRoot.querySelector("ace-ic10") as IC10Editor;
@@ -83,6 +86,7 @@ export class App extends BaseElement {
root.addEventListener("app-export", this._handleExport.bind(this));
root.addEventListener("app-save", this._handleSave.bind(this));
root.addEventListener("app-load", this._handleLoad.bind(this));
root.addEventListener("app-changelog", this._handleChangelog.bind(this));
return root;
}
@@ -104,11 +108,54 @@ export class App extends BaseElement {
</div>
<session-share-dialog></session-share-dialog>
<save-dialog></save-dialog>
<app-welcome @sl-after-hide=${this.afterWelcomeHide}></app-welcome>
</div>
`;
}
firstUpdated(): void {}
firstUpdated(): void {
setTimeout(() => {
this.checkSeenVersion();
}, 2000);
}
checkSeenVersion() {
const seenVersionsStr = window.localStorage.getItem("seenVersions");
let seenVersions: string[] = [];
if (seenVersionsStr !== null && seenVersionsStr.length > 0) {
try {
const saved = JSON.parse(seenVersionsStr);
seenVersions = saved;
} catch (e) {
console.log("error pulling seen versions", e);
}
}
const ourVer = `${this.appVersion}_${this.gitVer}_${this.buildDate}`;
if (!seenVersions.includes(ourVer)) {
this.appWelcome.show();
}
}
afterWelcomeHide() {
const seenVersionsStr = window.localStorage.getItem("seenVersions");
const seenVersions: string[] = [];
if (seenVersionsStr !== null && seenVersionsStr.length > 0) {
try {
const saved = JSON.parse(seenVersionsStr);
seenVersions.concat(saved);
} catch (e) {
console.log("error pulling seen versions", e);
}
}
const unique = new Set(seenVersions);
const ourVer = `${this.appVersion}_${this.gitVer}_${this.buildDate}`;
if (this.appWelcome.dontShowAgain) {
unique.add(ourVer)
} else {
unique.delete(ourVer)
}
window.localStorage.setItem("seenVersions", JSON.stringify(Array.from(unique)));
}
_handleShare(_e: Event) {
// TODO:
@@ -130,6 +177,10 @@ export class App extends BaseElement {
_handleOpenFile(_e: Event) {
openFile(window.Editor.editor);
}
_handleChangelog(_e: Event) {
this.appWelcome.show();
}
}

1113
www/src/ts/app/gfm-styles.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -157,6 +157,11 @@ export class Nav extends BaseElement {
<sl-menu-item value="preset-demo"> Demo </sl-menu-item>
</sl-menu>
</sl-menu-item>
<sl-divider></sl-divider>
<sl-menu-item value="changelog">
Changelog
<sl-icon name="journal-text" slot="prefix"></sl-icon>
</sl-menu-item>
</sl-menu>
</sl-dropdown>
</div>
@@ -246,6 +251,10 @@ export class Nav extends BaseElement {
break;
case "preset-demo":
window.location.hash = "demo";
break;
case "changelog":
this.dispatchEvent(new CustomEvent("app-changelog", { bubbles: true }));
break;
default:
console.log("Unknown main menu item", item.value);
}

75
www/src/ts/app/welcome.ts Normal file
View File

@@ -0,0 +1,75 @@
import { html, css } from "lit";
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { customElement, property, query, state } from "lit/decorators.js";
import { BaseElement, defaultCss } from "../components";
import { SlDialog, SlSwitch } from "@shoelace-style/shoelace";
import { until } from "lit/directives/until.js";
import "@shoelace-style/shoelace/dist/components/spinner/spinner.js";
import '@shoelace-style/shoelace/dist/components/switch/switch.js';
import { marked } from "marked";
import { gfmStyles } from "./gfm-styles";
@customElement("app-welcome")
export class AppWelcome extends BaseElement {
static styles = [
...defaultCss,
gfmStyles,
css`
.welcome-dialog {
--width: 42rem;
}
`,
];
@property({ type: Boolean }) dontShowAgain: boolean;
constructor() {
super();
this.dontShowAgain = true;
}
@query("sl-dialog.welcome-dialog") dialog: SlDialog;
@query("sl-switch.dont-show-switch") dontShowSwitch: SlSwitch;
hide() {
this.dialog?.hide();
}
show() {
this.dialog?.show();
}
async getChangelog() {
const response = await fetch("static/CHANGELOG.md");
const blob = await response.blob();
const markdown = await blob.text();
const renderedText = await marked(markdown, {
async: true,
gfm: true,
});
return unsafeHTML(renderedText);
}
render() {
return html`
<sl-dialog class="welcome-dialog" label="Changlog">
<h6>Hey there!</h6>
<p>Looks like there have been some updates since you've last visit.</p>
<br />
<p>Check out the changelog below.</p>
<div class="p-4 border-1 border-solid rounded-lg max-h-80 mt-4 overflow-y-auto bg-neutral-900 markdown-body">
${until(this.getChangelog(), html`<sl-spinner class="ml-2 my-4" style="font-size: 2rem;"></sl-spinner>`)}
</div>
<div slot="footer">
<sl-switch class="dont-show-switch" size="small" ?checked=${this.dontShowAgain} @sl-change=${this._dontShowSwitchChange} >Don't show again</sl-switch>
</div>
</sl-dialog>
`;
}
_dontShowSwitchChange(e: CustomEvent) {
this.dontShowAgain = this.dontShowSwitch.checked;
}
}

View File

@@ -13,9 +13,7 @@ export function docReady(fn: () => void) {
}
function isZeroNegative(zero: number) {
const isZero = zero === 0;
const isNegative = 1 / zero === -Infinity;
return isNegative && isZero;
return Object.is(zero, -0)
}
export function numberToString(n: number): string {