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

Implementing desktop-class productivity apps wi...

Implementing desktop-class productivity apps with Angular and Project Fuguย ๐Ÿ…ฐ๏ธ๐Ÿ’˜๐Ÿก

Chris is a GDE for Angular and web capabilities. In his hands-on workshop, youโ€™ll learn how to implement desktop-class productivity apps using the new Project Fugu web APIs. This joint project between Google, Intel, Microsoft, and others seeks to bring missing features to the web, including access to the local file system, clipboard, and registering Angular apps as default file handlers. Learn how you can finally bring productivity apps like IDEs, image editors, or office apps to the web! You also need to bring your own laptop to this workshop.

Christian Liebel

October 05, 2022
Tweet

More Decks by Christian Liebel

Other Decks in Programming

Transcript

  1. Hello, itโ€™s me. Implementing desktop-class productivity apps with Angular and

    Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Christian Liebel Twitter: @christianliebel Email: christian.liebel @thinktecture.com Angular & PWA Slides: thinktecture.com /christian-liebel
  2. Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก

    Timetable 09:00โ€“10:30 Block 1 10:30โ€“11:00 Break 11:00โ€“12:30 Block 2 12:30โ€“14:00 Lunch Break 14:00โ€“15:30 Block 3 15:30โ€“16:00 Break 16:00โ€“17:30 Block 4
  3. Things NOT to expect - Blueprint for PWA development -

    No AuthN/AuthZ Things To Expect - Extensive/up-to-date insights into PWA and Project Fugu - A productivity app use case that works on your desktop & smartphone - Lots of fun - Hands-on exercises with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Implementing desktop-class productivity apps
  4. 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 Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Demo Use Case
  5. (Workshop Edition) โ€“ Productivity app โ€“ Draw images โ€“ Lots

    of actions & tools โ€“ Installable โ€“ Read/save ๏ฌles โ€“ Copy/paste images from/to clipboard โ€“ Share ๏ฌles to other apps โ€“ Register for ๏ฌle extensions Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Demo Use Case
  6. Setup complete? (Node.js, Google Chrome, Editor, Git) Implementing desktop-class productivity

    apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Setup (1/3) LAB #0
  7. git clone https://github.com/thinktecture/ng-de- 2022-fugu.git cd ng-de-2022-pwa npm i git pull

    npm start -- --open Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Setup (3/3) LAB #0
  8. Paint PWA Capabilities Progressive Enhancement Implementing desktop-class productivity apps with

    Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Agenda
  9. Paint PWA Capabilities Progressive Enhancement Implementing desktop-class productivity apps with

    Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก 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+ Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint
  11. Canvas Add a canvas element to app.component.html: <canvas #canvas width="600"

    height="480"></canvas> Query the canvas element in app.component.ts: @ViewChild('canvas') canvas?: ElementRef<HTMLCanvasElement>; Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint LAB #1
  12. Canvas 2D Context fillRect(x, y, width, height) strokeRect(x, y, width,

    height) beginPath() moveTo(x, y) lineTo(x, y) fill() stroke() Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint
  13. Canvas 2D Context 1. Introduce a new ๏ฌeld at the

    top of app.component.ts: context?: CanvasRenderingContext2D; 2. Get the 2D context in ngAfterViewInit(): const canvas = this.canvas!.nativeElement; const ctx = canvas.getContext('2d')!; this.context = ctx; 3. Prepare the canvas: ctx.fillStyle = 'white'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = 'black'; Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint LAB #2
  14. Low-latency Rendering Implementing desktop-class productivity apps with Angular and Project

    Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint Web pages need to synchronize with the DOM on graphics updates causing latencies that can make drawing dif๏ฌcult Low-latency rendering skips syncing with the DOM with can lead to a more natural experience Supported on Chrome (Chrome OS and Windows only)
  15. Low-latency Rendering Opt-in to low-latency rendering (app.js): const ctx =

    canvas.getContext('2d', { desynchronized: true })!; Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint LAB #3
  16. Pointer Events Implementing desktop-class productivity apps with Angular and Project

    Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint 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
  17. Pointer Events 1. In app.component.html, add event bindings for the

    pointer events: <canvas #canvas width="600" height="480" (pointerdown)="onPointerDown($event)" (pointermove)="onPointerMove($event)" (pointerup)="onPointerUp()" ></canvas> 2. In app.component.ts (onPointerMove()), draw the user input: this.context!.fillRect(event.offsetX, event.offsetY, 2, 2); Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint LAB #4
  18. Bresenham Line Algorithm The user may move faster than the

    input can be processed For this case, we need to remember the previous point and interpolate the points in between The Bresenham line algorithm calculates the missing pixels between two given points Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint
  19. Bresenham Line Algorithm 1. At the top of app.component.ts, a

    ๏ฌeld called previousPoint to store the previous point: previousPoint?: { x: number, y: number }; 2. In onPointerDown(), set the current point as the previous point: this.previousPoint = { x: event.offsetX, y: event.offsetY }; 3. In onPointerUp(), set this.previousPoint to undefined. Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint LAB #5
  20. Bresenham Line Algorithm 4. In onPointerMove(), call the Bresenham line

    algorithm with the points: if (this.previousPoint) { const currentPoint = { x: event.offsetX, y: event.offsetY }; for (const point of this.paintService.bresenhamLine(this.previousPoint, currentPoint)) { this.context!.fillRect(point.x, point.y, 2, 2); } this.previousPoint = currentPoint; } Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint LAB #5
  21. Color Selection For this demo, we will only implement the

    brush tool. However, we want to bring in some color. A simple method to implement a color selection is to use the HTML color-type input element that shows the native color picker: <input type="color"> Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint
  22. Color Selection 1. In app.component.html, replace the content of the

    <nav> node with: <input type="color" #color (change)="onColorChange(color)"> 2. In app.component.ts (onColorChange()), update the contextโ€™s ๏ฌll style accordingly: this.context!.fillStyle = color.value; Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Paint LAB #6
  23. Paint PWA Capabilities Progressive Enhancement Implementing desktop-class productivity apps with

    Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Agenda
  24. with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Implementing desktop-class productivity apps

    Responsive Linkable Discoverable Installable App-like Connectivity Independent Fresh Safe Re-engageable Progressive
  25. Web App Manifest Distinguishes Web Apps from Websites JSON-based ๏ฌle

    containing metadata for apps only Apps can be identi๏ฌed by search engines, app store providers, etc. Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA
  26. manifest.webmanifest { "short_name": "Paint", "name": "Paint Workshop", "theme_color": "white", "icons":

    [{ "src": "icon.png", "sizes": "512x512" }], "start_url": "/index.html", "display": "standalone", "shortcuts": [/* โ€ฆ */] } Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA Names Icons Display Mode Shortcuts Start URL Theme color (status bar/window bar)
  27. Manifest Display Modes Implementing desktop-class productivity apps with Angular and

    Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA browser minimal-ui standalone fullscreen
  28. Manifest Icon Purposes (any) any context (e.g. app icon) monochrome

    different color requirements (at risk) maskable user agent masks icon as required Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA Safe Zone Windows iOS Android
  29. Web App Manifest 1. Run the following command to add

    PWA support to the current project: ng add @angular/pwa 2. In manifest.webmanifest, a) set name and short_name to values of your choice b) change the theme_color to #000080 c) change the background_color to #808080 3. In index.html, change the theme-color to #000080. 4. Test manifest in DevTools: F12 > Application > Manifest Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA LAB #7
  30. Manifest Shortcuts Implementing desktop-class productivity apps with Angular and Project

    Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA Secondary entrypoints for your application (e.g., home screen quick actions, jump lists, โ€ฆ) Static de๏ฌnition in Web App Manifest Dynamic API may follow in the future Supported by Google Chrome for Android, macOS and Windows
  31. Web App Manifest 1. In manifest.webmanifest, add (at least) the

    following shortcut: "shortcuts": [{ "name": "About Paint", "short_name": "About", "description": "Show information about Paint", "url": "./", "icons": [{ "src": "assets/icons/icon-512x512.png", "sizes": "512x512" }] }] 2. Test in DevTools: F12 > Application > Manifest Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA LAB #8
  32. Web App Manifest โ€“ Chrome Install Criteria 1. Web App

    is not already installed 2. Meets a user engagement heuristic (user has interacted and clicked with origin for at least 30 seconds) 3. Includes a Web App Manifest that has short_name or name, at least a 192px and 512px icon, a start_url and a display mode of fullscreen, standalone or minimal-ui 4. Served over HTTPS 5. Has a registered service worker with a fetch event handler Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA https://web.dev/install-criteria/
  33. Service Worker JavaScript executed in an own thread, registered by

    the website Acts as a controller, proxy, or interceptor Has a cache to store responses (for of๏ฌ‚ine availability and performance) Can wake up even when the website is closed and perform background tasks (e.g., push noti๏ฌcations or sync) Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA
  34. Service Worker Implementing desktop-class productivity apps with Angular and Project

    Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA Service Worker Internet Website HTML/JS Cache fetch
  35. NgServiceWorker Angular CLI supports Service Worker generation by simply adding

    PWA support: ng add @angular/pwa One-size-๏ฌts-all Service Worker Pre-de๏ฌned functionality, limited customizability PWA with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Implementing desktop-class productivity apps
  36. Workbox Toolchain by Google Includes a CLI Generates a service

    worker implementation from directory contents (e.g., build output, or our development directory) Allows you to modify the service worker behavior (maximum ๏ฌ‚exibility) Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA
  37. Service Worker 1. In your console, run: npm run pwa

    2. Test in DevTools: F12 > Application > Service Worker 3. Install the app: Address Bar > Install Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA LAB #9
  38. Service Worker Debugging More information on installed service workers can

    be found on โ€ข about://serviceworker- internals (Chromium-based browsers) โ€ข about:serviceworkers (Mozilla Firefox) Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA
  39. Lighthouse Implementing desktop-class productivity apps with Angular and Project Fugu

    ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA Auditing tool by Google, integrated in Chrome DevTools Automatically checks performance metrics, PWA support, accessibility, SEO and other best practices and gives tips on how to improve Can simulate mobile devices
  40. Lighthouse 1. Make sure only one tab/window of your PWA

    is open 2. Open DevTools: F12 > Lighthouse 3. Make sure to select at least the โ€œProgressive Web Appโ€ category 4. Click โ€œAnalyze page loadโ€ Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก PWA LAB #10
  41. Paint PWA Capabilities Progressive Enhancement Implementing desktop-class productivity apps with

    Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Agenda
  42. Project Fugu Implementing desktop-class productivity apps with Angular and Project

    Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities ยปLetโ€™s bring the web back โ€“ API by APIยซ Thomas Steiner, Google
  43. Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก

    Capabilities Contacts Picker Screen Wake Lock API File System Access API Shape Detection API
  44. Fugu Process โ€“ Write an Explainer (https://github.com/WICG/native-๏ฌle- system/blob/master/EXPLAINER.md) โ€“ Discuss

    capability with developers, browser vendors, standard orgs โ€“ Iterate โ€“ Compile a design document โ€“ W3C TAG Review (https://github.com/w3ctag/design- reviews/issues/390) โ€“ Formal spec within Web Incubator Community Group (WICG, https://wicg.github.io/native-๏ฌle-system/) Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities
  45. Fugu Process โ€“ Implementation in Chromium โ€“ Launches behind a

    ๏ฌ‚ag (chrome://๏ฌ‚ags/#enable-experimental-web- platform-features) โ€“ Origin Trial (https://developers.chrome.com/origintrials/) โ€“ Transfer to W3C Working Group + Recommendation? Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities
  46. Browser Implementing desktop-class productivity apps with Angular and Project Fugu

    ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities navigator.share({ url: 'http://example.com' }); ShareIntent DataTransferManager โ€ฆ NSSharingServicePicker
  47. File System Access API Some applications heavily rely on working

    with ๏ฌles (e.g. Visual Studio Code, Adobe Photoshop, โ€ฆ) File System Access API allows you to open, save and override ๏ฌles and directories Supported by Chrome, Edge Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities
  48. File System Access API 1. Add the following buttons to

    the <nav> bar in app.component.html (before the color input): <button (click)="open()">Open</button> <button (click)="save()">Save</button> <button (click)="copy()">Copy</button> <button (click)="paste()">Paste</button> <button (click)="share()">Share</button> Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities LAB #11
  49. File System Access API 2. Add the following lines at

    the top of app.component.ts: readonly fileOptions = { types: [{ description: 'PNG files', accept: {'image/png': ['.png']} }] }; Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities LAB #11
  50. File System Access API 3. Add the following lines to

    the save() function: const blob = await this.paintService.toBlob(this.canvas!.nativeElement); const handle = await window.showSaveFilePicker(this.fileOptions); const writable = await handle.createWritable(); await writable.write(blob); await writable.close(); Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities LAB #11
  51. File System Access API Add the following code to the

    open() function: const [handle] = await window.showOpenFilePicker(this.fileOptions); const file = await handle.getFile(); const image = await this.paintService.getImage(file); this.context!.drawImage(image, 0, 0); Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities LAB #12
  52. 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 ๏ฌrst (privacy!) Supported by Chrome, Edge and Safari and Firefox (plain- text only) Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities
  53. Async Clipboard API Add the following code to the copy()

    function: await navigator.clipboard.write([ new ClipboardItem({ "image/png": this.paintService.toBlob(this.canvas!.nativeElement) }), ]); Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities LAB #13
  54. Async Clipboard API 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 this.paintService.getImage(blob); this.context!.drawImage(image, 0, 0); } } } Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities LAB #14
  55. Web Share API Allows sharing a title, URL, text, or

    ๏ฌles API can only be invoked as a result of a user action (i.e. a click or keypress) Supported by Chrome, Edge, Safari and Firefox (Android only) Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities
  56. Web Share API const blob = await this.paintService.toBlob(this.canvas!.nativeElement); const file

    = new File([blob], 'untitled.png', {type: 'image/png'}); const item = { files: [file], text: 'Awesome drawing' }; if (navigator.canShare(item)) { await navigator.share(item); } Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities LAB #15
  57. File Handling API Register your PWA as a handler for

    ๏ฌle extensions Requires installing the application ๏ฌrst Declare supported extensions in Web App Manifest and add imperative code to your application logic Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities
  58. File Handling API 1. Add the following property to your

    manifest (manifest.webmanifest): "file_handlers": [{ "action": "/index.html", "accept": { "image/png": [".png"] } }] Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities LAB #16
  59. File Handling API 2. Add the following code to ngAfterViewInit()

    in app.component.ts: if ('launchQueue' in window) { window.launchQueue.setConsumer(async params => { const [handle] = params.files; if (handle) { const file = await handle.getFile(); const image = await this.paintService.getImage(file); ctx.drawImage(image, 0, 0); } }); } Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities LAB #16
  60. File Handling API 3. Rebuild PWA: npm run pwa Note:

    Wait for a few seconds and reload the application after opening, as the PWA needs to fetch the new ๏ฌles ๏ฌrst. Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities LAB #16
  61. Summary - Project Fugu helps the web to become more

    and more capable - Project Fugu APIs could bring many more app experiences to the web (IDEs, productivity apps, etc.) - But: Web is threatened by alternative approaches and platforms, support for modern Web API varies from platform to platform - You can make a difference! - File bugs in browser engine bugtrackers - File Fugu requests: https://goo.gle/new-fugu-request Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Capabilities
  62. Paint PWA Capabilities Progressive Enhancement Implementing desktop-class productivity apps with

    Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Agenda
  63. Overview Use available interfaces and functions of a system (opposite

    of Graceful Degradation) Users with modern, feature-rich browsers get a better experience Apps are available on older browsers, but with limited functionality Concept: Browser feature support should grow over timeโ€”thereby more users can enjoy an increasing number of features Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Progressive Enhancement
  64. Overview if ('serviceWorker' in navigator) { navigator.serviceWorker.register(โ€ฆ) .then(() => /*

    โ€ฆ */); } In JavaScript: check whether an API/feature is available. If yesโ€”use it! Otherwise: 1. Disable the functionality 2. Fall back to an alternative API (if available) Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Progressive Enhancement
  65. Disabling unsupported features In app.component.ts, introduce the following check object:

    readonly supported = { open: 'showOpenFilePicker' in window, } as const; In app.component.html, disable the open button if the API is unsupported: <button (click)="open()" [disabled]="!supported.open"> Open</button> Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Progressive Enhancement LAB #17
  66. Disabling unsupported features Introduce checks for the remaining APIs: 1.

    Save: 'showSaveFilePicker' in window 2. Copy: navigator.clipboard && 'write' in navigator.clipboard 3. Paste: navigator.clipboard && 'read' in navigator.clipboard 4. Share: 'canShare' in navigator Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Progressive Enhancement LAB #17
  67. Providing an alternative implementation 1. In the save() method of

    app.component.ts, test for the existence of the showSaveFilePicker() method on the window object. 2. If the method does not exist, fall back to the following code for save: const anchor = document.createElement('a'); const url = URL.createObjectURL(blob); anchor.href = url; anchor.download = ''; anchor.click(); URL.revokeObjectURL(url); 3. Remove the compatibility check to always enable the button. Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Progressive Enhancement LAB #18
  68. Deployment Implementing desktop-class productivity apps with Angular and Project Fugu

    ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Electron/Capacitor JS HTML CSS .ipa .exe .app ELF .apk .appx Single-Page Application Capacitor Electron
  69. (Simpli๏ฌed) Implementing desktop-class productivity apps with Angular and Project Fugu

    ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Store Deployments https://example.com .appx .apk Server Microsoft Store Play Store Source Files
  70. Run app on your device npm run pwa https://ngrok.com/download ngrok

    http 3000 Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก LAB #19
  71. New powerful APIs regularly ship with new releases of Chromium-based

    browsers Some only add minor ๏ฌnishing touches, others enable whole application categories as productivity apps to ๏ฌnally make the shift to the web Some APIs already made their way into other browsers (e.g., Web Share) Fugu process makes sure that capabilities are implemented in a secure, privacy-preserving manner Letโ€™s make the web a more capable platform! Implementing desktop-class productivity apps with Angular and Project Fugu ๐Ÿ…ฐ๐Ÿ’˜๐Ÿก Summary