feat(call): migrate from WebRTC to LiveKit
Some checks failed
Frontend CI / ota-android (push) Has been cancelled
Frontend CI / ota-ios (push) Has been cancelled
Frontend CI / build-and-push-web (push) Has been cancelled
Frontend CI / build-android-apk (push) Has been cancelled

Replace the custom WebRTC implementation with LiveKit for improved
stability and feature support.

- Remove `react-native-webrtc` and custom `WebRTCManager`
- Implement `LiveKitService` for room and track management
- Update `callStore` to handle LiveKit events and connection states
- Refactor `CallScreen` (mobile and web) to use `@livekit/react-native`
  and `VideoView`
- Update WebSocket protocol to use `call_ready` instead of manual SDP/ICE
  exchanges
- Add necessary camera and microphone permissions to `app.json`
- Update Metro and Babel configurations for LiveKit compatibility
This commit is contained in:
2026-06-01 13:45:45 +08:00
parent 72c30ed156
commit 70ab00795a
17 changed files with 2500 additions and 1420 deletions

View File

@@ -14,39 +14,80 @@ const withHuaweiPush = (config, options = {}) => {
config = withSettingsGradle(config, (config) => {
const contents = config.modResults.contents;
// Add Huawei Maven repo to pluginManagement.repositories for plugin resolution
if (!contents.includes('developer.huawei.com/repo')) {
if (contents.includes('pluginManagement')) {
config.modResults.contents = contents.replace(
/(pluginManagement\s*\{[\s\S]*?repositories\s*\{)/,
`$1\n maven { url 'https://developer.huawei.com/repo/' }`
);
}
if (!config.modResults.contents.includes('developer.huawei.com/repo')) {
} else {
// No pluginManagement block at all — create one with the Huawei repo
config.modResults.contents =
`pluginManagement {\n repositories {\n maven { url 'https://developer.huawei.com/repo/' }\n }\n}\n` +
`pluginManagement {\n repositories {\n maven { url 'https://developer.huawei.com/repo/' }\n }\n}\n\n` +
config.modResults.contents;
}
}
if (!config.modResults.contents.includes("id 'com.huawei.agconnect'")) {
if (config.modResults.contents.includes('pluginManagement')) {
// Map the plugin ID to its Maven artifact via resolutionStrategy.
// AGConnect is not published as a standard Gradle plugin marker, so Gradle 9+
// cannot resolve it by plugin ID alone. This mapping tells Gradle where to find it.
if (!config.modResults.contents.includes('com.huawei.agconnect:agcp')) {
const pmMatch = config.modResults.contents.match(/pluginManagement\s*\{/);
if (pmMatch) {
config.modResults.contents = config.modResults.contents.replace(
/(pluginManagement\s*\{)/,
`$1\n plugins {\n id 'com.huawei.agconnect' version '1.9.1.301' apply false\n }`
`$1\n resolutionStrategy {\n eachPlugin {\n if (requested.id.id == 'com.huawei.agconnect') {\n useModule('com.huawei.agconnect:agcp:1.9.1.301')\n }\n }\n }`
);
}
}
if (!config.modResults.contents.includes('developer.huawei.com/repo')) {
// Ensure Huawei Maven repo also appears in dependencyResolutionManagement (Gradle 9+)
if (!config.modResults.contents.match(/dependencyResolutionManagement[\s\S]*developer\.huawei\.com\/repo/)) {
const depMgmtPattern = /dependencyResolutionManagement\s*\{[\s\S]*?repositories\s*\{/;
if (depMgmtPattern.test(config.modResults.contents)) {
config.modResults.contents = config.modResults.contents.replace(
depMgmtPattern,
`$&\n maven { url 'https://developer.huawei.com/repo/' }`
`$&\n maven { url 'https://developer.huawei.com/repo/' }`
);
}
}
// Declare the plugin in a top-level plugins {} block (outside pluginManagement).
// In Gradle 9+, plugins declared with `apply false` in settings.gradle are
// available to all subprojects via `apply plugin:` or the plugins DSL.
if (!config.modResults.contents.includes("id 'com.huawei.agconnect'")) {
const pluginsBlockPattern = /^plugins\s*\{/m;
if (pluginsBlockPattern.test(config.modResults.contents)) {
// Add to existing top-level plugins block
config.modResults.contents = config.modResults.contents.replace(
/^plugins\s*\{/m,
`plugins {\n id 'com.huawei.agconnect' version '1.9.1.301' apply false`
);
} else {
// Insert a top-level plugins block after pluginManagement closing brace,
// or at the very beginning if no pluginManagement block exists.
const pmClosePattern = /\n\}\n/;
if (pmClosePattern.test(config.modResults.contents)) {
const firstClosing = config.modResults.contents.indexOf('}', config.modResults.contents.indexOf('pluginManagement')) + 1;
if (firstClosing > 0) {
const insertPos = firstClosing;
config.modResults.contents =
config.modResults.contents.slice(0, insertPos) +
`\n\nplugins {\n id 'com.huawei.agconnect' version '1.9.1.301' apply false\n}` +
config.modResults.contents.slice(insertPos);
}
} else {
// Fallback: prepend after pluginManagement block
config.modResults.contents =
config.modResults.contents.replace(
/(pluginManagement\s*\{[\s\S]*?\})/,
`$1\n\nplugins {\n id 'com.huawei.agconnect' version '1.9.1.301' apply false\n}`
);
}
}
}
return config;
});