Files
.github
.vscode
android
assets
buildtools
ios
lib
database
models
pods
screens
services
widgets
account
chat
content
alert.native.dart
alert.web.dart
attachment_preview.dart
cloud_file_collection.dart
cloud_file_picker.dart
cloud_files.dart
image.dart
markdown.dart
paging_helper_ext.dart
sheet.dart
video.dart
video.native.dart
video.web.dart
post
realms
tour
alert.dart
app_scaffold.dart
check_in.dart
check_in.g.dart
context_menu.dart
response.dart
firebase_options.dart
main.dart
route.dart
route.gr.dart
linux
macos
web
windows
.gitignore
.metadata
README.md
analysis_options.yaml
build.yaml
devtools_options.yaml
firebase.json
pubspec.lock
pubspec.yaml
App/lib/widgets/content/video.native.dart
2025-05-28 23:21:13 +08:00

92 lines
2.3 KiB
Dart

import 'dart:developer';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:island/pods/network.dart';
import 'package:island/widgets/alert.dart';
import 'package:media_kit/media_kit.dart';
import 'package:media_kit_video/media_kit_video.dart';
class UniversalVideo extends ConsumerStatefulWidget {
final String uri;
final double aspectRatio;
const UniversalVideo({
super.key,
required this.uri,
this.aspectRatio = 16 / 9,
});
@override
ConsumerState<UniversalVideo> createState() => _UniversalVideoState();
}
class _UniversalVideoState extends ConsumerState<UniversalVideo> {
Player? _player;
VideoController? _videoController;
void _openVideo() async {
final url = widget.uri;
MediaKit.ensureInitialized();
_player = Player();
_videoController = VideoController(_player!);
String? uri;
final inCacheInfo = await DefaultCacheManager().getFileFromCache(url);
if (inCacheInfo == null) {
log('[MediaPlayer] Miss cache: $url');
final token = await getToken(ref.watch(tokenProvider));
final fileStream = DefaultCacheManager().getFileStream(
url,
headers: {'Authorization': 'Bearer $token'},
withProgress: true,
);
await for (var fileInfo in fileStream) {
if (fileInfo is FileInfo) {
uri = fileInfo.file.path;
break;
}
}
} else {
uri = inCacheInfo.file.path;
log('[MediaPlayer] Hit cache: $url');
}
if (uri == null) {
showErrorAlert('Failed to open media... $url');
return;
}
_player!.open(Media(uri), play: false);
}
@override
void initState() {
super.initState();
_openVideo();
}
@override
void dispose() {
super.dispose();
_player?.dispose();
}
@override
Widget build(BuildContext context) {
if (_videoController == null) {
return Center(child: CircularProgressIndicator());
}
return Video(
controller: _videoController!,
aspectRatio: widget.aspectRatio,
controls:
!kIsWeb && (Platform.isAndroid || Platform.isIOS)
? MaterialVideoControls
: MaterialDesktopVideoControls,
);
}
}