Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Making of paint.js.org: eine Web-Component-basierte Produktivitäts-PWA

Making of paint.js.org: eine Web-Component-basierte Produktivitäts-PWA

Progressive Web Apps und neue, durch Project Fugu eingeführte Web-Plattform-APIs erlauben es Entwicklern, Produktivitätsapps der Desktopklasse mit Webtechnologien zu schreiben. In dieser Session zeigt Ihnen Christian Liebel von Thinktecture die kritischen Aspekte der Implementierung von paint.js.org, einem webbasierten Klon des Produktivitätsapp-Dinosauriers Microsoft Paint. Es läuft großartig im Browser, als eigenständige Anwendung und lässt sich dank Web Components sogar in fremde Anwendungen integrieren. Und weil alles webbasiert ist, läuft es auf allen Betriebssystemen von Mobile bis Desktop, und nicht nur Windows 95.

Christian Liebel

April 29, 2023
Tweet

More Decks by Christian Liebel

Other Decks in Programming

Transcript

  1. Hello, it’s me. Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Christian

    Liebel Twitter: @christianliebel Email: christian.liebel @thinktecture.com Angular & PWA Slides: thinktecture.com /christian-liebel
  2. https://paint.js.org – Productivity app – Draw images – Lots of

    actions & tools – Installable – Read/save files – Copy/paste images from/to clipboard – Share files to other apps – Register for file extensions Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Demo
  3. Web Components and Architecture Canvas and Input Offline Capability and

    Installability Copy and Paste File Access and File Handling Dark Mode Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Agenda
  4. Web Components and Architecture Canvas and Input Offline Capability and

    Installability Copy and Paste File Access and File Handling Dark Mode Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Agenda
  5. Web Components <my-component value="3"> </my-component> – The web’s native component

    model – Easy interop – Very basic: No data binding, dependency injection, … Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Web Components and Architecture
  6. Related APIs Custom Elements API Definition of custom HTML elements

    Interaction via custom DOM attributes, properties, and events Shadow DOM Can prevent DOM access from outside Can prevent CSS manipulation from outside HTML Templates (not used in this demo) Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Web Components and Architecture
  7. Lit – Provided by Google – Lightweight library (5 KB)

    – Custom lifecycle on top of Web Components – Tagged template literals for HTML and CSS to prevent XSS attacks including support for data binding – TypeScript decorators for component registration and attribute/property declaration Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Web Components and Architecture
  8. Lit @customElement('paint-tool-box') export class ToolBox { render(): TemplateResult { return

    html` ${tools.map( (tool) => html`<paint-tool .tool=${tool} title="${tool.tooltip}" class="${this.drawingContext?.tool === tool ? 'active' : ''} ${tool.instance ? '' : 'unavailable'}" @pointerup="${() => this.selectTool(tool)}" ></paint-tool>`, )} `; } } Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Web Components and Architecture
  9. Web Components and Architecture Canvas and Input Offline Capability and

    Installability Copy and Paste File Access and File Handling Dark Mode Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Agenda
  10. Canvas – Plain bitmap for the web – Cross-platform, hardware-

    accelerated graphics operations – Supports different contexts (2D, 3D: WebGL, WebGL 2.0) – Supported on all evergreen browsers and on IE 9+ Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Canvas and Input
  11. Canvas 2D Context fillRect(x, y, width, height) strokeRect(x, y, width,

    height) beginPath() moveTo(x, y) lineTo(x, y) fill() stroke() Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Canvas and Input
  12. Pointer Events Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Canvas and

    Input Users nowadays use different input methods, cross-platform apps should cover all of them Pointer Events offer an abstract interface to catch all input methods (pointerdown, pointermove, pointerup) event.offsetX/event.offsetY contain the pointer’s position relative to the listener
  13. Web Components and Architecture Canvas and Input Offline Capability and

    Installability Copy and Paste File Access and File Handling Dark Mode Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Agenda
  14. Web App Manifest Distinguishes Web Apps from Websites JSON-based file

    containing metadata for apps only Apps can be identified by search engines, app store providers, etc. Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Offline Capability and Installability
  15. manifest.webmanifest { "short_name": "Paint", "name": "Paint Workshop", "theme_color": "white", "icons":

    [{ "src": "icon.png", "sizes": "512x512" }], "start_url": "/index.html", "display": "standalone", "shortcuts": [/* … */] } Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Offline Capability and Installability Names Icons Display Mode Shortcuts Start URL Theme color (status bar/window bar)
  16. Service Worker JavaScript snippet executed in an own thread, registered

    by the website Acts as a controller, proxy, or interceptor Has a cache to store responses (for offline availability and performance) Can wake up even when the website is closed and perform background tasks (e.g., push notifications or sync) Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Offline Capability and Installability
  17. Service Worker Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Offline Capability

    and Installability Service Worker Internet Website HTML/JS Cache fetch
  18. Web Components and Architecture Canvas and Input Offline Capability and

    Installability Copy and Paste File Access and File Handling Dark Mode Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Agenda
  19. Browser Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Capabilities navigator.share({ url:

    'http://example.com' }); ShareIntent DataTransferManager … NSSharingServicePicker
  20. Async Clipboard API Allows reading from/writing to the clipboard in

    an asynchronous manner (UI won’t freeze during long-running operations) Reading from the clipboard requires user consent first (privacy!) Supported by Chrome, Edge and Safari Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Copy and Paste
  21. Async Clipboard API const btnCopy = document.querySelector('#copy'); btnCopy.addEventListener('click', async ()

    => { const blob = await toBlob(canvas); await navigator.clipboard.write([ new ClipboardItem({[blob.type]: blob}) ]); }); Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Copy and Paste
  22. Async Clipboard API const btnPaste = document.querySelector('#paste'); btnPaste.addEventListener('click', async ()

    => { const clipboardItems = await navigator.clipboard.read(); for (const clipboardItem of clipboardItems) { for (const type of clipboardItem.types) { if (type === 'image/png') { const blob = await clipboardItem.getType(type); const image = await getImage(blob); ctx.drawImage(image, 0, 0); } } } }); Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Copy and Paste
  23. Web Components and Architecture Canvas and Input Offline Capability and

    Installability Copy and Paste File Access and File Handling Dark Mode Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Agenda
  24. File System Access API Some applications heavily rely on working

    with files (e.g. Visual Studio Code, Adobe Photoshop, …) File System Access API allows you to open, save and override files and directories Supported by Chrome, Edge Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA File Access and File Handling
  25. File System Access API btnSave.addEventListener('click', async () => { const

    blob = await toBlob(canvas); const handle = await window.showSaveFilePicker(fileOptions); const writable = await handle.createWritable(); await writable.write(blob); await writable.close(); }); Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA File Access and File Handling
  26. File System Access API btnOpen.addEventListener('click', async () => { const

    [handle] = await window.showOpenFilePicker(fileOptions); const file = await handle.getFile(); const image = await getImage(file); ctx.drawImage(image, 0, 0); }); Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA File Access and File Handling
  27. File Handling API Register your PWA as a handler for

    file extensions Requires installing the application first Declare supported extensions in Web App Manifest and add imperative code to your application logic Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA File Access and File Handling
  28. File Handling API "file_handlers": [{ "action": "/index.html", "accept": { "image/png":

    [".png"] } }] Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA File Access and File Handling
  29. File Handling API if ('launchQueue' in window) { launchQueue.setConsumer(async params

    => { const [handle] = params.files; if (handle) { const file = await handle.getFile(); const image = await getImage(file); ctx.drawImage(image, 0, 0); } }); } Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA File Access and File Handling
  30. Web Components and Architecture Canvas and Input Offline Capability and

    Installability Copy and Paste File Access and File Handling Dark Mode Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Agenda
  31. CSS Custom Properties – Also known as “CSS variables” –

    Cascade even through Shadow DOM boundaries, i.e. they can be accessed by subordinate components – Paint.js.org defines the Windows 95 color scheme on app root level :host { --button-face: rgb(192 192 192); --button-light: white; --button-dark: rgb(128 128 128); --button-darker: black; --button-text: black; } Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Dark Mode
  32. prefers-color-scheme CSS Media Feature – The prefers-color-scheme CSS media feature

    indicates which color scheme the user prefers – Takes two values: – light, if the user prefers a dark-on-light color scheme (or didn’t actively make a decision) – dark, if the user prefers a light-on-dark color scheme – Preference is usually inherited form the operating system’s settings – Changes are automatically reflected (e.g., when the operating system switches between light and dark mode based on time) Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Dark Mode
  33. CSS-Only Light Mode :host { --button-face: rgb(192 192 192); --button-light:

    white; --button-dark: rgb(128 128 128); --button-darker: black; --button-text: black; } Dark Mode @media (prefers-color-scheme: dark) { :host { --button-face: rgb(64 64 64); --button-light: rgb(128 128 128); --button-dark: rgb(32 32 32); --button-text: white; } } Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Dark Mode
  34. Web Components: Very robust, works consistently across evergreen browsers, perfect

    for integration scenarios. Lit: Shares basic concepts with other frameworks/libraries (such as Angular), but is much more lightweight. Paint.js.org is smaller (= transferred bytes) than the Windows 95 of Paint (320K)! Capabilities: Powerful APIs available on Chromium and WebKit-based browsers, fallbacks are used for other browsers. Conclusion: Successful project! 🥳 You can perfectly implement web- based (= cross-platform), desktop-class productivity applications. Making of paint.js.org Eine Web-Component-basierte Produktivitäts-PWA Summary