feat: 添加 PWA 安装提示功能,更新 Navbar 以支持安装应用选项,增加多语言支持
This commit is contained in:
1 parent
df4833aea8
commit
0068d85729
5 files changed
+93
-3
No files matched your search
@@ -29,6 +29,7 @@ import { useAuth } from "../providers/AuthProvider";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import LanguageSelector from "./LanguageSelector";
|
||||
import { canInstallPWA, promptPWAInstall } from "@/utils/pwaInstallHandler";
|
||||
|
||||
const Navbar = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -120,6 +121,14 @@ const Navbar = () => {
|
||||
</Text>
|
||||
</Flex>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={promptPWAInstall}>
|
||||
<Flex gap="2" align="center">
|
||||
<DownloadIcon width="14" height="14" />
|
||||
<Text className="pl-2" size="2">
|
||||
{t("navbar.installApp")}
|
||||
</Text>
|
||||
</Flex>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</Box>
|
||||
@@ -219,6 +228,15 @@ const Navbar = () => {
|
||||
</Text>
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
<Button onClick={promptPWAInstall} variant="ghost">
|
||||
<Flex gap="2" align="center">
|
||||
<DownloadIcon width="14" height="14" />
|
||||
<Text className="pl-2" size="2">
|
||||
{t("navbar.installApp")}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
<Separator orientation="vertical" className="!h-6 hidden lg:block" />
|
||||
|
||||
@@ -6,6 +6,7 @@ const enUS = {
|
||||
"navbar.agentMonitors": "Agent Monitors",
|
||||
"navbar.statusPage": "Status Page",
|
||||
"navbar.notifications": "Notifications",
|
||||
"navbar.installApp": "Install App",
|
||||
"navbar.userManagement": "User Management",
|
||||
"navbar.profile": "Profile",
|
||||
"navbar.logout": "Logout",
|
||||
|
||||
@@ -6,6 +6,7 @@ const zhCN = {
|
||||
"navbar.agentMonitors": "客户端监控",
|
||||
"navbar.statusPage": "状态页",
|
||||
"navbar.notifications": "通知",
|
||||
"navbar.installApp": "安装应用",
|
||||
"navbar.userManagement": "用户管理",
|
||||
"navbar.profile": "个人资料",
|
||||
"navbar.logout": "退出登录",
|
||||
|
||||
@@ -34,9 +34,11 @@ const Home = () => {
|
||||
|
||||
<Flex gap="4" mt="4">
|
||||
{isAuthenticated ? (
|
||||
<Button asChild>
|
||||
<Link to="/dashboard">{t("home.getStarted")}</Link>
|
||||
</Button>
|
||||
<>
|
||||
<Button asChild>
|
||||
<Link to="/dashboard">{t("home.getStarted")}</Link>
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Button asChild>
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
let deferredPrompt: any; // 用于存储 beforeinstallprompt 事件
|
||||
|
||||
/**
|
||||
* 监听 'beforeinstallprompt' 事件。
|
||||
* 当浏览器准备好提示用户安装 PWA 时,此事件会触发。
|
||||
*/
|
||||
window.addEventListener('beforeinstallprompt', (e) => {
|
||||
// 阻止浏览器默认的迷你信息栏提示 (在某些移动浏览器上)
|
||||
e.preventDefault();
|
||||
// 保存事件,以便稍后可以触发它
|
||||
deferredPrompt = e;
|
||||
// 派发一个自定义事件,通知应用 PWA 可以安装了
|
||||
// 这允许 UI 组件(如 Navbar)更新其状态
|
||||
window.dispatchEvent(new CustomEvent('pwaInstallReady', { detail: { canInstall: true } }));
|
||||
console.log('`beforeinstallprompt` 事件已触发。PWA 可以安装。');
|
||||
});
|
||||
|
||||
/**
|
||||
* 检查 PWA 是否可以被安装。
|
||||
* @returns {boolean} 如果可以安装则返回 true,否则返回 false。
|
||||
*/
|
||||
export const canInstallPWA = (): boolean => {
|
||||
return !!deferredPrompt;
|
||||
};
|
||||
|
||||
/**
|
||||
* 触发 PWA 安装提示。
|
||||
* @returns {Promise<boolean>} 如果用户接受了安装提示,则解析为 true,否则为 false。
|
||||
*/
|
||||
export const promptPWAInstall = async (): Promise<boolean> => {
|
||||
if (!deferredPrompt) {
|
||||
console.warn('PWA 安装提示不可用或已被使用。');
|
||||
return false;
|
||||
}
|
||||
// 显示安装提示
|
||||
deferredPrompt.prompt();
|
||||
// 等待用户对提示做出响应
|
||||
try {
|
||||
const { outcome } = await deferredPrompt.userChoice;
|
||||
if (outcome === 'accepted') {
|
||||
console.log('用户接受了 PWA 安装提示');
|
||||
} else {
|
||||
console.log('用户拒绝了 PWA 安装提示');
|
||||
}
|
||||
// 清除 deferredPrompt,因为它只能使用一次
|
||||
deferredPrompt = null;
|
||||
// 派发自定义事件,通知 PWA 安装状态已更改
|
||||
window.dispatchEvent(new CustomEvent('pwaInstallReady', { detail: { canInstall: false } }));
|
||||
return outcome === 'accepted';
|
||||
} catch (error) {
|
||||
console.error('PWA 安装提示时发生错误:', error);
|
||||
deferredPrompt = null;
|
||||
window.dispatchEvent(new CustomEvent('pwaInstallReady', { detail: { canInstall: false } }));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 监听 'appinstalled' 事件。
|
||||
* 当 PWA 成功安装后,此事件会触发。
|
||||
*/
|
||||
window.addEventListener('appinstalled', () => {
|
||||
console.log('PWA 已成功安装!');
|
||||
// PWA 安装后,deferredPrompt 通常应为 null,
|
||||
// 因为 beforeinstallprompt 不会再次触发,直到应用被卸载(在某些情况下)
|
||||
deferredPrompt = null;
|
||||
window.dispatchEvent(new CustomEvent('pwaInstallReady', { detail: { canInstall: false } }));
|
||||
});
|
||||
Reference in new issue
Block a user