Fix rotate logic & add detail expansion on overlay

This commit is contained in:
tommyxchow 2021-12-26 03:19:08 -05:00
parent 89b54ff08e
commit 0798fbb4ea
4 changed files with 179 additions and 100 deletions

View file

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:frosty/core/settings/settings.dart';
@ -13,6 +15,8 @@ class VideoOverlay extends StatelessWidget {
@override
Widget build(BuildContext context) {
final portrait = MediaQuery.of(context).orientation == Orientation.portrait;
return GestureDetector(
onTap: videoStore.handleVideoTap,
child: SizedBox.expand(
@ -31,13 +35,14 @@ class VideoOverlay extends StatelessWidget {
children: [
Row(
children: [
IconButton(
icon: Icon(
Icons.adaptive.arrow_back,
color: const Color(0xFFFFFFFF),
if (portrait)
IconButton(
icon: Icon(
Icons.adaptive.arrow_back,
color: const Color(0xFFFFFFFF),
),
onPressed: () => Navigator.of(context).pop(),
),
onPressed: () => Navigator.of(context).pop(),
),
const Spacer(),
IconButton(
icon: const Icon(
@ -58,45 +63,64 @@ class VideoOverlay extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: videoStore.streamInfo != null
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
videoStore.streamInfo!.userName,
style: const TextStyle(
color: Color(0xFFFFFFFF),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 5.0),
Text(
videoStore.streamInfo!.title,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 5.0),
Text(
'${videoStore.streamInfo?.gameName} for ${NumberFormat().format(videoStore.streamInfo?.viewerCount)} viewers',
style: const TextStyle(
color: Color(0xFFFFFFFF),
),
),
],
)
: null,
child: GestureDetector(
onTap: videoStore.handleExpand,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: videoStore.streamInfo != null
? AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: videoStore.expandInfo
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
videoStore.streamInfo!.userName,
style: const TextStyle(
color: Color(0xFFFFFFFF),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 5.0),
Text(
videoStore.streamInfo!.title,
maxLines: portrait ? 2 : 4,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 5.0),
Text(
'${videoStore.streamInfo?.gameName} for ${NumberFormat().format(videoStore.streamInfo?.viewerCount)} viewers',
style: const TextStyle(
color: Color(0xFFFFFFFF),
),
),
],
)
: Align(
alignment: Alignment.bottomLeft,
child: Text(
videoStore.streamInfo!.userName,
style: const TextStyle(
color: Color(0xFFFFFFFF),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
: null,
),
),
),
IconButton(
icon: const Icon(
Icons.picture_in_picture_alt_rounded,
color: Color(0xFFFFFFFF),
if (Platform.isIOS)
IconButton(
icon: const Icon(
Icons.picture_in_picture_alt_rounded,
color: Color(0xFFFFFFFF),
),
onPressed: videoStore.requestPictureInPicture,
),
onPressed: videoStore.requestPictureInPicture,
),
IconButton(
icon: const Icon(
Icons.fullscreen,

View file

@ -21,6 +21,9 @@ abstract class _VideoStoreBase with Store {
@readonly
var _paused = false;
@readonly
var _expandInfo = false;
@readonly
StreamTwitch? _streamInfo;
@ -68,6 +71,13 @@ abstract class _VideoStoreBase with Store {
}
}
@action
void handleExpand() {
overlayTimer.cancel();
_expandInfo = !_expandInfo;
overlayTimer = Timer(const Duration(seconds: 5), () => _menuVisible = false);
}
void initVideo() {
controller?.runJavascript('document.getElementsByTagName("button")[0].click();');
controller?.runJavascript('document.getElementsByTagName("video")[0].muted = false;');

View file

@ -43,6 +43,23 @@ mixin _$VideoStore on _VideoStoreBase, Store {
});
}
final _$_expandInfoAtom = Atom(name: '_VideoStoreBase._expandInfo');
bool get expandInfo {
_$_expandInfoAtom.reportRead();
return super._expandInfo;
}
@override
bool get _expandInfo => expandInfo;
@override
set _expandInfo(bool value) {
_$_expandInfoAtom.reportWrite(value, super._expandInfo, () {
super._expandInfo = value;
});
}
final _$_streamInfoAtom = Atom(name: '_VideoStoreBase._streamInfo');
StreamTwitch? get streamInfo {
@ -93,6 +110,17 @@ mixin _$VideoStore on _VideoStoreBase, Store {
}
}
@override
void handleExpand() {
final _$actionInfo = _$_VideoStoreBaseActionController.startAction(
name: '_VideoStoreBase.handleExpand');
try {
return super.handleExpand();
} finally {
_$_VideoStoreBaseActionController.endAction(_$actionInfo);
}
}
@override
String toString() {
return '''

View file

@ -42,72 +42,89 @@ class VideoChat extends StatelessWidget {
),
);
return Scaffold(
body: OrientationBuilder(builder: (context, orientation) {
if (orientation == Orientation.landscape) {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
return Observer(
final appBar = AppBar(
title: Text(
userName,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () => showModalBottomSheet(
context: context,
builder: (context) {
if (context.read<SettingsStore>().fullScreen) {
return Stack(
children: [
Visibility(
visible: false,
maintainState: true,
child: chat,
),
Center(child: video),
],
);
}
return Row(
children: [
Flexible(
flex: 2,
child: video,
),
Flexible(
flex: 1,
child: chat,
),
],
);
return Settings(settingsStore: context.read<SettingsStore>());
},
);
}
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.bottom, SystemUiOverlay.top]);
return Column(
children: [
Observer(
),
),
],
);
return Scaffold(
body: OrientationBuilder(
builder: (context, orientation) {
if (orientation == Orientation.landscape) {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
return Observer(
builder: (context) {
if (context.read<SettingsStore>().videoEnabled) {
return video;
}
return AppBar(
title: Text(
userName,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () => showModalBottomSheet(
context: context,
builder: (context) {
return Settings(settingsStore: context.read<SettingsStore>());
},
),
return WillPopScope(
onWillPop: () async => false,
child: Observer(
builder: (context) => context.read<SettingsStore>().fullScreen
? Stack(
children: [
Visibility(
visible: false,
maintainState: true,
child: chat,
),
Center(child: video),
],
)
: Row(
children: [
Flexible(
flex: 2,
child: video,
),
Flexible(
flex: 1,
child: chat,
),
],
),
),
);
}
return Column(
children: [
appBar,
Expanded(child: chat),
],
);
},
),
Expanded(
child: chat,
),
],
);
}),
);
}
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.bottom, SystemUiOverlay.top]);
return Column(
children: [
Observer(
builder: (context) {
if (context.read<SettingsStore>().videoEnabled) {
return video;
}
return appBar;
},
),
Expanded(
child: chat,
),
],
);
},
),
);
}
}