diff --git a/README.md b/README.md index 7d5ccb3..5d27eef 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ DevRant client built with vanilla JavaScript, Web Components, and CSS. python3 proxy.py ``` -Open `http://localhost:8000` +Open `http://localhost:8101` ## Features diff --git a/js/app.js b/js/app.js index 00d9dd6..8c758d3 100644 --- a/js/app.js +++ b/js/app.js @@ -58,6 +58,33 @@ class Application { this.main = null; this.currentPage = null; this.isNavOpen = false; + this.deferredInstallPrompt = null; + this.setupInstallPrompt(); + } + + setupInstallPrompt() { + window.addEventListener('beforeinstallprompt', (e) => { + e.preventDefault(); + this.deferredInstallPrompt = e; + window.dispatchEvent(new CustomEvent('rantii:install-available')); + }); + + window.addEventListener('appinstalled', () => { + this.deferredInstallPrompt = null; + window.dispatchEvent(new CustomEvent('rantii:app-installed')); + }); + } + + canInstall() { + return this.deferredInstallPrompt !== null; + } + + async installApp() { + if (!this.deferredInstallPrompt) return false; + this.deferredInstallPrompt.prompt(); + const { outcome } = await this.deferredInstallPrompt.userChoice; + this.deferredInstallPrompt = null; + return outcome === 'accepted'; } async init() { diff --git a/js/pages/settings-page.js b/js/pages/settings-page.js index 305ebf7..80b4670 100644 --- a/js/pages/settings-page.js +++ b/js/pages/settings-page.js @@ -9,6 +9,7 @@ import { BaseComponent } from '../components/base-component.js'; class SettingsPage extends BaseComponent { init() { + this.installHandler = () => this.render(); this.render(); this.bindEvents(); } @@ -16,6 +17,7 @@ class SettingsPage extends BaseComponent { render() { const isLoggedIn = this.isLoggedIn(); const user = this.getCurrentUser(); + const canInstall = this.getApp()?.canInstall(); this.addClass('page', 'settings-page'); @@ -29,6 +31,18 @@ class SettingsPage extends BaseComponent {

Settings

+ ${canInstall ? ` +
+

Install App

+

Install Rantii for quick access

+ +
+ ` : ''} ${isLoggedIn ? `

Account

@@ -67,6 +81,13 @@ class SettingsPage extends BaseComponent { bindEvents() { this.on(this, 'click', this.handleClick); + window.addEventListener('rantii:install-available', this.installHandler); + window.addEventListener('rantii:app-installed', this.installHandler); + } + + onDisconnected() { + window.removeEventListener('rantii:install-available', this.installHandler); + window.removeEventListener('rantii:app-installed', this.installHandler); } handleClick(e) { @@ -74,6 +95,7 @@ class SettingsPage extends BaseComponent { const loginBtn = e.target.closest('.login-btn'); const logoutBtn = e.target.closest('.logout-btn'); const clearCacheBtn = e.target.closest('.clear-cache-btn'); + const installBtn = e.target.closest('.install-btn'); if (backBtn) { window.history.back(); @@ -92,6 +114,19 @@ class SettingsPage extends BaseComponent { if (clearCacheBtn) { this.clearCache(); + return; + } + + if (installBtn) { + this.installApp(); + } + } + + async installApp() { + const installed = await this.getApp()?.installApp(); + if (installed) { + this.getApp()?.toast?.success('App installed'); + this.render(); } }