Added video player page
This commit is contained in:
parent
ca0feb8c8d
commit
00830f8a05
6 changed files with 156 additions and 63 deletions
|
@ -3,6 +3,7 @@
|
|||
<application
|
||||
android:label="Immich"
|
||||
android:name="${applicationName}"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
|
|
|
@ -51,56 +51,3 @@ class ImageGrid extends ConsumerWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
// class VideoThumbnailPlayer extends StatefulWidget {
|
||||
// ImmichAsset videoAsset;
|
||||
|
||||
// VideoThumbnailPlayer({Key? key, required this.videoAsset}) : super(key: key);
|
||||
|
||||
// @override
|
||||
// State<VideoThumbnailPlayer> createState() => _VideoThumbnailPlayerState();
|
||||
// }
|
||||
|
||||
// class _VideoThumbnailPlayerState extends State<VideoThumbnailPlayer> {
|
||||
// late VideoPlayerController videoPlayerController;
|
||||
// ChewieController? chewieController;
|
||||
|
||||
// @override
|
||||
// void initState() {
|
||||
// super.initState();
|
||||
// initializePlayer();
|
||||
// }
|
||||
|
||||
// Future<void> initializePlayer() async {
|
||||
// videoPlayerController =
|
||||
// VideoPlayerController.network('https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4');
|
||||
|
||||
// await Future.wait([
|
||||
// videoPlayerController.initialize(),
|
||||
// ]);
|
||||
// _createChewieController();
|
||||
// setState(() {});
|
||||
// }
|
||||
|
||||
// _createChewieController() {
|
||||
// chewieController = ChewieController(
|
||||
// showControlsOnInitialize: false,
|
||||
// videoPlayerController: videoPlayerController,
|
||||
// autoPlay: true,
|
||||
// looping: true,
|
||||
// );
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return chewieController != null && chewieController!.videoPlayerController.value.isInitialized
|
||||
// ? SizedBox(
|
||||
// height: 300,
|
||||
// width: 300,
|
||||
// child: Chewie(
|
||||
// controller: chewieController!,
|
||||
// ),
|
||||
// )
|
||||
// : const Text("Loading Video");
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -21,14 +21,24 @@ class ThumbnailImage extends HookWidget {
|
|||
'${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=true';
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
AutoRouter.of(context).push(
|
||||
ImageViewerRoute(
|
||||
imageUrl:
|
||||
'${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=false',
|
||||
heroTag: asset.id,
|
||||
thumbnailUrl: thumbnailRequestUrl,
|
||||
),
|
||||
);
|
||||
if (asset.type == 'IMAGE') {
|
||||
AutoRouter.of(context).push(
|
||||
ImageViewerRoute(
|
||||
imageUrl:
|
||||
'${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=false',
|
||||
heroTag: asset.id,
|
||||
thumbnailUrl: thumbnailRequestUrl,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
debugPrint("Navigate to video player");
|
||||
|
||||
AutoRouter.of(context).push(
|
||||
VideoViewerRoute(
|
||||
videoUrl: '${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}',
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
onLongPress: () {},
|
||||
child: Hero(
|
||||
|
@ -37,7 +47,7 @@ class ThumbnailImage extends HookWidget {
|
|||
cacheKey: "${asset.id}-${cacheKey.value}",
|
||||
width: 300,
|
||||
height: 300,
|
||||
memCacheHeight: 250,
|
||||
memCacheHeight: asset.type == 'IMAGE' ? 250 : 500,
|
||||
fit: BoxFit.cover,
|
||||
imageUrl: thumbnailRequestUrl,
|
||||
httpHeaders: {"Authorization": "Bearer ${box.get(accessTokenKey)}"},
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:immich_mobile/modules/home/views/home_page.dart';
|
|||
import 'package:immich_mobile/routing/auth_guard.dart';
|
||||
import 'package:immich_mobile/shared/views/backup_controller_page.dart';
|
||||
import 'package:immich_mobile/shared/views/image_viewer_page.dart';
|
||||
import 'package:immich_mobile/shared/views/video_viewer_page.dart';
|
||||
|
||||
part 'router.gr.dart';
|
||||
|
||||
|
@ -15,6 +16,7 @@ part 'router.gr.dart';
|
|||
AutoRoute(page: HomePage, guards: [AuthGuard]),
|
||||
AutoRoute(page: BackupControllerPage, guards: [AuthGuard]),
|
||||
AutoRoute(page: ImageViewerPage, guards: [AuthGuard]),
|
||||
AutoRoute(page: VideoViewerPage, guards: [AuthGuard]),
|
||||
],
|
||||
)
|
||||
class AppRouter extends _$AppRouter {
|
||||
|
|
|
@ -42,6 +42,12 @@ class _$AppRouter extends RootStackRouter {
|
|||
imageUrl: args.imageUrl,
|
||||
heroTag: args.heroTag,
|
||||
thumbnailUrl: args.thumbnailUrl));
|
||||
},
|
||||
VideoViewerRoute.name: (routeData) {
|
||||
final args = routeData.argsAs<VideoViewerRouteArgs>();
|
||||
return MaterialPageX<dynamic>(
|
||||
routeData: routeData,
|
||||
child: VideoViewerPage(key: args.key, videoUrl: args.videoUrl));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -52,7 +58,9 @@ class _$AppRouter extends RootStackRouter {
|
|||
RouteConfig(BackupControllerRoute.name,
|
||||
path: '/backup-controller-page', guards: [authGuard]),
|
||||
RouteConfig(ImageViewerRoute.name,
|
||||
path: '/image-viewer-page', guards: [authGuard])
|
||||
path: '/image-viewer-page', guards: [authGuard]),
|
||||
RouteConfig(VideoViewerRoute.name,
|
||||
path: '/video-viewer-page', guards: [authGuard])
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -120,3 +128,27 @@ class ImageViewerRouteArgs {
|
|||
return 'ImageViewerRouteArgs{key: $key, imageUrl: $imageUrl, heroTag: $heroTag, thumbnailUrl: $thumbnailUrl}';
|
||||
}
|
||||
}
|
||||
|
||||
/// generated route for
|
||||
/// [VideoViewerPage]
|
||||
class VideoViewerRoute extends PageRouteInfo<VideoViewerRouteArgs> {
|
||||
VideoViewerRoute({Key? key, required String videoUrl})
|
||||
: super(VideoViewerRoute.name,
|
||||
path: '/video-viewer-page',
|
||||
args: VideoViewerRouteArgs(key: key, videoUrl: videoUrl));
|
||||
|
||||
static const String name = 'VideoViewerRoute';
|
||||
}
|
||||
|
||||
class VideoViewerRouteArgs {
|
||||
const VideoViewerRouteArgs({this.key, required this.videoUrl});
|
||||
|
||||
final Key? key;
|
||||
|
||||
final String videoUrl;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'VideoViewerRouteArgs{key: $key, videoUrl: $videoUrl}';
|
||||
}
|
||||
}
|
||||
|
|
101
mobile/lib/shared/views/video_viewer_page.dart
Normal file
101
mobile/lib/shared/views/video_viewer_page.dart
Normal file
|
@ -0,0 +1,101 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:immich_mobile/constants/hive_box.dart';
|
||||
import 'package:chewie/chewie.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
class VideoViewerPage extends StatelessWidget {
|
||||
final String videoUrl;
|
||||
|
||||
const VideoViewerPage({Key? key, required this.videoUrl}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String jwtToken = Hive.box(userInfoBox).get(accessTokenKey);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.black,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.black,
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
AutoRouter.of(context).pop();
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back_ios)),
|
||||
),
|
||||
body: Center(
|
||||
child: VideoThumbnailPlayer(
|
||||
url: videoUrl,
|
||||
jwtToken: jwtToken,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class VideoThumbnailPlayer extends StatefulWidget {
|
||||
final String url;
|
||||
final String? jwtToken;
|
||||
|
||||
const VideoThumbnailPlayer({Key? key, required this.url, this.jwtToken}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<VideoThumbnailPlayer> createState() => _VideoThumbnailPlayerState();
|
||||
}
|
||||
|
||||
class _VideoThumbnailPlayerState extends State<VideoThumbnailPlayer> {
|
||||
late VideoPlayerController videoPlayerController;
|
||||
ChewieController? chewieController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initializePlayer();
|
||||
}
|
||||
|
||||
Future<void> initializePlayer() async {
|
||||
videoPlayerController =
|
||||
VideoPlayerController.network(widget.url, httpHeaders: {"Authorization": "Bearer ${widget.jwtToken}"});
|
||||
|
||||
await Future.wait([
|
||||
videoPlayerController.initialize(),
|
||||
]);
|
||||
_createChewieController();
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
_createChewieController() {
|
||||
chewieController = ChewieController(
|
||||
showOptions: true,
|
||||
showControlsOnInitialize: false,
|
||||
videoPlayerController: videoPlayerController,
|
||||
autoPlay: true,
|
||||
autoInitialize: false,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
videoPlayerController.pause();
|
||||
videoPlayerController.dispose();
|
||||
chewieController!.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return chewieController != null && chewieController!.videoPlayerController.value.isInitialized
|
||||
? SizedBox(
|
||||
child: Chewie(
|
||||
controller: chewieController!,
|
||||
),
|
||||
)
|
||||
: const SizedBox(
|
||||
width: 75,
|
||||
height: 75,
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
));
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue