➕ Add webrtc deps
This commit is contained in:
parent
33be7182d8
commit
ed32a31819
@ -15,12 +15,12 @@ android {
|
|||||||
ndkVersion = flutter.ndkVersion
|
ndkVersion = flutter.ndkVersion
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = JavaVersion.VERSION_1_8
|
jvmTarget = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
@ -1,4 +1,15 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<uses-feature android:name="android.hardware.camera" />
|
||||||
|
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="Solian"
|
android:label="Solian"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
@ -17,12 +28,12 @@
|
|||||||
while the Flutter UI initializes. After that, this theme continues
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
to determine the Window background behind the Flutter UI. -->
|
to determine the Window background behind the Flutter UI. -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme"
|
android:resource="@style/NormalTheme"
|
||||||
/>
|
/>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
@ -38,8 +49,8 @@
|
|||||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
<action android:name="android.intent.action.PROCESS_TEXT" />
|
||||||
<data android:mimeType="text/plain"/>
|
<data android:mimeType="text/plain" />
|
||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
</manifest>
|
</manifest>
|
@ -40,5 +40,9 @@ end
|
|||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
installer.pods_project.targets.each do |target|
|
installer.pods_project.targets.each do |target|
|
||||||
flutter_additional_ios_build_settings(target)
|
flutter_additional_ios_build_settings(target)
|
||||||
|
target.build_configurations.each do |config|
|
||||||
|
# Workaround for https://github.com/flutter/flutter/issues/64502
|
||||||
|
config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -105,6 +105,9 @@ PODS:
|
|||||||
- flutter_udid (0.0.1):
|
- flutter_udid (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SAMKeychain
|
- SAMKeychain
|
||||||
|
- flutter_webrtc (0.11.8):
|
||||||
|
- Flutter
|
||||||
|
- WebRTC-SDK (= 125.6422.05)
|
||||||
- GoogleAppMeasurement (11.4.0):
|
- GoogleAppMeasurement (11.4.0):
|
||||||
- GoogleAppMeasurement/AdIdSupport (= 11.4.0)
|
- GoogleAppMeasurement/AdIdSupport (= 11.4.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
||||||
@ -202,6 +205,7 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- wakelock_plus (0.0.1):
|
- wakelock_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- WebRTC-SDK (125.6422.05)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
|
||||||
@ -214,6 +218,7 @@ DEPENDENCIES:
|
|||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||||
- flutter_udid (from `.symlinks/plugins/flutter_udid/ios`)
|
- flutter_udid (from `.symlinks/plugins/flutter_udid/ios`)
|
||||||
|
- flutter_webrtc (from `.symlinks/plugins/flutter_webrtc/ios`)
|
||||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||||
- isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`)
|
- isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`)
|
||||||
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
|
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
|
||||||
@ -249,6 +254,7 @@ SPEC REPOS:
|
|||||||
- SDWebImage
|
- SDWebImage
|
||||||
- Sentry
|
- Sentry
|
||||||
- SwiftyGif
|
- SwiftyGif
|
||||||
|
- WebRTC-SDK
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
connectivity_plus:
|
connectivity_plus:
|
||||||
@ -271,6 +277,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||||
flutter_udid:
|
flutter_udid:
|
||||||
:path: ".symlinks/plugins/flutter_udid/ios"
|
:path: ".symlinks/plugins/flutter_udid/ios"
|
||||||
|
flutter_webrtc:
|
||||||
|
:path: ".symlinks/plugins/flutter_webrtc/ios"
|
||||||
image_picker_ios:
|
image_picker_ios:
|
||||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||||
isar_flutter_libs:
|
isar_flutter_libs:
|
||||||
@ -321,6 +329,7 @@ SPEC CHECKSUMS:
|
|||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
flutter_native_splash: e8a1e01082d97a8099d973f919f57904c925008a
|
flutter_native_splash: e8a1e01082d97a8099d973f919f57904c925008a
|
||||||
flutter_udid: a2482c67a61b9c806ef59dd82ed8d007f1b7ac04
|
flutter_udid: a2482c67a61b9c806ef59dd82ed8d007f1b7ac04
|
||||||
|
flutter_webrtc: 4f730f3d58a28b0afdea039c8bf4a0f616a6b20c
|
||||||
GoogleAppMeasurement: 987769c4ca6b968f2479fbcc9fe3ce34af454b8e
|
GoogleAppMeasurement: 987769c4ca6b968f2479fbcc9fe3ce34af454b8e
|
||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
|
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
|
||||||
@ -345,7 +354,8 @@ SPEC CHECKSUMS:
|
|||||||
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
||||||
volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9
|
volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9
|
||||||
wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1
|
wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1
|
||||||
|
WebRTC-SDK: 1990a1a595bd0b59c17485ce13ff17f575732c12
|
||||||
|
|
||||||
PODFILE CHECKSUM: a57f30d18f102dd3ce366b1d62a55ecbef2158e5
|
PODFILE CHECKSUM: d2bdaa1cc7915e14cf47235c34a21fcb07b00390
|
||||||
|
|
||||||
COCOAPODS: 1.15.2
|
COCOAPODS: 1.15.2
|
||||||
|
@ -4,6 +4,7 @@ import 'package:easy_localization_loader/easy_localization_loader.dart';
|
|||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:relative_time/relative_time.dart';
|
import 'package:relative_time/relative_time.dart';
|
||||||
@ -22,6 +23,7 @@ import 'package:surface/providers/websocket.dart';
|
|||||||
import 'package:surface/router.dart';
|
import 'package:surface/router.dart';
|
||||||
import 'package:surface/types/chat.dart';
|
import 'package:surface/types/chat.dart';
|
||||||
import 'package:surface/types/realm.dart';
|
import 'package:surface/types/realm.dart';
|
||||||
|
import 'package:flutter_web_plugins/url_strategy.dart' show usePathUrlStrategy;
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@ -41,6 +43,9 @@ void main() async {
|
|||||||
debugInvertOversizedImages = true;
|
debugInvertOversizedImages = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GoRouter.optionURLReflectsImperativeAPIs = true;
|
||||||
|
usePathUrlStrategy();
|
||||||
|
|
||||||
await SentryFlutter.init(
|
await SentryFlutter.init(
|
||||||
(options) {
|
(options) {
|
||||||
options.dsn =
|
options.dsn =
|
||||||
|
@ -10,6 +10,7 @@ import 'package:surface/screens/album.dart';
|
|||||||
import 'package:surface/screens/auth/login.dart';
|
import 'package:surface/screens/auth/login.dart';
|
||||||
import 'package:surface/screens/auth/register.dart';
|
import 'package:surface/screens/auth/register.dart';
|
||||||
import 'package:surface/screens/chat.dart';
|
import 'package:surface/screens/chat.dart';
|
||||||
|
import 'package:surface/screens/chat/call_room.dart';
|
||||||
import 'package:surface/screens/chat/manage.dart';
|
import 'package:surface/screens/chat/manage.dart';
|
||||||
import 'package:surface/screens/chat/room.dart';
|
import 'package:surface/screens/chat/room.dart';
|
||||||
import 'package:surface/screens/explore.dart';
|
import 'package:surface/screens/explore.dart';
|
||||||
@ -47,7 +48,7 @@ final _appRoutes = [
|
|||||||
),
|
),
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/post/write/:mode',
|
path: '/write/:mode',
|
||||||
name: 'postEditor',
|
name: 'postEditor',
|
||||||
builder: (context, state) => AppBackground(
|
builder: (context, state) => AppBackground(
|
||||||
isLessOptimization: true,
|
isLessOptimization: true,
|
||||||
@ -66,14 +67,14 @@ final _appRoutes = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/post/search',
|
path: '/search',
|
||||||
name: 'postSearch',
|
name: 'postSearch',
|
||||||
builder: (context, state) => const AppBackground(
|
builder: (context, state) => const AppBackground(
|
||||||
child: PostSearchScreen(),
|
child: PostSearchScreen(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/post/:slug',
|
path: '/:slug',
|
||||||
name: 'postDetail',
|
name: 'postDetail',
|
||||||
builder: (context, state) => AppBackground(
|
builder: (context, state) => AppBackground(
|
||||||
child: PostDetailScreen(
|
child: PostDetailScreen(
|
||||||
@ -99,7 +100,7 @@ final _appRoutes = [
|
|||||||
),
|
),
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/chat/:scope/:alias',
|
path: '/:scope/:alias',
|
||||||
name: 'chatRoom',
|
name: 'chatRoom',
|
||||||
builder: (context, state) => AppBackground(
|
builder: (context, state) => AppBackground(
|
||||||
isLessOptimization: true,
|
isLessOptimization: true,
|
||||||
@ -110,7 +111,18 @@ final _appRoutes = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/chat/manage',
|
path: '/:scope/:alias/call',
|
||||||
|
name: 'chatCallRoom',
|
||||||
|
builder: (context, state) => AppBackground(
|
||||||
|
isLessOptimization: true,
|
||||||
|
child: CallRoomScreen(
|
||||||
|
scope: state.pathParameters['scope']!,
|
||||||
|
alias: state.pathParameters['alias']!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: '/manage',
|
||||||
name: 'chatManage',
|
name: 'chatManage',
|
||||||
pageBuilder: (context, state) => CustomTransitionPage(
|
pageBuilder: (context, state) => CustomTransitionPage(
|
||||||
child: ChatManageScreen(),
|
child: ChatManageScreen(),
|
||||||
@ -138,7 +150,7 @@ final _appRoutes = [
|
|||||||
),
|
),
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/realm/manage',
|
path: '/manage',
|
||||||
name: 'realmManage',
|
name: 'realmManage',
|
||||||
pageBuilder: (context, state) => CustomTransitionPage(
|
pageBuilder: (context, state) => CustomTransitionPage(
|
||||||
child: RealmManageScreen(
|
child: RealmManageScreen(
|
||||||
|
137
lib/screens/chat/call_room.dart
Normal file
137
lib/screens/chat/call_room.dart
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||||
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||||
|
|
||||||
|
class CallRoomScreen extends StatefulWidget {
|
||||||
|
final String scope;
|
||||||
|
final String alias;
|
||||||
|
const CallRoomScreen({super.key, required this.scope, required this.alias});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CallRoomScreen> createState() => _CallRoomScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
const _kLocalWebRtcBaseUrl = 'http://localhost:8001';
|
||||||
|
|
||||||
|
class _CallRoomScreenState extends State<CallRoomScreen> {
|
||||||
|
RTCPeerConnection? _peerConnection;
|
||||||
|
MediaStream? _localStream;
|
||||||
|
WebSocketChannel? _wsChannel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_initWebRtc();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _initWebRtc() async {
|
||||||
|
final client = Dio();
|
||||||
|
client.options.baseUrl = _kLocalWebRtcBaseUrl;
|
||||||
|
|
||||||
|
final configResp = await client.get('/.well-known/webrtc');
|
||||||
|
|
||||||
|
// Get user media (audio only)
|
||||||
|
_localStream = await navigator.mediaDevices.getUserMedia({
|
||||||
|
'audio': true,
|
||||||
|
'video': false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Configure Peer Connection
|
||||||
|
Map<String, dynamic> config = {
|
||||||
|
'iceServers': configResp.data['ice_servers']
|
||||||
|
};
|
||||||
|
|
||||||
|
_peerConnection = await createPeerConnection(config);
|
||||||
|
|
||||||
|
// Add local stream to peer connection
|
||||||
|
_peerConnection?.addStream(_localStream!);
|
||||||
|
|
||||||
|
// Listen for ICE candidates
|
||||||
|
_peerConnection?.onIceCandidate = (RTCIceCandidate candidate) {
|
||||||
|
print('New ICE candidate: ${candidate.candidate}');
|
||||||
|
// Send the candidate to the signaling server
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle remote stream
|
||||||
|
_peerConnection?.onAddStream = (MediaStream stream) {
|
||||||
|
print('Remote stream added');
|
||||||
|
// Play the remote stream
|
||||||
|
};
|
||||||
|
|
||||||
|
_wsChannel = WebSocketChannel.connect(
|
||||||
|
Uri.parse('$_kLocalWebRtcBaseUrl/webrtc'),
|
||||||
|
);
|
||||||
|
await _wsChannel!.ready;
|
||||||
|
|
||||||
|
_wsChannel!.stream.listen((event) {
|
||||||
|
final Map<String, dynamic> data = jsonDecode(event);
|
||||||
|
|
||||||
|
switch (data['type']) {
|
||||||
|
case 'offer':
|
||||||
|
_handleOffer(data);
|
||||||
|
break;
|
||||||
|
case 'answer':
|
||||||
|
_handleAnswer(data);
|
||||||
|
break;
|
||||||
|
case 'candidate':
|
||||||
|
_handleCandidate(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _handleOffer(Map<String, dynamic> data) async {
|
||||||
|
// Set remote description
|
||||||
|
final offer = RTCSessionDescription(data['sdp'], data['type']);
|
||||||
|
await _peerConnection?.setRemoteDescription(offer);
|
||||||
|
|
||||||
|
// Create and send answer
|
||||||
|
final answer = await _peerConnection?.createAnswer();
|
||||||
|
await _peerConnection?.setLocalDescription(answer!);
|
||||||
|
|
||||||
|
_wsChannel?.sink.add({
|
||||||
|
'type': 'answer',
|
||||||
|
'sdp': answer?.sdp,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _handleAnswer(Map<String, dynamic> data) async {
|
||||||
|
// Set remote description
|
||||||
|
final answer = RTCSessionDescription(data['sdp'], data['type']);
|
||||||
|
await _peerConnection?.setRemoteDescription(answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _handleCandidate(Map<String, dynamic> data) async {
|
||||||
|
// Add ICE candidate
|
||||||
|
final candidate = RTCIceCandidate(
|
||||||
|
data['candidate'],
|
||||||
|
data['sdpMid'],
|
||||||
|
data['sdpMLineIndex'],
|
||||||
|
);
|
||||||
|
await _peerConnection?.addCandidate(candidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_wsChannel?.sink.close();
|
||||||
|
_localStream?.dispose();
|
||||||
|
_peerConnection?.close();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: Text('Voice Chat')),
|
||||||
|
body: Center(
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: Text('Start Call'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:surface/controllers/chat_message_controller.dart';
|
import 'package:surface/controllers/chat_message_controller.dart';
|
||||||
@ -62,6 +64,18 @@ class _ChatRoomScreenState extends State<ChatRoomScreen> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(_channel?.name ?? 'loading'.tr()),
|
title: Text(_channel?.name ?? 'loading'.tr()),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
GoRouter.of(context).pushNamed('chatCallRoom', pathParameters: {
|
||||||
|
'scope': widget.scope,
|
||||||
|
'alias': widget.alias,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.voice_chat),
|
||||||
|
),
|
||||||
|
IconButton(onPressed: () {}, icon: const Icon(Symbols.more_vert)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: ListenableBuilder(
|
body: ListenableBuilder(
|
||||||
listenable: _messageController,
|
listenable: _messageController,
|
||||||
|
@ -122,21 +122,25 @@ class _PostDetailScreenState extends State<PostDetailScreen> {
|
|||||||
const SliverToBoxAdapter(child: Divider(height: 1)),
|
const SliverToBoxAdapter(child: Divider(height: 1)),
|
||||||
if (_data != null)
|
if (_data != null)
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Row(
|
child: Container(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
constraints: const BoxConstraints(maxWidth: 640),
|
||||||
children: [
|
child: Row(
|
||||||
const Icon(Symbols.comment, size: 24),
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
const Gap(16),
|
children: [
|
||||||
Text('postCommentsDetailed')
|
const Icon(Symbols.comment, size: 24),
|
||||||
.plural(_data!.metric.replyCount)
|
const Gap(16),
|
||||||
.textStyle(Theme.of(context).textTheme.titleLarge!),
|
Text('postCommentsDetailed')
|
||||||
],
|
.plural(_data!.metric.replyCount)
|
||||||
).padding(horizontal: 20, vertical: 12),
|
.textStyle(Theme.of(context).textTheme.titleLarge!),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 20, vertical: 12).center(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (_data != null && ua.isAuthorized)
|
if (_data != null && ua.isAuthorized)
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 240,
|
height: 240,
|
||||||
|
constraints: const BoxConstraints(maxWidth: 640),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.symmetric(
|
border: Border.symmetric(
|
||||||
horizontal: BorderSide(
|
horizontal: BorderSide(
|
||||||
@ -158,7 +162,7 @@ class _PostDetailScreenState extends State<PostDetailScreen> {
|
|||||||
_childListKey.currentState!.refresh();
|
_childListKey.currentState!.refresh();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
).center(),
|
||||||
),
|
),
|
||||||
if (_data != null)
|
if (_data != null)
|
||||||
PostCommentSliverList(
|
PostCommentSliverList(
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include <file_selector_linux/file_selector_plugin.h>
|
#include <file_selector_linux/file_selector_plugin.h>
|
||||||
#include <flutter_udid/flutter_udid_plugin.h>
|
#include <flutter_udid/flutter_udid_plugin.h>
|
||||||
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
|
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
||||||
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
||||||
#include <media_kit_video/media_kit_video_plugin.h>
|
#include <media_kit_video/media_kit_video_plugin.h>
|
||||||
#include <pasteboard/pasteboard_plugin.h>
|
#include <pasteboard/pasteboard_plugin.h>
|
||||||
@ -22,9 +22,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||||||
g_autoptr(FlPluginRegistrar) flutter_udid_registrar =
|
g_autoptr(FlPluginRegistrar) flutter_udid_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterUdidPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterUdidPlugin");
|
||||||
flutter_udid_plugin_register_with_registrar(flutter_udid_registrar);
|
flutter_udid_plugin_register_with_registrar(flutter_udid_registrar);
|
||||||
g_autoptr(FlPluginRegistrar) isar_flutter_libs_registrar =
|
g_autoptr(FlPluginRegistrar) flutter_webrtc_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "IsarFlutterLibsPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterWebRTCPlugin");
|
||||||
isar_flutter_libs_plugin_register_with_registrar(isar_flutter_libs_registrar);
|
flutter_web_r_t_c_plugin_register_with_registrar(flutter_webrtc_registrar);
|
||||||
g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar =
|
g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin");
|
||||||
media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar);
|
media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
file_selector_linux
|
file_selector_linux
|
||||||
flutter_udid
|
flutter_udid
|
||||||
isar_flutter_libs
|
flutter_webrtc
|
||||||
media_kit_libs_linux
|
media_kit_libs_linux
|
||||||
media_kit_video
|
media_kit_video
|
||||||
pasteboard
|
pasteboard
|
||||||
|
@ -11,7 +11,7 @@ import firebase_analytics
|
|||||||
import firebase_core
|
import firebase_core
|
||||||
import firebase_messaging
|
import firebase_messaging
|
||||||
import flutter_udid
|
import flutter_udid
|
||||||
import isar_flutter_libs
|
import flutter_webrtc
|
||||||
import media_kit_libs_macos_video
|
import media_kit_libs_macos_video
|
||||||
import media_kit_video
|
import media_kit_video
|
||||||
import package_info_plus
|
import package_info_plus
|
||||||
@ -31,7 +31,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||||
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
|
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
|
||||||
FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
|
FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
|
||||||
IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin"))
|
FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin"))
|
||||||
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
|
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
|
||||||
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
||||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||||
|
50
pubspec.lock
50
pubspec.lock
@ -310,6 +310,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.7"
|
version: "2.3.7"
|
||||||
|
dart_webrtc:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dart_webrtc
|
||||||
|
sha256: c664ad88d5646735753add421ee2118486c100febef5e92b7f59cdbabf6a51f6
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.9"
|
||||||
dbus:
|
dbus:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -630,10 +638,18 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
version: "3.0.0"
|
||||||
flutter_web_plugins:
|
flutter_web_plugins:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_webrtc:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_webrtc
|
||||||
|
sha256: "0b69ecab98211504c10d40c1c4cb48eb387e03ea8e732079bd0d2665d8c20d3f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.12.1+hotfix.1"
|
||||||
freezed:
|
freezed:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -858,22 +874,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.4"
|
||||||
isar:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: isar
|
|
||||||
sha256: "99165dadb2cf2329d3140198363a7e7bff9bbd441871898a87e26914d25cf1ea"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.0+1"
|
|
||||||
isar_flutter_libs:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: isar_flutter_libs
|
|
||||||
sha256: bc6768cc4b9c61aabff77152e7f33b4b17d2fc93134f7af1c3dd51500fe8d5e8
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.0+1"
|
|
||||||
jni:
|
jni:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1226,6 +1226,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.6"
|
version: "3.1.6"
|
||||||
|
platform_detect:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: platform_detect
|
||||||
|
sha256: a62f99417fc4fa2d099ce0ccdbb1bd3977920f2a64292c326271f049d4bc3a4f
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1791,6 +1799,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.1"
|
||||||
|
webrtc_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webrtc_interface
|
||||||
|
sha256: abec3ab7956bd5ac539cf34a42fa0c82ea26675847c0966bb85160400eea9388
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -30,6 +30,8 @@ environment:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_web_plugins:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
@ -73,8 +75,6 @@ dependencies:
|
|||||||
collection: ^1.18.0
|
collection: ^1.18.0
|
||||||
mime: ^2.0.0
|
mime: ^2.0.0
|
||||||
web_socket_channel: ^3.0.1
|
web_socket_channel: ^3.0.1
|
||||||
isar: ^3.1.0+1
|
|
||||||
isar_flutter_libs: ^3.1.0+1
|
|
||||||
hive: ^2.2.3
|
hive: ^2.2.3
|
||||||
hive_flutter: ^1.1.0
|
hive_flutter: ^1.1.0
|
||||||
swipe_to: ^1.0.6
|
swipe_to: ^1.0.6
|
||||||
@ -88,6 +88,7 @@ dependencies:
|
|||||||
pasteboard: ^0.3.0
|
pasteboard: ^0.3.0
|
||||||
sentry_flutter: ^8.10.1
|
sentry_flutter: ^8.10.1
|
||||||
synchronized: ^3.3.0+3
|
synchronized: ^3.3.0+3
|
||||||
|
flutter_webrtc: ^0.12.1+hotfix.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include <file_selector_windows/file_selector_windows.h>
|
#include <file_selector_windows/file_selector_windows.h>
|
||||||
#include <firebase_core/firebase_core_plugin_c_api.h>
|
#include <firebase_core/firebase_core_plugin_c_api.h>
|
||||||
#include <flutter_udid/flutter_udid_plugin_c_api.h>
|
#include <flutter_udid/flutter_udid_plugin_c_api.h>
|
||||||
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
|
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
||||||
#include <media_kit_libs_windows_video/media_kit_libs_windows_video_plugin_c_api.h>
|
#include <media_kit_libs_windows_video/media_kit_libs_windows_video_plugin_c_api.h>
|
||||||
#include <media_kit_video/media_kit_video_plugin_c_api.h>
|
#include <media_kit_video/media_kit_video_plugin_c_api.h>
|
||||||
#include <pasteboard/pasteboard_plugin.h>
|
#include <pasteboard/pasteboard_plugin.h>
|
||||||
@ -27,8 +27,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||||||
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
|
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
|
||||||
FlutterUdidPluginCApiRegisterWithRegistrar(
|
FlutterUdidPluginCApiRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("FlutterUdidPluginCApi"));
|
registry->GetRegistrarForPlugin("FlutterUdidPluginCApi"));
|
||||||
IsarFlutterLibsPluginRegisterWithRegistrar(
|
FlutterWebRTCPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("IsarFlutterLibsPlugin"));
|
registry->GetRegistrarForPlugin("FlutterWebRTCPlugin"));
|
||||||
MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar(
|
MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi"));
|
registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi"));
|
||||||
MediaKitVideoPluginCApiRegisterWithRegistrar(
|
MediaKitVideoPluginCApiRegisterWithRegistrar(
|
||||||
|
@ -7,7 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
file_selector_windows
|
file_selector_windows
|
||||||
firebase_core
|
firebase_core
|
||||||
flutter_udid
|
flutter_udid
|
||||||
isar_flutter_libs
|
flutter_webrtc
|
||||||
media_kit_libs_windows_video
|
media_kit_libs_windows_video
|
||||||
media_kit_video
|
media_kit_video
|
||||||
pasteboard
|
pasteboard
|
||||||
|
Loading…
x
Reference in New Issue
Block a user