This commit is contained in:
retoor 2025-12-04 20:33:22 +01:00
parent ae789a5b40
commit 8e6feefdaf
3 changed files with 63 additions and 1 deletions

View File

@ -13,7 +13,7 @@ DevRant client built with vanilla JavaScript, Web Components, and CSS.
python3 proxy.py python3 proxy.py
``` ```
Open `http://localhost:8000` Open `http://localhost:8101`
## Features ## Features

View File

@ -58,6 +58,33 @@ class Application {
this.main = null; this.main = null;
this.currentPage = null; this.currentPage = null;
this.isNavOpen = false; 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() { async init() {

View File

@ -9,6 +9,7 @@ import { BaseComponent } from '../components/base-component.js';
class SettingsPage extends BaseComponent { class SettingsPage extends BaseComponent {
init() { init() {
this.installHandler = () => this.render();
this.render(); this.render();
this.bindEvents(); this.bindEvents();
} }
@ -16,6 +17,7 @@ class SettingsPage extends BaseComponent {
render() { render() {
const isLoggedIn = this.isLoggedIn(); const isLoggedIn = this.isLoggedIn();
const user = this.getCurrentUser(); const user = this.getCurrentUser();
const canInstall = this.getApp()?.canInstall();
this.addClass('page', 'settings-page'); this.addClass('page', 'settings-page');
@ -29,6 +31,18 @@ class SettingsPage extends BaseComponent {
<h1>Settings</h1> <h1>Settings</h1>
</header> </header>
<div class="settings-content"> <div class="settings-content">
${canInstall ? `
<section class="settings-section">
<h2>Install App</h2>
<p>Install Rantii for quick access</p>
<button class="btn btn-primary install-btn">
<svg viewBox="0 0 24 24" width="20" height="20" style="margin-right: 8px;">
<path fill="currentColor" d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
</svg>
Install Rantii
</button>
</section>
` : ''}
${isLoggedIn ? ` ${isLoggedIn ? `
<section class="settings-section"> <section class="settings-section">
<h2>Account</h2> <h2>Account</h2>
@ -67,6 +81,13 @@ class SettingsPage extends BaseComponent {
bindEvents() { bindEvents() {
this.on(this, 'click', this.handleClick); 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) { handleClick(e) {
@ -74,6 +95,7 @@ class SettingsPage extends BaseComponent {
const loginBtn = e.target.closest('.login-btn'); const loginBtn = e.target.closest('.login-btn');
const logoutBtn = e.target.closest('.logout-btn'); const logoutBtn = e.target.closest('.logout-btn');
const clearCacheBtn = e.target.closest('.clear-cache-btn'); const clearCacheBtn = e.target.closest('.clear-cache-btn');
const installBtn = e.target.closest('.install-btn');
if (backBtn) { if (backBtn) {
window.history.back(); window.history.back();
@ -92,6 +114,19 @@ class SettingsPage extends BaseComponent {
if (clearCacheBtn) { if (clearCacheBtn) {
this.clearCache(); 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();
} }
} }