feat(chat): prompt facebook users to open external browser
This commit is contained in:
@@ -17,16 +17,19 @@
|
||||
* - `ChatLogout` → 登出(机器自动 cleanup WS actor)
|
||||
* - chat 机器内部用 fromCallback actor 完整管理 WS 生命周期
|
||||
*/
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import { useAuthState } from "@/stores/auth/auth-context";
|
||||
import type { LoginStatus } from "@/data/dto/auth";
|
||||
import { AuthStorage } from "@/data/storage/auth/auth_storage";
|
||||
import { UserStorage } from "@/data/storage/user/user_storage";
|
||||
import { useChatDispatch, useChatState } from "@/stores/chat/chat-context";
|
||||
import { AppEnvUtil } from "@/utils/app-env";
|
||||
import { ROUTES } from "@/router/routes";
|
||||
import { BrowserDetector } from "@/utils/browser-detect";
|
||||
import { UrlLauncherUtil } from "@/utils/url-launcher-util";
|
||||
import { ROUTE_BUILDERS, ROUTES } from "@/router/routes";
|
||||
|
||||
import { MobileShell } from "@/app/_components/core";
|
||||
|
||||
@@ -36,6 +39,7 @@ import {
|
||||
ChatHeader,
|
||||
ChatInputBar,
|
||||
ChatQuotaExhaustedBanner,
|
||||
ExternalBrowserDialog,
|
||||
PwaInstallOverlay,
|
||||
} from "./components";
|
||||
import styles from "./components/chat-screen.module.css";
|
||||
@@ -81,6 +85,8 @@ export function ChatScreen() {
|
||||
const state = useChatState();
|
||||
const authState = useAuthState();
|
||||
const chatDispatch = useChatDispatch();
|
||||
const [showExternalBrowserDialog, setShowExternalBrowserDialog] =
|
||||
useState(false);
|
||||
|
||||
// isGuest 派生(chat-screen 是唯一知道这个值的地方 —— chat 机器无 isGuest 字段)
|
||||
const isGuest = deriveIsGuest(authState.loginStatus);
|
||||
@@ -103,6 +109,7 @@ export function ChatScreen() {
|
||||
// - 登录态变化(guest→email 等)→ 派 ChatGuestLogin 或 ChatNonGuestLogin
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
const prevLoginStatusRef = useRef<LoginStatus | null>(null);
|
||||
const externalBrowserPromptShownRef = useRef(false);
|
||||
useEffect(() => {
|
||||
if (!authState.hasInitialized || authState.isLoading) return;
|
||||
|
||||
@@ -125,6 +132,55 @@ export function ChatScreen() {
|
||||
router,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!authState.hasInitialized || authState.isLoading) return;
|
||||
if (authState.loginStatus !== "facebook") return;
|
||||
if (externalBrowserPromptShownRef.current) return;
|
||||
if (!BrowserDetector.isInAppBrowser()) return;
|
||||
|
||||
externalBrowserPromptShownRef.current = true;
|
||||
const timer = window.setTimeout(() => {
|
||||
setShowExternalBrowserDialog(true);
|
||||
}, 3000);
|
||||
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [
|
||||
authState.hasInitialized,
|
||||
authState.isLoading,
|
||||
authState.loginStatus,
|
||||
]);
|
||||
|
||||
async function handleOpenExternalBrowser(): Promise<void> {
|
||||
setShowExternalBrowserDialog(false);
|
||||
|
||||
const authStorage = AuthStorage.getInstance();
|
||||
const userStorage = UserStorage.getInstance();
|
||||
const [deviceIdR, facebookIdR, avatarUrlR] = await Promise.all([
|
||||
authStorage.getDeviceId(),
|
||||
authStorage.getFacebookId(),
|
||||
userStorage.getAvatarUrl(),
|
||||
]);
|
||||
|
||||
const deviceId = deviceIdR.success ? deviceIdR.data : null;
|
||||
const facebookId = facebookIdR.success ? facebookIdR.data : null;
|
||||
const avatarUrl = avatarUrlR.success ? avatarUrlR.data : null;
|
||||
|
||||
if (deviceId && facebookId) {
|
||||
UrlLauncherUtil.openUrlWithExternalBrowser(
|
||||
ROUTE_BUILDERS.chatDeviceId(deviceId),
|
||||
{
|
||||
queryParams: {
|
||||
fbid: facebookId,
|
||||
...(avatarUrl ? { avatarUrl } : {}),
|
||||
},
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
UrlLauncherUtil.openUrlWithExternalBrowser(ROUTES.chat);
|
||||
}
|
||||
|
||||
return (
|
||||
<MobileShell>
|
||||
<div className={styles.shell}>
|
||||
@@ -162,6 +218,12 @@ export function ChatScreen() {
|
||||
|
||||
{/* PWA 安装提示触发器(无可见 UI,3.5s 后弹 dialog) */}
|
||||
<PwaInstallOverlay />
|
||||
|
||||
<ExternalBrowserDialog
|
||||
open={showExternalBrowserDialog}
|
||||
onClose={() => setShowExternalBrowserDialog(false)}
|
||||
onConfirm={() => void handleOpenExternalBrowser()}
|
||||
/>
|
||||
</div>
|
||||
</MobileShell>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user