refactor(App, navigation): migrate to Expo Router and clean up navigation structure
- Updated App entry point to utilize Expo Router, simplifying the navigation setup. - Removed legacy navigation components and services to streamline the codebase. - Adjusted package.json to reflect the new entry point and updated dependencies for compatibility. - Enhanced overall application structure by consolidating navigation logic and improving maintainability.
This commit is contained in:
@@ -27,6 +27,54 @@ import {
|
||||
CursorPaginationResponse,
|
||||
} from '../types/dto';
|
||||
|
||||
function asGroupId(raw: unknown): string {
|
||||
return String(raw);
|
||||
}
|
||||
|
||||
function normalizeGroup(g: GroupResponse): GroupResponse {
|
||||
return { ...g, id: asGroupId(g.id) };
|
||||
}
|
||||
|
||||
function normalizeMember(m: GroupMemberResponse): GroupMemberResponse {
|
||||
return { ...m, group_id: asGroupId(m.group_id) };
|
||||
}
|
||||
|
||||
function normalizeAnnouncement(a: GroupAnnouncementResponse): GroupAnnouncementResponse {
|
||||
return { ...a, group_id: asGroupId(a.group_id) };
|
||||
}
|
||||
|
||||
function normalizeGroupListResponse(r: GroupListResponse): GroupListResponse {
|
||||
return { ...r, list: r.list.map(normalizeGroup) };
|
||||
}
|
||||
|
||||
function normalizeMemberListResponse(r: GroupMemberListResponse): GroupMemberListResponse {
|
||||
return { ...r, list: r.list.map(normalizeMember) };
|
||||
}
|
||||
|
||||
function normalizeAnnouncementListResponse(
|
||||
r: GroupAnnouncementListResponse
|
||||
): GroupAnnouncementListResponse {
|
||||
return { ...r, list: r.list.map(normalizeAnnouncement) };
|
||||
}
|
||||
|
||||
function normalizeGroupCursor(
|
||||
r: CursorPaginationResponse<GroupResponse>
|
||||
): CursorPaginationResponse<GroupResponse> {
|
||||
return { ...r, list: r.list.map(normalizeGroup) };
|
||||
}
|
||||
|
||||
function normalizeMemberCursor(
|
||||
r: CursorPaginationResponse<GroupMemberResponse>
|
||||
): CursorPaginationResponse<GroupMemberResponse> {
|
||||
return { ...r, list: r.list.map(normalizeMember) };
|
||||
}
|
||||
|
||||
function normalizeAnnouncementCursor(
|
||||
r: CursorPaginationResponse<GroupAnnouncementResponse>
|
||||
): CursorPaginationResponse<GroupAnnouncementResponse> {
|
||||
return { ...r, list: r.list.map(normalizeAnnouncement) };
|
||||
}
|
||||
|
||||
// 群组服务类(纯 API 层)
|
||||
// SQLite/内存缓存编排由 groupManager 统一处理
|
||||
class GroupService {
|
||||
@@ -35,27 +83,27 @@ class GroupService {
|
||||
page,
|
||||
page_size: pageSize,
|
||||
});
|
||||
return response.data;
|
||||
return normalizeGroupListResponse(response.data);
|
||||
}
|
||||
|
||||
async fetchGroupFromApi(id: number | string): Promise<GroupResponse> {
|
||||
const response = await api.get<GroupResponse>(`/groups/${encodeURIComponent(String(id))}`);
|
||||
return response.data;
|
||||
async fetchGroupFromApi(id: string): Promise<GroupResponse> {
|
||||
const response = await api.get<GroupResponse>(`/groups/${encodeURIComponent(id)}`);
|
||||
return normalizeGroup(response.data);
|
||||
}
|
||||
|
||||
async fetchMembersFromApi(
|
||||
groupId: number | string,
|
||||
groupId: string,
|
||||
page = 1,
|
||||
pageSize = 50
|
||||
): Promise<GroupMemberListResponse> {
|
||||
const response = await api.get<GroupMemberListResponse>(
|
||||
`/groups/${encodeURIComponent(String(groupId))}/members`,
|
||||
`/groups/${encodeURIComponent(groupId)}/members`,
|
||||
{
|
||||
page,
|
||||
page_size: pageSize,
|
||||
}
|
||||
);
|
||||
return response.data;
|
||||
return normalizeMemberListResponse(response.data);
|
||||
}
|
||||
|
||||
// ==================== 群组管理 ====================
|
||||
@@ -66,7 +114,7 @@ class GroupService {
|
||||
*/
|
||||
async createGroup(data: CreateGroupRequest): Promise<GroupResponse> {
|
||||
const response = await api.post<GroupResponse>('/groups', data);
|
||||
return response.data;
|
||||
return normalizeGroup(response.data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +129,7 @@ class GroupService {
|
||||
* 获取群组详情
|
||||
* GET /api/v1/groups/:id
|
||||
*/
|
||||
async getGroup(id: number | string): Promise<GroupResponse> {
|
||||
async getGroup(id: string): Promise<GroupResponse> {
|
||||
return this.fetchGroupFromApi(id);
|
||||
}
|
||||
|
||||
@@ -89,27 +137,30 @@ class GroupService {
|
||||
* 获取当前用户在群组中的成员信息
|
||||
* GET /api/v1/groups/:id/me
|
||||
*/
|
||||
async getMyMemberInfo(groupId: number | string): Promise<MyMemberInfoResponse> {
|
||||
async getMyMemberInfo(groupId: string): Promise<MyMemberInfoResponse> {
|
||||
const response = await api.get<MyMemberInfoResponse>(
|
||||
`/groups/${encodeURIComponent(String(groupId))}/me`
|
||||
`/groups/${encodeURIComponent(groupId)}/me`
|
||||
);
|
||||
return response.data;
|
||||
return {
|
||||
...response.data,
|
||||
member: normalizeMember(response.data.member),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 解散群组
|
||||
* DELETE /api/v1/groups/:id
|
||||
*/
|
||||
async dissolveGroup(id: number | string): Promise<void> {
|
||||
await api.delete(`/groups/${encodeURIComponent(String(id))}`);
|
||||
async dissolveGroup(id: string): Promise<void> {
|
||||
await api.delete(`/groups/${encodeURIComponent(id)}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转让群主
|
||||
* POST /api/v1/groups/:id/transfer
|
||||
*/
|
||||
async transferOwner(id: number | string, data: TransferOwnerRequest): Promise<void> {
|
||||
await api.post(`/groups/${encodeURIComponent(String(id))}/transfer`, data);
|
||||
async transferOwner(id: string, data: TransferOwnerRequest): Promise<void> {
|
||||
await api.post(`/groups/${encodeURIComponent(id)}/transfer`, data);
|
||||
}
|
||||
|
||||
// ==================== 成员管理 ====================
|
||||
@@ -118,25 +169,25 @@ class GroupService {
|
||||
* 邀请成员加入群组
|
||||
* POST /api/v1/groups/:id/invitations
|
||||
*/
|
||||
async inviteMembers(groupId: number | string, data: InviteMembersRequest): Promise<void> {
|
||||
await api.post(`/groups/${encodeURIComponent(String(groupId))}/invitations`, data);
|
||||
async inviteMembers(groupId: string, data: InviteMembersRequest): Promise<void> {
|
||||
await api.post(`/groups/${encodeURIComponent(groupId)}/invitations`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请加入群组
|
||||
* POST /api/v1/groups/:id/join-requests
|
||||
*/
|
||||
async joinGroup(groupId: number | string): Promise<void> {
|
||||
await api.post(`/groups/${encodeURIComponent(String(groupId))}/join-requests`);
|
||||
async joinGroup(groupId: string): Promise<void> {
|
||||
await api.post(`/groups/${encodeURIComponent(groupId)}/join-requests`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应群邀请/申请
|
||||
* POST /api/v1/groups/:id/join-requests/respond
|
||||
*/
|
||||
async respondInvite(groupId: number | string, data: HandleGroupRequestAction): Promise<void> {
|
||||
async respondInvite(groupId: string, data: HandleGroupRequestAction): Promise<void> {
|
||||
await api.post(
|
||||
`/groups/${encodeURIComponent(String(groupId))}/join-requests/respond`,
|
||||
`/groups/${encodeURIComponent(groupId)}/join-requests/respond`,
|
||||
data
|
||||
);
|
||||
}
|
||||
@@ -145,9 +196,9 @@ class GroupService {
|
||||
* 审批主动加群申请
|
||||
* POST /api/v1/groups/:id/join-requests/handle
|
||||
*/
|
||||
async reviewJoinRequest(groupId: number | string, data: HandleGroupRequestAction): Promise<void> {
|
||||
async reviewJoinRequest(groupId: string, data: HandleGroupRequestAction): Promise<void> {
|
||||
await api.post(
|
||||
`/groups/${encodeURIComponent(String(groupId))}/join-requests/handle`,
|
||||
`/groups/${encodeURIComponent(groupId)}/join-requests/handle`,
|
||||
data
|
||||
);
|
||||
}
|
||||
@@ -156,15 +207,15 @@ class GroupService {
|
||||
* 退出群组
|
||||
* POST /api/v1/groups/:id/leave
|
||||
*/
|
||||
async leaveGroup(groupId: number | string): Promise<void> {
|
||||
await api.post(`/groups/${encodeURIComponent(String(groupId))}/leave`);
|
||||
async leaveGroup(groupId: string): Promise<void> {
|
||||
await api.post(`/groups/${encodeURIComponent(groupId)}/leave`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取群组成员列表
|
||||
* GET /api/v1/groups/:id/members
|
||||
*/
|
||||
async getMembers(groupId: number | string, page = 1, pageSize = 50): Promise<GroupMemberListResponse> {
|
||||
async getMembers(groupId: string, page = 1, pageSize = 50): Promise<GroupMemberListResponse> {
|
||||
return this.fetchMembersFromApi(groupId, page, pageSize);
|
||||
}
|
||||
|
||||
@@ -172,8 +223,8 @@ class GroupService {
|
||||
* 移除群成员(踢人)
|
||||
* POST /api/v1/groups/:id/members/kick
|
||||
*/
|
||||
async removeMember(groupId: number | string, userId: string): Promise<void> {
|
||||
await api.post(`/groups/${encodeURIComponent(String(groupId))}/members/kick`, {
|
||||
async removeMember(groupId: string, userId: string): Promise<void> {
|
||||
await api.post(`/groups/${encodeURIComponent(groupId)}/members/kick`, {
|
||||
user_id: userId,
|
||||
reject_add_request: false,
|
||||
});
|
||||
@@ -184,12 +235,12 @@ class GroupService {
|
||||
* PUT /api/v1/groups/:id/members/:user_id/admin
|
||||
*/
|
||||
async setMemberRole(
|
||||
groupId: number | string,
|
||||
groupId: string,
|
||||
userId: string,
|
||||
data: SetRoleRequest
|
||||
): Promise<void> {
|
||||
await api.put(
|
||||
`/groups/${encodeURIComponent(String(groupId))}/members/${encodeURIComponent(userId)}/admin`,
|
||||
`/groups/${encodeURIComponent(groupId)}/members/${encodeURIComponent(userId)}/admin`,
|
||||
{
|
||||
enable: data.role === 'admin',
|
||||
}
|
||||
@@ -200,8 +251,8 @@ class GroupService {
|
||||
* 设置群昵称
|
||||
* PUT /api/v1/groups/:id/members/me/nickname
|
||||
*/
|
||||
async setNickname(groupId: number | string, data: SetNicknameRequest): Promise<void> {
|
||||
await api.put(`/groups/${encodeURIComponent(String(groupId))}/members/me/nickname`, data);
|
||||
async setNickname(groupId: string, data: SetNicknameRequest): Promise<void> {
|
||||
await api.put(`/groups/${encodeURIComponent(groupId)}/members/me/nickname`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,11 +263,11 @@ class GroupService {
|
||||
* @param duration 禁言时长(秒),0表示解除禁言
|
||||
*/
|
||||
async muteMember(
|
||||
groupId: number | string,
|
||||
groupId: string,
|
||||
userId: string,
|
||||
duration: number = 0
|
||||
): Promise<void> {
|
||||
await api.post(`/groups/${encodeURIComponent(String(groupId))}/members/ban`, {
|
||||
await api.post(`/groups/${encodeURIComponent(groupId)}/members/ban`, {
|
||||
user_id: userId,
|
||||
duration: duration,
|
||||
});
|
||||
@@ -228,8 +279,8 @@ class GroupService {
|
||||
* 设置全员禁言
|
||||
* PUT /api/v1/groups/:id/ban
|
||||
*/
|
||||
async setMuteAll(groupId: number | string, data: SetMuteAllRequest): Promise<void> {
|
||||
await api.put(`/groups/${encodeURIComponent(String(groupId))}/ban`, {
|
||||
async setMuteAll(groupId: string, data: SetMuteAllRequest): Promise<void> {
|
||||
await api.put(`/groups/${encodeURIComponent(groupId)}/ban`, {
|
||||
enable: data.mute_all,
|
||||
});
|
||||
}
|
||||
@@ -238,16 +289,16 @@ class GroupService {
|
||||
* 设置加群方式
|
||||
* PUT /api/v1/groups/:id/join-type
|
||||
*/
|
||||
async setJoinType(groupId: number | string, data: SetJoinTypeRequest): Promise<void> {
|
||||
await api.put(`/groups/${encodeURIComponent(String(groupId))}/join-type`, data);
|
||||
async setJoinType(groupId: string, data: SetJoinTypeRequest): Promise<void> {
|
||||
await api.put(`/groups/${encodeURIComponent(groupId)}/join-type`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置群名称
|
||||
* PUT /api/v1/groups/:id/name
|
||||
*/
|
||||
async setGroupName(groupId: number | string, groupName: string): Promise<void> {
|
||||
await api.put(`/groups/${encodeURIComponent(String(groupId))}/name`, {
|
||||
async setGroupName(groupId: string, groupName: string): Promise<void> {
|
||||
await api.put(`/groups/${encodeURIComponent(groupId)}/name`, {
|
||||
group_name: groupName,
|
||||
});
|
||||
}
|
||||
@@ -256,14 +307,14 @@ class GroupService {
|
||||
* 设置群头像
|
||||
* PUT /api/v1/groups/:id/avatar
|
||||
*/
|
||||
async setGroupAvatar(groupId: number | string, avatarUrl: string): Promise<GroupResponse> {
|
||||
async setGroupAvatar(groupId: string, avatarUrl: string): Promise<GroupResponse> {
|
||||
const response = await api.put<GroupResponse>(
|
||||
`/groups/${encodeURIComponent(String(groupId))}/avatar`,
|
||||
`/groups/${encodeURIComponent(groupId)}/avatar`,
|
||||
{
|
||||
avatar: avatarUrl,
|
||||
}
|
||||
);
|
||||
return response.data;
|
||||
return normalizeGroup(response.data);
|
||||
}
|
||||
|
||||
// ==================== 群公告 ====================
|
||||
@@ -273,14 +324,14 @@ class GroupService {
|
||||
* POST /api/v1/groups/:id/announcements
|
||||
*/
|
||||
async createAnnouncement(
|
||||
groupId: number | string,
|
||||
groupId: string,
|
||||
data: CreateAnnouncementRequest
|
||||
): Promise<GroupAnnouncementResponse> {
|
||||
const response = await api.post<GroupAnnouncementResponse>(
|
||||
`/groups/${encodeURIComponent(String(groupId))}/announcements`,
|
||||
`/groups/${encodeURIComponent(groupId)}/announcements`,
|
||||
data
|
||||
);
|
||||
return response.data;
|
||||
return normalizeAnnouncement(response.data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -288,19 +339,19 @@ class GroupService {
|
||||
* GET /api/v1/groups/:id/announcements
|
||||
*/
|
||||
async getAnnouncements(
|
||||
groupId: number | string,
|
||||
groupId: string,
|
||||
page = 1,
|
||||
pageSize = 20
|
||||
): Promise<GroupAnnouncementListResponse> {
|
||||
try {
|
||||
const response = await api.get<GroupAnnouncementListResponse>(
|
||||
`/groups/${encodeURIComponent(String(groupId))}/announcements`,
|
||||
`/groups/${encodeURIComponent(groupId)}/announcements`,
|
||||
{
|
||||
page,
|
||||
page_size: pageSize,
|
||||
}
|
||||
);
|
||||
return response.data;
|
||||
return normalizeAnnouncementListResponse(response.data);
|
||||
} catch (error) {
|
||||
console.error('获取群公告列表失败:', error);
|
||||
return {
|
||||
@@ -317,9 +368,9 @@ class GroupService {
|
||||
* 删除群公告
|
||||
* DELETE /api/v1/groups/:id/announcements/:announcement_id
|
||||
*/
|
||||
async deleteAnnouncement(groupId: number | string, announcementId: number): Promise<void> {
|
||||
async deleteAnnouncement(groupId: string, announcementId: number): Promise<void> {
|
||||
await api.delete(
|
||||
`/groups/${encodeURIComponent(String(groupId))}/announcements/${encodeURIComponent(String(announcementId))}`
|
||||
`/groups/${encodeURIComponent(groupId)}/announcements/${encodeURIComponent(String(announcementId))}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -335,7 +386,7 @@ class GroupService {
|
||||
): Promise<CursorPaginationResponse<GroupResponse>> {
|
||||
try {
|
||||
const response = await api.get<CursorPaginationResponse<GroupResponse>>('/groups/cursor', params);
|
||||
return response.data;
|
||||
return normalizeGroupCursor(response.data);
|
||||
} catch (error) {
|
||||
console.error('获取群组列表失败:', error);
|
||||
return {
|
||||
@@ -354,15 +405,15 @@ class GroupService {
|
||||
* @param params 游标分页请求参数
|
||||
*/
|
||||
async getGroupMembersCursor(
|
||||
groupId: number | string,
|
||||
groupId: string,
|
||||
params: CursorPaginationRequest = {}
|
||||
): Promise<CursorPaginationResponse<GroupMemberResponse>> {
|
||||
try {
|
||||
const response = await api.get<CursorPaginationResponse<GroupMemberResponse>>(
|
||||
`/groups/${encodeURIComponent(String(groupId))}/members/cursor`,
|
||||
`/groups/${encodeURIComponent(groupId)}/members/cursor`,
|
||||
params
|
||||
);
|
||||
return response.data;
|
||||
return normalizeMemberCursor(response.data);
|
||||
} catch (error) {
|
||||
console.error('获取群组成员列表失败:', error);
|
||||
return {
|
||||
@@ -381,15 +432,15 @@ class GroupService {
|
||||
* @param params 游标分页请求参数
|
||||
*/
|
||||
async getGroupAnnouncementsCursor(
|
||||
groupId: number | string,
|
||||
groupId: string,
|
||||
params: CursorPaginationRequest = {}
|
||||
): Promise<CursorPaginationResponse<GroupAnnouncementResponse>> {
|
||||
try {
|
||||
const response = await api.get<CursorPaginationResponse<GroupAnnouncementResponse>>(
|
||||
`/groups/${encodeURIComponent(String(groupId))}/announcements/cursor`,
|
||||
`/groups/${encodeURIComponent(groupId)}/announcements/cursor`,
|
||||
params
|
||||
);
|
||||
return response.data;
|
||||
return normalizeAnnouncementCursor(response.data);
|
||||
} catch (error) {
|
||||
console.error('获取群公告列表失败:', error);
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user