8 changed files with 205 additions and 5 deletions
Split View
Diff Options
-
56lib/controller/discover/room_controller.dart
-
28lib/model/rtc/rtc_channel_data.dart
-
1lib/network/api_urls.dart
-
3lib/network/index.dart
-
6lib/network/network_service.dart
-
18lib/network/rtc_api.dart
-
81lib/network/rtc_api.g.dart
-
17lib/pages/discover/discover_page.dart
@ -0,0 +1,56 @@ |
|||
import 'package:dating_touchme_app/model/rtc/rtc_channel_data.dart'; |
|||
import 'package:dating_touchme_app/network/network_service.dart'; |
|||
import 'package:dating_touchme_app/rtc/rtc_manager.dart'; |
|||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
|||
import 'package:get/get.dart'; |
|||
|
|||
import '../../pages/discover/live_room_page.dart'; |
|||
|
|||
/// 直播房间相关控制器 |
|||
class RoomController extends GetxController { |
|||
RoomController({NetworkService? networkService}) |
|||
: _networkService = networkService ?? Get.find<NetworkService>(); |
|||
|
|||
final NetworkService _networkService; |
|||
|
|||
/// 当前频道信息 |
|||
final Rxn<RtcChannelData> rtcChannel = Rxn<RtcChannelData>(); |
|||
|
|||
/// 是否正在创建 |
|||
final RxBool isLoading = false.obs; |
|||
|
|||
/// 调用接口创建 RTC 频道 |
|||
Future<void> createRtcChannel() async { |
|||
if (isLoading.value) return ; |
|||
|
|||
try { |
|||
isLoading.value = true; |
|||
final response = await _networkService.rtcApi.createRtcChannel(); |
|||
final base = response.data; |
|||
|
|||
if (base.isSuccess && base.data != null) { |
|||
rtcChannel.value = base.data; |
|||
await _joinRtcChannel(base.data!); |
|||
} else { |
|||
final message = base.message.isNotEmpty ? base.message : '创建频道失败'; |
|||
SmartDialog.showToast(message); |
|||
} |
|||
} catch (e) { |
|||
SmartDialog.showToast('创建频道异常:$e'); |
|||
} finally { |
|||
isLoading.value = false; |
|||
} |
|||
} |
|||
Future<void> _joinRtcChannel(RtcChannelData data) async { |
|||
try { |
|||
await RTCManager.instance.joinChannel( |
|||
token: data.token, |
|||
channelId: data.channelId, |
|||
); |
|||
Get.to(() => const LiveRoomPage(id: 0)); |
|||
} catch (e) { |
|||
SmartDialog.showToast('加入频道失败:$e'); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,28 @@ |
|||
/// RTC 频道创建返回数据 |
|||
class RtcChannelData { |
|||
final String channelId; |
|||
final String token; |
|||
|
|||
RtcChannelData({ |
|||
required this.channelId, |
|||
required this.token, |
|||
}); |
|||
|
|||
factory RtcChannelData.fromJson(Map<String, dynamic> json) { |
|||
return RtcChannelData( |
|||
channelId: json['channelId']?.toString() ?? '', |
|||
token: json['token']?.toString() ?? '', |
|||
); |
|||
} |
|||
|
|||
Map<String, dynamic> toJson() { |
|||
return { |
|||
'channelId': channelId, |
|||
'token': token, |
|||
}; |
|||
} |
|||
|
|||
@override |
|||
String toString() => 'RtcChannelData(channelId: $channelId)'; |
|||
} |
|||
|
|||
@ -1,4 +1,5 @@ |
|||
export 'api_service.dart'; |
|||
export 'network_config.dart'; |
|||
export 'network_service.dart'; |
|||
export 'response_model.dart'; |
|||
export 'response_model.dart'; |
|||
export 'rtc_api.dart'; |
|||
@ -0,0 +1,18 @@ |
|||
import 'package:dating_touchme_app/model/rtc/rtc_channel_data.dart'; |
|||
import 'package:dating_touchme_app/network/api_urls.dart'; |
|||
import 'package:dating_touchme_app/network/response_model.dart'; |
|||
import 'package:dio/dio.dart'; |
|||
import 'package:retrofit/retrofit.dart'; |
|||
|
|||
part 'rtc_api.g.dart'; |
|||
|
|||
/// RTC 相关接口 |
|||
@RestApi(baseUrl: '') |
|||
abstract class RtcApi { |
|||
factory RtcApi(Dio dio) = _RtcApi; |
|||
|
|||
/// 创建实时音视频频道 |
|||
@POST(ApiUrls.createRtcChannel) |
|||
Future<HttpResponse<BaseResponse<RtcChannelData>>> createRtcChannel(); |
|||
} |
|||
|
|||
@ -0,0 +1,81 @@ |
|||
// GENERATED CODE - DO NOT MODIFY BY HAND |
|||
|
|||
part of 'rtc_api.dart'; |
|||
|
|||
// dart format off |
|||
|
|||
// ************************************************************************** |
|||
// RetrofitGenerator |
|||
// ************************************************************************** |
|||
|
|||
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations,unused_element_parameter,avoid_unused_constructor_parameters,unreachable_from_main |
|||
|
|||
class _RtcApi implements RtcApi { |
|||
_RtcApi(this._dio, {this.baseUrl, this.errorLogger}); |
|||
|
|||
final Dio _dio; |
|||
|
|||
String? baseUrl; |
|||
|
|||
final ParseErrorLogger? errorLogger; |
|||
|
|||
@override |
|||
Future<HttpResponse<BaseResponse<RtcChannelData>>> createRtcChannel() async { |
|||
final _extra = <String, dynamic>{}; |
|||
final queryParameters = <String, dynamic>{}; |
|||
final _headers = <String, dynamic>{}; |
|||
const Map<String, dynamic>? _data = null; |
|||
final _options = _setStreamType<HttpResponse<BaseResponse<RtcChannelData>>>( |
|||
Options(method: 'POST', headers: _headers, extra: _extra) |
|||
.compose( |
|||
_dio.options, |
|||
'dating-agency-chat-audio/user/create/rtc-channel', |
|||
queryParameters: queryParameters, |
|||
data: _data, |
|||
) |
|||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), |
|||
); |
|||
final _result = await _dio.fetch<Map<String, dynamic>>(_options); |
|||
late BaseResponse<RtcChannelData> _value; |
|||
try { |
|||
_value = BaseResponse<RtcChannelData>.fromJson( |
|||
_result.data!, |
|||
(json) => RtcChannelData.fromJson(json as Map<String, dynamic>), |
|||
); |
|||
} on Object catch (e, s) { |
|||
errorLogger?.logError(e, s, _options); |
|||
rethrow; |
|||
} |
|||
final httpResponse = HttpResponse(_value, _result); |
|||
return httpResponse; |
|||
} |
|||
|
|||
RequestOptions _setStreamType<T>(RequestOptions requestOptions) { |
|||
if (T != dynamic && |
|||
!(requestOptions.responseType == ResponseType.bytes || |
|||
requestOptions.responseType == ResponseType.stream)) { |
|||
if (T == String) { |
|||
requestOptions.responseType = ResponseType.plain; |
|||
} else { |
|||
requestOptions.responseType = ResponseType.json; |
|||
} |
|||
} |
|||
return requestOptions; |
|||
} |
|||
|
|||
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) { |
|||
if (baseUrl == null || baseUrl.trim().isEmpty) { |
|||
return dioBaseUrl; |
|||
} |
|||
|
|||
final url = Uri.parse(baseUrl); |
|||
|
|||
if (url.isAbsolute) { |
|||
return url.toString(); |
|||
} |
|||
|
|||
return Uri.parse(dioBaseUrl).resolveUri(url).toString(); |
|||
} |
|||
} |
|||
|
|||
// dart format on |
|||
Write
Preview
Loading…
Cancel
Save