feat(sidebar): add conditional pwa install action

This commit is contained in:
2026-07-03 18:39:00 +08:00
parent 27cb2e2c33
commit f470119a1b
2 changed files with 90 additions and 16 deletions
@@ -123,6 +123,12 @@
text-transform: uppercase;
}
.settingsActions {
display: flex;
flex-direction: column;
gap: clamp(10px, 2.222vw, 12px);
}
.logoutCard {
display: flex;
width: 100%;
@@ -141,6 +147,11 @@
transition: background 0.18s ease, box-shadow 0.18s ease, transform 0.16s ease;
}
.installCard {
border-color: rgba(246, 87, 160, 0.14);
background: rgba(255, 255, 255, 0.9);
}
.logoutCard:hover {
background: #ffffff;
box-shadow: 0 16px 34px rgba(55, 36, 44, 0.1);
@@ -168,6 +179,11 @@
color: #ef4d64;
}
.installIcon {
background: rgba(246, 87, 160, 0.12);
color: #f657a0;
}
.logoutText {
display: flex;
min-width: 0;
@@ -182,6 +198,13 @@
line-height: 1.15;
}
.installTitle {
color: #171114;
font-size: var(--responsive-body, 16px);
font-weight: 760;
line-height: 1.15;
}
.logoutSubtitle {
color: #817076;
font-size: var(--responsive-caption, 13px);
@@ -189,6 +212,13 @@
line-height: 1.25;
}
.installSubtitle {
color: #817076;
font-size: var(--responsive-caption, 13px);
font-weight: 620;
line-height: 1.25;
}
.revealOne,
.revealTwo,
.revealThree {
+46 -2
View File
@@ -1,7 +1,7 @@
"use client";
import { useEffect } from "react";
import { LogOut } from "lucide-react";
import { useEffect, useState } from "react";
import { Download, LogOut } from "lucide-react";
import { signOut } from "next-auth/react";
import { BackButton } from "@/app/_components";
@@ -10,6 +10,7 @@ import { ROUTES } from "@/router/routes";
import { useAppNavigator } from "@/router/use-app-navigator";
import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";
import { useUserDispatch, useUserState } from "@/stores/user/user-context";
import { pwaUtil } from "@/utils";
import {
SidebarWalletCard,
@@ -27,6 +28,7 @@ export function SidebarScreen() {
const userDispatch = useUserDispatch();
const auth = useAuthState();
const authDispatch = useAuthDispatch();
const [canShowInstallApp, setCanShowInstallApp] = useState(false);
useEffect(() => {
if (!auth.hasInitialized || auth.isLoading) return;
@@ -40,6 +42,25 @@ export function SidebarScreen() {
userDispatch,
]);
useEffect(() => {
pwaUtil.prepareInstallPrompt();
const timer = window.setTimeout(() => {
setCanShowInstallApp(pwaUtil.isSupported() && !pwaUtil.isInstalled());
}, 0);
return () => {
window.clearTimeout(timer);
};
}, []);
const handleInstallAppClick = async () => {
pwaUtil.prepareInstallPrompt();
const result = await pwaUtil.install();
if (result === "accepted" || pwaUtil.isInstalled()) {
setCanShowInstallApp(false);
}
};
const handleLogoutClick = () => {
userDispatch({ type: "UserClearLocal" });
authDispatch({ type: "AuthLogoutSubmitted" });
@@ -100,6 +121,28 @@ export function SidebarScreen() {
{sidebarState !== "guest" ? (
<section className={`${styles.settingsSlot} ${styles.revealThree}`}>
<p className={styles.settingsLabel}>Other</p>
<div className={styles.settingsActions}>
{canShowInstallApp ? (
<button
type="button"
className={`${styles.logoutCard} ${styles.installCard}`}
onClick={() => void handleInstallAppClick()}
>
<span
className={`${styles.logoutIcon} ${styles.installIcon}`}
aria-hidden="true"
>
<Download size={19} strokeWidth={2.2} />
</span>
<span className={styles.logoutText}>
<span className={styles.installTitle}>Install app</span>
<span className={styles.installSubtitle}>
Add CozSweet to your Home Screen
</span>
</span>
</button>
) : null}
<button
type="button"
className={styles.logoutCard}
@@ -115,6 +158,7 @@ export function SidebarScreen() {
</span>
</span>
</button>
</div>
</section>
) : null}
</div>