Rebrand the entire application from "胡萝卜社区" (Carrot BBS) to "威友" (WithYou), including:
Some checks failed
Frontend CI / build-and-push-web (push) Failing after 2m51s
Frontend CI / ota-android (push) Successful in 11m16s
Frontend CI / build-android-apk (push) Failing after 12m54s

- Update app name, package name (skin.carrot.bbs → cn.qczlit.withyou), and bundle identifier
- Update API endpoints (bbs.littlelan.cn → withyou.littlelan.cn)
- Update URL scheme (carrotbbs:// → withyou://)
- Rename database from carrot_bbs to with_you
- Update CI/CD pipeline image names and artifact naming
- Add Android signing configuration for release builds
- Update all UI text and comments throughout the codebase
- Refactor registerStore to use in-memory state instead of AsyncStorage persistence
- Improve WebRTC track handling and call stream management
- Add metro platform resolution for native platform support

BREAKING app package, database, and URLs are no longer valid
This commit is contained in:
lafay
2026-04-22 16:54:51 +08:00
parent 1c3797ea7d
commit 437dab3b6e
47 changed files with 221 additions and 235 deletions

View File

@@ -1,4 +1,4 @@
/**
/**
* 后台同步管理器
*
* 整合前台服务、后台同步、消息状态管理
@@ -86,7 +86,7 @@ class BackgroundSyncManager {
if (mode === BackgroundSyncMode.REALTIME) {
// 切换到实时模式:立即启动前台服务(无论前台还是后台)
const started = await ForegroundServiceModule.start({
title: '萝卜社区',
title: '威友',
body: '正在后台同步消息',
});
if (started) {
@@ -134,7 +134,7 @@ class BackgroundSyncManager {
if (this.mode === BackgroundSyncMode.REALTIME) {
// 确保前台服务正在运行
await ForegroundServiceModule.start({
title: '萝卜社区',
title: '威友',
body: '正在后台同步消息',
});
@@ -154,7 +154,7 @@ class BackgroundSyncManager {
// 实时模式下:前台服务保持运行,只更新通知文字
if (this.mode === BackgroundSyncMode.REALTIME) {
await ForegroundServiceModule.update('萝卜社区', '正在后台同步消息');
await ForegroundServiceModule.update('威友', '正在后台同步消息');
}
// 立即同步一次(获取离线消息)
@@ -235,12 +235,12 @@ class BackgroundSyncManager {
if (totalUnread > 0) {
await ForegroundServiceModule.update(
'萝卜社区',
'威友',
`您有 ${totalUnread} 条未读消息`
);
} else {
await ForegroundServiceModule.update(
'萝卜社区',
'威友',
'正在后台同步消息'
);
}

View File

@@ -1,4 +1,4 @@
/**
/**
* 前台服务模块
*
* 提供 React Native 层对 Android 前台服务的控制接口
@@ -40,7 +40,7 @@ export const ForegroundServiceModule = {
try {
const result = await ForegroundService.start(
options.title || '萝卜社区',
options.title || '威友',
options.body || '正在后台同步消息'
);
console.log('[ForegroundService] 服务已启动');

View File

@@ -11,13 +11,13 @@ import { Platform } from 'react-native';
import { eventBus } from '@/core/events/EventBus';
// 生产地址 https://bbs.littlelan.cn
// 生产地址 https://withyou.littlelan.cn
const getBaseUrl = () => {
const configuredBaseUrl = Constants.expoConfig?.extra?.apiBaseUrl;
if (typeof configuredBaseUrl === 'string' && configuredBaseUrl.trim().length > 0) {
return configuredBaseUrl;
}
return 'https://bbs.littlelan.cn/api/v1';
return 'https://withyou.littlelan.cn/api/v1';
};
const BASE_URL = getBaseUrl();

View File

@@ -144,7 +144,7 @@ async function downloadAndInstallAPK(downloadUrl: string, version: string): Prom
}
try {
const downloadPath = `${FileSystem.documentDirectory}carrot-bbs-${version}.apk`;
const downloadPath = `${FileSystem.documentDirectory}with-you-${version}.apk`;
// 显示下载进度
showConfirm({

View File

@@ -96,22 +96,24 @@ class WebRTCManager {
console.log('[WebRTC] ontrack: no track in event');
return;
}
// Official react-native-webrtc approach: use event.streams[0] if available
if (event.streams && event.streams[0]) {
this.remoteStream = event.streams[0];
} else {
// Fallback: manually construct stream
if (!this.remoteStream) {
this.remoteStream = new MediaStream();
}
// Check if track already exists to avoid duplicates
const existingTracks = this.remoteStream.getTracks();
const trackExists = existingTracks.some(t => t.id === event.track.id);
if (!trackExists) {
this.remoteStream.addTrack(event.track);
}
// Always manually construct/append to remoteStream to ensure all tracks are collected
// react-native-webrtc may fire ontrack per-track and event.streams[0] might not contain all tracks
if (!this.remoteStream) {
this.remoteStream = new MediaStream();
}
this.emit({ type: 'remotestream', stream: this.remoteStream! });
// Check if track already exists to avoid duplicates
const existingTracks = this.remoteStream.getTracks();
const trackExists = existingTracks.some(t => t.id === event.track.id);
if (!trackExists) {
this.remoteStream.addTrack(event.track);
console.log('[WebRTC] Added remote track:', event.track.kind, 'total tracks:', this.remoteStream.getTracks().length);
} else {
console.log('[WebRTC] Remote track already exists:', event.track.kind);
}
this.emit({ type: 'remotestream', stream: this.remoteStream });
};
// @ts-ignore
@@ -655,7 +657,8 @@ class WebRTCManager {
}
if (this.remoteStream) {
this.remoteStream.getTracks().forEach((track) => track.stop());
// Do not stop remote tracks; they are managed by the peer connection
// and will be ended automatically when the connection closes
this.remoteStream = null;
}