feat(chat): trigger pwa prompt after message threshold
This commit is contained in:
@@ -67,6 +67,7 @@ export function ChatScreen() {
|
|||||||
historyLoaded: state.historyLoaded,
|
historyLoaded: state.historyLoaded,
|
||||||
loginStatus: authState.loginStatus,
|
loginStatus: authState.loginStatus,
|
||||||
});
|
});
|
||||||
|
const shouldShowPwaInstall = state.historyLoaded && state.messages.length >= 10;
|
||||||
|
|
||||||
const externalBrowserPromptShownRef = useRef(false);
|
const externalBrowserPromptShownRef = useRef(false);
|
||||||
|
|
||||||
@@ -181,8 +182,8 @@ export function ChatScreen() {
|
|||||||
{/* 浏览器提示(应用内浏览器检测) */}
|
{/* 浏览器提示(应用内浏览器检测) */}
|
||||||
<BrowserHintOverlay forceShow={isChatDevelopmentEnvironment()} />
|
<BrowserHintOverlay forceShow={isChatDevelopmentEnvironment()} />
|
||||||
|
|
||||||
{/* PWA 安装提示触发器(无可见 UI,3.5s 后弹 dialog) */}
|
{/* PWA 安装提示触发器(聊天消息数量达到阈值后才允许弹出) */}
|
||||||
<PwaInstallOverlay />
|
<PwaInstallOverlay enabled={shouldShowPwaInstall} />
|
||||||
|
|
||||||
<ExternalBrowserDialog
|
<ExternalBrowserDialog
|
||||||
open={showExternalBrowserDialog}
|
open={showExternalBrowserDialog}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* PwaInstallOverlay PWA 安装提示触发器
|
* PwaInstallOverlay PWA 安装提示触发器
|
||||||
*
|
*
|
||||||
* 行为:
|
* 行为:
|
||||||
|
* - 等聊天消息数量达到触发阈值后才开始检查
|
||||||
* - 检查 PWA 支持(pwaUtil.isSupported)
|
* - 检查 PWA 支持(pwaUtil.isSupported)
|
||||||
* - 检查 PWA 是否已安装(pwaUtil.isInstalled)—— 已安装则不弹
|
* - 检查 PWA 是否已安装(pwaUtil.isInstalled)—— 已安装则不弹
|
||||||
* - 检查每日是否已显示(使用 AppStorage 持久化)
|
* - 检查每日是否已显示(使用 AppStorage 持久化)
|
||||||
@@ -20,10 +21,19 @@ import { PwaInstallDialog } from "./pwa-install-dialog";
|
|||||||
import styles from "./pwa-install-overlay.module.css";
|
import styles from "./pwa-install-overlay.module.css";
|
||||||
|
|
||||||
const PWA_DIALOG_KEY = "cozsweet:lastPwaDialogShown";
|
const PWA_DIALOG_KEY = "cozsweet:lastPwaDialogShown";
|
||||||
|
const DEVELOPMENT_DIALOG_DELAY_MS = 1000;
|
||||||
|
const PRODUCTION_DIALOG_DELAY_MS = 1500;
|
||||||
|
|
||||||
export function PwaInstallOverlay() {
|
export interface PwaInstallOverlayProps {
|
||||||
|
enabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PwaInstallOverlay({ enabled }: PwaInstallOverlayProps) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!enabled) return;
|
||||||
|
|
||||||
let mounted = true;
|
let mounted = true;
|
||||||
|
let timer: number | undefined;
|
||||||
|
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
// const isDev = AppEnvUtil.isDevelopment();
|
// const isDev = AppEnvUtil.isDevelopment();
|
||||||
@@ -34,9 +44,11 @@ export function PwaInstallOverlay() {
|
|||||||
// 提前挂 beforeinstallprompt 监听,避免用户点 OK 时事件已在更早时机丢失。
|
// 提前挂 beforeinstallprompt 监听,避免用户点 OK 时事件已在更早时机丢失。
|
||||||
pwaUtil.prepareInstallPrompt();
|
pwaUtil.prepareInstallPrompt();
|
||||||
|
|
||||||
// 开发环境 1s 后弹(快);生产环境 3.5s 后弹(让用户先看到聊天内容)
|
// 达到聊天数量阈值后稍作停顿,避免弹窗与消息刷新挤在同一瞬间。
|
||||||
const delay = isDev ? 1000 : 3500;
|
const delay = isDev
|
||||||
setTimeout(() => {
|
? DEVELOPMENT_DIALOG_DELAY_MS
|
||||||
|
: PRODUCTION_DIALOG_DELAY_MS;
|
||||||
|
timer = window.setTimeout(() => {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
showPwaDialog();
|
showPwaDialog();
|
||||||
}, delay);
|
}, delay);
|
||||||
@@ -45,8 +57,9 @@ export function PwaInstallOverlay() {
|
|||||||
void init();
|
void init();
|
||||||
return () => {
|
return () => {
|
||||||
mounted = false;
|
mounted = false;
|
||||||
|
if (timer !== undefined) window.clearTimeout(timer);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [enabled]);
|
||||||
|
|
||||||
return <div className={styles.hidden} aria-hidden="true" />;
|
return <div className={styles.hidden} aria-hidden="true" />;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user