Files
frontend/src/navigation/hrefs.ts
lan d8d2b03f94
Some checks failed
Frontend CI / ota-android (push) Successful in 1m19s
Frontend CI / ota-ios (push) Successful in 1m50s
Frontend CI / build-and-push-web (push) Successful in 3m28s
Frontend CI / build-android-apk (push) Failing after 8m56s
feat(message): implement message search functionality
Add ability to search messages within a specific conversation. This includes:
- New `MessageSearchScreen` for displaying search results.
- `MessageRepository.searchByConversation` to query messages by keyword and conversation ID.
- Integration of search entry points in `GroupInfoScreen` and `PrivateChatInfoScreen`.
- Support for scrolling to a specific message sequence (`scrollToSeq`) when navigating from search results.
- Enhanced `HighlightText` component to support custom highlight styles.

feat(message): implement message search functionality
2026-05-14 02:26:32 +08:00

242 lines
6.4 KiB
TypeScript

/**
* Expo Router 路径构建(单一事实来源,避免魔法字符串散落)
*/
import type { SystemMessageResponse } from '../types/dto';
import { routePayloadCache } from '../stores';
export function hrefPostDetail(postId: string, scrollToComments?: boolean): string {
const q = scrollToComments ? '?scrollToComments=1' : '';
return `/post/${encodeURIComponent(postId)}${q}`;
}
export function hrefUserProfile(userId: string): string {
return `/user/${encodeURIComponent(userId)}`;
}
export function hrefHome(): string {
return '/home';
}
export function hrefHomeSearch(): string {
return '/home/search';
}
export function hrefMessages(): string {
return '/messages';
}
export function hrefNotifications(): string {
return '/messages/notifications';
}
export function hrefApps(): string {
return '/apps';
}
export function hrefSchedule(): string {
return '/apps/schedule';
}
export function hrefScheduleCourse(courseId: string): string {
return `/apps/schedule/course?courseId=${encodeURIComponent(courseId)}`;
}
export function hrefProfileSettings(): string {
return '/profile/settings';
}
export function hrefProfileEdit(): string {
return '/profile/edit-profile';
}
export function hrefProfileSecurity(): string {
return '/profile/account-security';
}
export function hrefProfileNotifications(): string {
return '/profile/notification-settings';
}
export function hrefProfileBlocked(): string {
return '/profile/blocked-users';
}
export function hrefProfileChatSettings(): string {
return '/profile/chat-settings';
}
export function hrefProfileMyPosts(): string {
return '/profile/my-posts';
}
export function hrefProfileBookmarks(): string {
return '/profile/bookmarks';
}
export function hrefCreatePost(mode?: 'create' | 'edit', postId?: string): string {
if (mode === 'edit' && postId) {
return `/posts/create?mode=edit&postId=${encodeURIComponent(postId)}`;
}
return '/posts/create';
}
export function hrefChat(params: {
conversationId: string;
userId?: string;
isGroupChat?: boolean;
groupId?: string;
groupName?: string;
groupAvatar?: string;
scrollToSeq?: number;
}): string {
const { conversationId, userId, isGroupChat, groupId, groupName, groupAvatar, scrollToSeq } = params;
const q = new URLSearchParams();
if (userId) q.set('userId', userId);
if (isGroupChat) q.set('isGroupChat', '1');
if (groupId != null && groupId !== '') q.set('groupId', String(groupId));
if (groupName) q.set('groupName', groupName);
if (groupAvatar) q.set('groupAvatar', groupAvatar);
if (scrollToSeq != null) q.set('scrollToSeq', String(scrollToSeq));
const qs = q.toString();
return `/chat/${encodeURIComponent(conversationId)}${qs ? `?${qs}` : ''}`;
}
export function hrefFollowList(userId: string, type: 'following' | 'followers'): string {
return `/users/${encodeURIComponent(userId)}/${type}`;
}
export function hrefGroupCreate(): string {
return '/group/create';
}
export function hrefGroupJoin(): string {
return '/group/join';
}
export function hrefGroupInfo(groupId: string, conversationId?: string): string {
const base = `/group/${encodeURIComponent(groupId)}`;
if (!conversationId) return base;
return `${base}?conversationId=${encodeURIComponent(conversationId)}`;
}
export function hrefGroupMembers(groupId: string): string {
return `/group/${encodeURIComponent(groupId)}/members`;
}
export function hrefGroupRequestDetail(message: SystemMessageResponse): string {
routePayloadCache.stashSystemMessage(message);
return `/group/request?messageId=${encodeURIComponent(message.id)}`;
}
export function hrefGroupInviteDetail(message: SystemMessageResponse): string {
routePayloadCache.stashSystemMessage(message);
return `/group/invite?messageId=${encodeURIComponent(message.id)}`;
}
export function hrefMessageSearch(params: {
conversationId: string;
conversationName?: string;
isGroupChat?: boolean;
}): string {
const q = new URLSearchParams({
conversationId: params.conversationId,
});
if (params.conversationName) q.set('conversationName', params.conversationName);
if (params.isGroupChat) q.set('isGroupChat', '1');
return `/chat/message-search?${q.toString()}`;
}
export function hrefPrivateChatInfo(params: {
conversationId: string;
userId: string;
userName?: string;
userAvatar?: string | null;
}): string {
const q = new URLSearchParams({
conversationId: params.conversationId,
userId: params.userId,
});
if (params.userName) q.set('userName', params.userName);
if (params.userAvatar != null) q.set('userAvatar', params.userAvatar ?? '');
return `/chat/private-info?${q.toString()}`;
}
export function hrefQrLoginConfirm(sessionId: string): string {
return `/qrcode/login/${encodeURIComponent(sessionId)}`;
}
export function hrefAuthLogin(): string {
return '/login';
}
export function hrefAuthRegister(): string {
return '/register';
}
export function hrefAuthForgot(): string {
return '/forgot-password';
}
export function hrefAuthWelcome(): string {
return '/welcome';
}
// ==================== Materials (学习资料) ====================
export function hrefMaterials(): string {
return '/apps/materials';
}
export function hrefMaterialSubject(subjectId: string): string {
return `/apps/materials/subject?subjectId=${encodeURIComponent(subjectId)}`;
}
export function hrefMaterialDetail(materialId: string): string {
return `/apps/materials/detail?materialId=${encodeURIComponent(materialId)}`;
}
// ==================== Profile Settings (设置相关) ====================
export function hrefProfileAbout(): string {
return '/profile/about';
}
export function hrefProfileTerms(): string {
return '/terms';
}
export function hrefProfilePrivacy(): string {
return '/privacy';
}
export function hrefProfileVerification(): string {
return '/profile/verification';
}
export function hrefVerificationGuide(): string {
return '/verification-guide';
}
export function hrefVerificationForm(identity?: string): string {
if (identity) {
return `/verification-form?identity=${encodeURIComponent(identity)}`;
}
return '/verification-form';
}
export function hrefProfileDataStorage(): string {
return '/profile/data-storage';
}
export function hrefProfilePrivacySettings(): string {
return '/profile/privacy-settings';
}
export function hrefProfileDeletion(): string {
return '/profile/account-deletion';
}
export function hrefEditTrade(tradeId: string): string {
return `/trade/edit/${encodeURIComponent(tradeId)}`;
}