import { Utils } from './lib/Utils'; import html2canvas from 'html2canvas'; import { c } from './lib/Log'; import { Api } from './Api'; abstract class Modal { protected div: HTMLDivElement; protected doneBtn: HTMLAnchorElement | null; protected loader: HTMLImageElement; constructor(className: string) { this.div = document.querySelector(`div.modal.${className}`) as HTMLDivElement; this.doneBtn = this.div.querySelector('.js-close'); this.loader = this.div.querySelector('.js-loader') as HTMLImageElement; this.doneBtn?.addEventListener('click', (e) => { e.preventDefault(); this.hide(); }); this.div.addEventListener('click', (e) => { if (e.target === this.div) { c.debug(`modal:background.click`); this.hide(); } }); } /** * Hooks: Implement those to perform the actual work done on show and hide. */ abstract performBeforeShow(): Promise; abstract performShow(): Promise; abstract performHide(): Promise; async show() { await this.performBeforeShow(); this.div.classList.add('fadeout'); this.div.classList.remove('hide'); await Utils.delay(100); this.div.classList.remove('fadeout'); await this.performShow(); this.loader.classList.add('hide'); } async hide() { this.div.classList.add('fadeout'); await Utils.delay(200); this.div.classList.add('hide'); this.div.classList.remove('fadeout'); await this.performHide(); } } export class ShareScreenshotModal extends Modal { private imResult = this.div.querySelector('.js-result') as HTMLImageElement; constructor() { super(`share-screenshot`); } async performBeforeShow() { this.loader.classList.remove('hide'); } async performShow() { await Utils.delay(800); /// <- for good ux const el = document.querySelector('div.page-inner') as HTMLDivElement; const canvas = await html2canvas(el, { logging: false, /// <- inoperant in our version of html2canvas. onclone: (doc) => { const clonedEl = doc.querySelector('div.page-inner') as HTMLDivElement; clonedEl.classList.add('html2canvas'); const watermark = doc.querySelector('div.watermark') as HTMLDivElement; watermark.style.visibility = `visible`; } }); this.imResult.src = canvas.toDataURL(); } async performHide() { this.imResult.src = ""; } } export class SavePublishModal extends Modal { private saveBtn = this.div.querySelector('.js-save') as HTMLAnchorElement; private form = this.div.querySelector('form') as HTMLFormElement; constructor( private quill: Quill ) { super(`save-publish`); /// vv Url fields auto-select. const urlInputs = Array.from( this.div.querySelectorAll('.doc-url') ) as HTMLInputElement[]; for (const x of urlInputs) { x.addEventListener('focus', () => { x.select(); }); } this.saveBtn.addEventListener('click', (e) => { e.preventDefault(); if (! this.form.reportValidity()) { /// Form is invalid. return ; } this.save(); }); this.form.addEventListener('submit', (e) => { e.preventDefault(); this.saveBtn.click(); }); } async performBeforeShow() {} async performShow() {} async performHide() {} async save() { this.loader.classList.remove('hide'); const inputTitle = this.div.querySelector('.doc-title') as HTMLInputElement; const title = inputTitle.value; const contents = this.quill.getContents(); c.log(JSON.stringify({ title, contents })); const success = await Api.shared.postEdit({ title, contents }); await Utils.delay(800); /// <- for good ux if (success) { this.loader.classList.add('hide'); this.hide(); /// For now we always redirect to the edit url here: /// vv const inputEditUrl = this.div.querySelector('.doc-edit-url') as HTMLInputElement; window.location.href = inputEditUrl.value; } else { window.alert(`did not manage to save`); } } }