Add bg opacity option to overlay chat (#130)

This commit is contained in:
Tommy Chow 2022-06-04 01:36:09 -04:00
parent 07c260def5
commit 2b6e683cae
6 changed files with 178 additions and 135 deletions

View file

@ -75,86 +75,86 @@ void main() async {
// Navigator key for sleep timer. Allows navigation popping without context.
final navigatorKey = GlobalKey<NavigatorState>();
const gray = Color.fromRGBO(22, 22, 22, 1.0);
const purple = Color(0xff9146ff);
final lightTheme = ThemeData(
canvasColor: Colors.white,
splashFactory: Platform.isIOS ? NoSplash.splashFactory : null,
fontFamily: 'Inter',
appBarTheme: const AppBarTheme(
color: Colors.white,
elevation: 0.0,
titleTextStyle: TextStyle(
fontFamily: 'Inter',
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black,
),
iconTheme: IconThemeData(color: Colors.black),
),
colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.deepPurple,
accentColor: purple,
),
toggleableActiveColor: purple,
tabBarTheme: const TabBarTheme(
labelColor: Colors.black,
unselectedLabelColor: Colors.grey,
),
);
final darkTheme = ThemeData(
canvasColor: gray,
brightness: Brightness.dark,
splashFactory: Platform.isIOS ? NoSplash.splashFactory : null,
fontFamily: 'Inter',
appBarTheme: const AppBarTheme(
color: gray,
elevation: 0.0,
titleTextStyle: TextStyle(
fontFamily: 'Inter',
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
bottomNavigationBarTheme: const BottomNavigationBarThemeData(backgroundColor: gray),
colorScheme: ColorScheme.fromSwatch(
brightness: Brightness.dark,
primarySwatch: Colors.deepPurple,
accentColor: purple,
),
dialogBackgroundColor: gray,
toggleableActiveColor: purple,
);
final oledTheme = ThemeData(
canvasColor: Colors.black,
splashFactory: Platform.isIOS ? NoSplash.splashFactory : null,
fontFamily: 'Inter',
appBarTheme: const AppBarTheme(
color: Colors.black,
elevation: 0.0,
titleTextStyle: TextStyle(
fontFamily: 'Inter',
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
colorScheme: ColorScheme.fromSwatch(
brightness: Brightness.dark,
primarySwatch: Colors.deepPurple,
accentColor: purple,
),
dialogBackgroundColor: Colors.black,
toggleableActiveColor: purple,
);
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
const gray = Color.fromRGBO(22, 22, 22, 1.0);
const purple = Color(0xff9146ff);
final lightTheme = ThemeData(
canvasColor: Colors.white,
splashFactory: Platform.isIOS ? NoSplash.splashFactory : null,
fontFamily: 'Inter',
appBarTheme: const AppBarTheme(
color: Colors.white,
elevation: 0.0,
titleTextStyle: TextStyle(
fontFamily: 'Inter',
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black,
),
iconTheme: IconThemeData(color: Colors.black),
),
colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.deepPurple,
accentColor: purple,
),
toggleableActiveColor: purple,
tabBarTheme: const TabBarTheme(
labelColor: Colors.black,
unselectedLabelColor: Colors.grey,
),
);
final darkTheme = ThemeData(
canvasColor: gray,
brightness: Brightness.dark,
splashFactory: Platform.isIOS ? NoSplash.splashFactory : null,
fontFamily: 'Inter',
appBarTheme: const AppBarTheme(
color: gray,
elevation: 0.0,
titleTextStyle: TextStyle(
fontFamily: 'Inter',
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
bottomNavigationBarTheme: const BottomNavigationBarThemeData(backgroundColor: gray),
colorScheme: ColorScheme.fromSwatch(
brightness: Brightness.dark,
primarySwatch: Colors.deepPurple,
accentColor: purple,
),
dialogBackgroundColor: gray,
toggleableActiveColor: purple,
);
final oledTheme = ThemeData(
canvasColor: Colors.black,
splashFactory: Platform.isIOS ? NoSplash.splashFactory : null,
fontFamily: 'Inter',
appBarTheme: const AppBarTheme(
color: Colors.black,
elevation: 0.0,
titleTextStyle: TextStyle(
fontFamily: 'Inter',
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
colorScheme: ColorScheme.fromSwatch(
brightness: Brightness.dark,
primarySwatch: Colors.deepPurple,
accentColor: purple,
),
dialogBackgroundColor: Colors.black,
toggleableActiveColor: purple,
);
return Observer(
builder: (context) {
final settingsStore = context.read<SettingsStore>();

View file

@ -108,8 +108,7 @@ class Chat extends StatelessWidget {
),
),
),
if (chatStore.settings.showBottomBar && (!chatStore.settings.fullScreen || MediaQuery.of(context).orientation == Orientation.portrait))
ChatBottomBar(chatStore: chatStore),
if (chatStore.settings.showBottomBar) ChatBottomBar(chatStore: chatStore),
if (chatStore.assetsStore.showEmoteMenu)
SizedBox(
height: MediaQuery.of(context).size.height / 3,

View file

@ -77,9 +77,9 @@ class _VideoChatState extends State<VideoChat> {
videoStore: _videoStore,
);
final overlay = VideoOverlay(videoStore: _videoStore);
final videoOverlay = VideoOverlay(videoStore: _videoStore);
final video = GestureDetector(
final overlay = GestureDetector(
onLongPress: _videoStore.handleToggleOverlay,
onTap: () {
if (_chatStore.assetsStore.showEmoteMenu) {
@ -93,33 +93,37 @@ class _VideoChatState extends State<VideoChat> {
}
},
child: Observer(
builder: (context) {
if (_videoStore.settingsStore.showOverlay) {
return Stack(
children: [
player,
if (_videoStore.paused || _videoStore.streamInfo == null)
overlay
else
AnimatedOpacity(
opacity: _videoStore.overlayVisible ? 1.0 : 0.0,
duration: const Duration(milliseconds: 200),
child: ColoredBox(
color: const Color.fromRGBO(0, 0, 0, 0.5),
child: IgnorePointer(
ignoring: !_videoStore.overlayVisible,
child: overlay,
),
),
),
],
);
}
return player;
builder: (_) {
if (_videoStore.paused || _videoStore.streamInfo == null) return videoOverlay;
return AnimatedOpacity(
opacity: _videoStore.overlayVisible ? 1.0 : 0.0,
duration: const Duration(milliseconds: 200),
child: ColoredBox(
color: const Color.fromRGBO(0, 0, 0, 0.5),
child: IgnorePointer(
ignoring: !_videoStore.overlayVisible,
child: videoOverlay,
),
),
);
},
),
);
final video = Observer(
builder: (context) {
if (!_videoStore.settingsStore.showOverlay) return player;
return Stack(
children: [
player,
overlay,
],
);
},
);
final chat = Chat(
key: _chatKey,
chatStore: _chatStore,
@ -165,10 +169,24 @@ class _VideoChatState extends State<VideoChat> {
? MediaQuery.of(context).size.width / 2
: MediaQuery.of(context).size.width * _chatStore.settings.landscapeChatWidth,
curve: Curves.ease,
color: _chatStore.settings.fullScreen ? null : Theme.of(context).scaffoldBackgroundColor,
color: _chatStore.settings.fullScreen
? Colors.black.withOpacity(_chatStore.settings.fullScreenChatOverlayOpacity)
: Theme.of(context).scaffoldBackgroundColor,
child: chat,
);
final overlayChat = Visibility(
visible: settingsStore.fullScreenChatOverlay,
maintainState: true,
child: Theme(
data: darkTheme,
child: DefaultTextStyle(
style: DefaultTextStyle.of(context).style.copyWith(color: Colors.white),
child: landscapeChat,
),
),
);
return ColoredBox(
color: settingsStore.showVideo ? Colors.black : Theme.of(context).scaffoldBackgroundColor,
child: SafeArea(
@ -176,38 +194,22 @@ class _VideoChatState extends State<VideoChat> {
child: settingsStore.showVideo
? settingsStore.fullScreen
? Stack(
alignment: settingsStore.landscapeChatLeftSide ? Alignment.topLeft : Alignment.topRight,
children: [
video,
IgnorePointer(
ignoring: _videoStore.overlayVisible,
child: Visibility(
visible: settingsStore.fullScreenChatOverlay,
maintainState: true,
child: DefaultTextStyle(
style: DefaultTextStyle.of(context).style.copyWith(color: Colors.white),
child: landscapeChat,
),
),
),
player,
Row(
children: settingsStore.landscapeChatLeftSide
? [overlayChat, Expanded(child: overlay)]
: [Expanded(child: overlay), overlayChat],
)
],
)
: Row(
children: settingsStore.landscapeChatLeftSide
? [
landscapeChat,
Expanded(child: video),
]
: [
Expanded(child: video),
landscapeChat,
],
? [landscapeChat, Expanded(child: video)]
: [Expanded(child: video), landscapeChat],
)
: Column(
children: [
appBar,
Expanded(child: chat),
],
children: [appBar, Expanded(child: chat)],
),
),
);
@ -224,13 +226,9 @@ class _VideoChatState extends State<VideoChat> {
children: [
Observer(
builder: (_) {
if (settingsStore.showVideo) {
return AspectRatio(
aspectRatio: 16 / 9,
child: video,
);
}
return appBar;
if (!settingsStore.showVideo) return appBar;
return AspectRatio(aspectRatio: 16 / 9, child: video);
},
),
Expanded(child: chat),

View file

@ -86,6 +86,23 @@ class _ChatSettingsState extends State<ChatSettings> {
onChanged: (newValue) => settingsStore.landscapeChatWidth = newValue,
),
),
const SizedBox(height: 15.0),
ListTile(
title: Row(
children: [
const Text('Landscape Chat Overlay Opacity'),
const Spacer(),
Text('${(settingsStore.fullScreenChatOverlayOpacity * 100).toStringAsFixed(0)}%'),
],
),
subtitle: Slider.adaptive(
value: settingsStore.fullScreenChatOverlayOpacity,
min: 0.0,
max: 1.0,
divisions: 10,
onChanged: (newValue) => settingsStore.fullScreenChatOverlayOpacity = newValue,
),
),
const SectionHeader(
'Emotes',
fontSize: 12.0,

View file

@ -93,6 +93,8 @@ abstract class _SettingsStoreBase with Store {
static const defaultChatDelay = 0.0;
static const defaultFullScreenChatOverlayOpacity = 0.5;
@JsonKey(defaultValue: defaultShowBottomBar)
@observable
var showBottomBar = defaultShowBottomBar;
@ -149,6 +151,10 @@ abstract class _SettingsStoreBase with Store {
@observable
var landscapeChatLeftSide = defaultLandscapeChatLeftSide;
@JsonKey(defaultValue: defaultFullScreenChatOverlayOpacity)
@observable
var fullScreenChatOverlayOpacity = defaultFullScreenChatOverlayOpacity;
// * Other settings
static const defaultSendCrashLogs = true;
@ -209,6 +215,7 @@ abstract class _SettingsStoreBase with Store {
landscapeChatWidth = defaultLandscapeChatWidth;
landscapeChatLeftSide = false;
chatDelay = defaultChatDelay;
fullScreenChatOverlayOpacity = defaultFullScreenChatOverlayOpacity;
// * Other settings
sendCrashLogs = defaultSendCrashLogs;

View file

@ -37,6 +37,8 @@ SettingsStore _$SettingsStoreFromJson(Map<String, dynamic> json) =>
..landscapeChatWidth =
(json['landscapeChatWidth'] as num?)?.toDouble() ?? 0.3
..landscapeChatLeftSide = json['landscapeChatLeftSide'] as bool? ?? false
..fullScreenChatOverlayOpacity =
(json['fullScreenChatOverlayOpacity'] as num?)?.toDouble() ?? 0.5
..sendCrashLogs = json['sendCrashLogs'] as bool? ?? true
..fullScreen = json['fullScreen'] as bool? ?? false
..expandInfo = json['expandInfo'] as bool? ?? true
@ -67,6 +69,7 @@ Map<String, dynamic> _$SettingsStoreToJson(SettingsStore instance) =>
'emoteAutocomplete': instance.emoteAutocomplete,
'landscapeChatWidth': instance.landscapeChatWidth,
'landscapeChatLeftSide': instance.landscapeChatLeftSide,
'fullScreenChatOverlayOpacity': instance.fullScreenChatOverlayOpacity,
'sendCrashLogs': instance.sendCrashLogs,
'fullScreen': instance.fullScreen,
'expandInfo': instance.expandInfo,
@ -448,6 +451,24 @@ mixin _$SettingsStore on _SettingsStoreBase, Store {
});
}
late final _$fullScreenChatOverlayOpacityAtom = Atom(
name: '_SettingsStoreBase.fullScreenChatOverlayOpacity',
context: context);
@override
double get fullScreenChatOverlayOpacity {
_$fullScreenChatOverlayOpacityAtom.reportRead();
return super.fullScreenChatOverlayOpacity;
}
@override
set fullScreenChatOverlayOpacity(double value) {
_$fullScreenChatOverlayOpacityAtom
.reportWrite(value, super.fullScreenChatOverlayOpacity, () {
super.fullScreenChatOverlayOpacity = value;
});
}
late final _$sendCrashLogsAtom =
Atom(name: '_SettingsStoreBase.sendCrashLogs', context: context);
@ -568,6 +589,7 @@ emoteScale: ${emoteScale},
emoteAutocomplete: ${emoteAutocomplete},
landscapeChatWidth: ${landscapeChatWidth},
landscapeChatLeftSide: ${landscapeChatLeftSide},
fullScreenChatOverlayOpacity: ${fullScreenChatOverlayOpacity},
sendCrashLogs: ${sendCrashLogs},
fullScreen: ${fullScreen},
expandInfo: ${expandInfo},