Added video player page

This commit is contained in:
Alex Tran 2022-02-05 20:40:04 -06:00
parent ca0feb8c8d
commit 00830f8a05
6 changed files with 156 additions and 63 deletions

View file

@ -3,6 +3,7 @@
<application
android:label="Immich"
android:name="${applicationName}"
android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"

View file

@ -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");
// }
// }

View file

@ -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)}"},

View file

@ -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 {

View file

@ -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}';
}
}

View 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,
));
}
}