fix:APP-push点击文案显示home页

This commit is contained in:
吕新雨
2026-03-12 18:02:25 +08:00
parent d37262876b
commit 22443c82b6
12 changed files with 414 additions and 16 deletions

View File

@@ -0,0 +1,77 @@
import { describe, expect, it, vi } from 'vitest';
vi.mock('../../storage/appStorage', () => ({
getLastHandledNotificationId: vi.fn(async () => null),
setLastHandledNotificationId: vi.fn(async () => undefined),
setPendingHomePushMessage: vi.fn(async () => undefined),
}));
import { buildPendingHomePushMessageFromResponse } from '../pushNotificationRoute';
describe('pushNotificationRoute.buildPendingHomePushMessageFromResponse', () => {
it('能从每日推荐 push payload 提取 home 文案', () => {
const result = buildPendingHomePushMessageFromResponse({
notification: {
request: {
identifier: 'notif-1',
content: {
title: '每日推荐',
body: '先用通知正文兜底',
data: {
scene: 'push',
target_screen: 'home',
home_text: '点击推送后回到首页展示这句文案',
content_id: '42',
},
},
},
},
});
expect(result).toMatchObject({
notification_id: 'notif-1',
title: '每日推荐',
text: '点击推送后回到首页展示这句文案',
content_id: 42,
scene: 'push',
});
});
it('home_text 缺失时回退到通知正文', () => {
const result = buildPendingHomePushMessageFromResponse({
notification: {
request: {
identifier: 'notif-2',
content: {
body: '直接展示通知正文',
data: {
target_screen: 'home',
},
},
},
},
});
expect(result?.text).toBe('直接展示通知正文');
expect(result?.notification_id).toBe('notif-2');
});
it('非 home 目标且非 push 场景时忽略', () => {
const result = buildPendingHomePushMessageFromResponse({
notification: {
request: {
identifier: 'notif-3',
content: {
body: '这条不应该进入首页',
data: {
target_screen: 'profile',
scene: 'other',
},
},
},
},
});
expect(result).toBeNull();
});
});

View File

@@ -0,0 +1,100 @@
import {
getLastHandledNotificationId,
setLastHandledNotificationId,
setPendingHomePushMessage,
type PendingHomePushMessage,
} from '../storage/appStorage';
type NotificationContentLike = {
title?: string | null;
body?: string | null;
data?: Record<string, unknown> | null;
};
export type NotificationResponseLike = {
notification?: {
request?: {
identifier?: string;
content?: NotificationContentLike;
};
};
};
type HomePushListener = (message: PendingHomePushMessage) => void;
const homePushListeners = new Set<HomePushListener>();
function readString(value: unknown): string | undefined {
if (typeof value !== 'string') return undefined;
const trimmed = value.trim();
return trimmed ? trimmed : undefined;
}
function readContentId(value: unknown): number | undefined {
if (typeof value === 'number' && Number.isFinite(value)) {
return Math.trunc(value);
}
if (typeof value === 'string' && value.trim()) {
const parsed = Number(value);
if (Number.isFinite(parsed)) return Math.trunc(parsed);
}
return undefined;
}
function notifyHomePushListeners(message: PendingHomePushMessage): void {
for (const listener of homePushListeners) {
listener(message);
}
}
export function subscribeHomePushMessage(listener: HomePushListener): () => void {
homePushListeners.add(listener);
return () => {
homePushListeners.delete(listener);
};
}
export function buildPendingHomePushMessageFromResponse(
response: NotificationResponseLike
): PendingHomePushMessage | null {
const request = response.notification?.request;
const content = request?.content;
const data =
content?.data && typeof content.data === 'object' && !Array.isArray(content.data)
? content.data
: {};
const targetScreen = readString(data.target_screen);
const scene = readString(data.scene);
const shouldOpenHome = targetScreen === 'home' || scene === 'push';
if (!shouldOpenHome) return null;
const text = readString(data.home_text) ?? readString(content?.body);
if (!text) return null;
return {
notification_id: readString(request?.identifier) ?? `push-${Date.now()}`,
received_at: new Date().toISOString(),
text,
title: readString(content?.title),
content_id: readContentId(data.content_id),
scene,
};
}
export async function persistHomePushMessageFromResponse(
response: NotificationResponseLike
): Promise<PendingHomePushMessage | null> {
const message = buildPendingHomePushMessageFromResponse(response);
if (!message) return null;
const lastHandledNotificationId = await getLastHandledNotificationId();
if (lastHandledNotificationId === message.notification_id) {
return null;
}
await setPendingHomePushMessage(message);
await setLastHandledNotificationId(message.notification_id);
notifyHomePushListeners(message);
return message;
}