import { AtomUri } from "@web-atoms/core/dist/core/AtomUri"; import { Inject } from "@web-atoms/core/dist/di/Inject"; import { NavigationService } from "@web-atoms/core/dist/services/NavigationService"; import Action from "@web-atoms/core/dist/view-model/Action"; import { AtomViewModel, Receive, Watch } from "@web-atoms/core/dist/view-model/AtomViewModel"; import Load from "@web-atoms/core/dist/view-model/Load"; import Channels from "../Channels"; import NewAppWindow from "../commands/new-app/NewAppWindow"; import Publish from "../commands/publish/Publish"; import IFileModel from "../model/FileModel"; import IContentModel from "../model/IContentModel"; import FileService from "../services/FileService"; import SourceService from "../services/SourceService"; declare var gtag: (a: "event", action: string , c: { event_category: string, event_label: string, value: number }) => void; const len = "http://a/".length; export default class AppHostViewModel extends AtomViewModel { public folder: string; // = "@web-atoms/sample-77"; public code: string; public imports: any; public root: IFileModel; public selectedFile: IFileModel; public documents: IFileModel[] = []; @Inject public sourceService: SourceService; @Inject private fileService: FileService; @Inject private navigationService: NavigationService; @Watch public showSelectedFile() { let file = this.selectedFile; do { file = file.parent; if (!file) { break; } file.isOpen = true; } while (true); } @Receive("delete-file") public async deleteFile(name: string, data: { url: string }) { for (const iterator of this.documents) { if (iterator.url === data.url) { this.documents.remove(iterator); if (this.selectedFile === iterator) { this.selectedFile = this.documents[0]; } return; } } } @Receive("open-url") public async openUrl(name: string, data: { url: string, name, features, start }) { // open model.. const url = /^http\:\/\//.test(data.url) ? data.url.substring(len) : data.url; const model = this.sourceService.root.get(url); this.selectedFile = model; if (data.start) { setTimeout(() => { this.app.broadcast(Channels.GotoLocation, data); }, 500); } } @Load({ init: true, watch: true }) public async loadCode() { const folder = this.folder || (this.folder = this.loadDefaultUrl()); if (!folder) { await this.createNewApp(); return; } await this.sourceService.updateModel(this.folder); this.root = this.sourceService.root; } @Action() public async save() { if (!this.sourceService.dirty) { return; } this.folder = await this.sourceService.save(this.folder); window.history.pushState("", `Web Atoms - ${this.folder}`, `/play/${this.folder}`); } @Action() public async publish() { if (typeof gtag !== "undefined") { gtag("event", "QR Code", { event_category: "View", event_label: "Open QR Code", value: 10 }); } await this.save(); const start = this.sourceService.folder.start ? this.sourceService.root.get(this.sourceService.folder.start) : this.selectedFile; const url = start.url; const wrap = start.content.indexOf("@web-atoms-embed: navigation-page") !== -1; await this.navigationService.openPage(Publish, { url, wrap }); } @Load({ watch: true }) public async loadSelectedFile() { const docs = this.documents; const s = this.selectedFile; if (!s) { return; } if (!docs.find((x) => x === s)) { docs.add(s); } } @Action() public async saveAs() { const p = prompt("Enter new Url to save", ""); if (!p) { return; } await this.fileService.create({ title: "Demo", description: "demo", url: p, clone: this.folder }); location.href = `/play/${p}`; } public async closeFile(file: IFileModel) { if (file.dirty) { // confirm... if (!await this.navigationService.confirm("All changes will be lost, are you sure?", "File is modified")) { return; } if (file.originalContent) { file.content = file.originalContent; file.model.setValue(file.content); } } const index = Math.max(0, this.documents.indexOf(file) - 1); this.documents.remove(file); if (this.documents.length > index) { this.selectedFile = this.documents[index]; } else { this.selectedFile = this.documents[0] ?? null; } } public async createNewApp() { while (true) { try { const template = await this.navigationService.openPage<{template: IContentModel, url: string}>(NewAppWindow); if (template.template) { await this.sourceService.generateTemplate(template.template); this.folder = template.url; this.root = this.sourceService.root; } else { location.href = template.url; } break; } catch (e) { // tslint:disable-next-line: no-console console.log(e); } } } private loadDefaultUrl(): string { const uri = new AtomUri(window.location.href); if ( !uri.query.url && !/^\/play\//.test(window.location.pathname)) { // return "@web-atoms/sample-9n/2"; return null; } const url = uri.query.url || window.location.pathname.substr("/play/".length); return url.toString(); } }