add native device orientation support, auto-fill safe area depending on orientation
This commit is contained in:
parent
57671967c9
commit
50c9bb2387
7 changed files with 126 additions and 105 deletions
|
|
@ -168,6 +168,8 @@ PODS:
|
|||
- nanopb/encode (= 3.30910.0)
|
||||
- nanopb/decode (3.30910.0)
|
||||
- nanopb/encode (3.30910.0)
|
||||
- native_device_orientation (0.0.1):
|
||||
- Flutter
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
|
|
@ -202,6 +204,7 @@ DEPENDENCIES:
|
|||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||
- native_device_orientation (from `.symlinks/plugins/native_device_orientation/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
|
|
@ -256,6 +259,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
||||
in_app_review:
|
||||
:path: ".symlinks/plugins/in_app_review/ios"
|
||||
native_device_orientation:
|
||||
:path: ".symlinks/plugins/native_device_orientation/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
|
|
@ -301,6 +306,7 @@ SPEC CHECKSUMS:
|
|||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||
in_app_review: 436034b18594851a7328d7f1c2ed5ec235b79cfc
|
||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||
native_device_orientation: 42487b19c552fb5a6a2b51e61b93366f628113df
|
||||
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
|
||||
path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ import 'package:frosty/screens/channel/video/stream_info_bar.dart';
|
|||
import 'package:frosty/screens/channel/video/video.dart';
|
||||
import 'package:frosty/screens/channel/video/video_overlay.dart';
|
||||
import 'package:frosty/screens/channel/video/video_store.dart';
|
||||
import 'package:frosty/screens/settings/stores/settings_store.dart';
|
||||
import 'package:frosty/theme.dart';
|
||||
import 'package:frosty/utils/context_extensions.dart';
|
||||
import 'package:frosty/widgets/blurred_container.dart';
|
||||
import 'package:frosty/widgets/draggable_divider.dart';
|
||||
import 'package:frosty/widgets/frosty_notification.dart';
|
||||
import 'package:native_device_orientation/native_device_orientation.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:simple_pip_mode/actions/pip_actions_layout.dart';
|
||||
import 'package:simple_pip_mode/pip_widget.dart';
|
||||
|
|
@ -540,19 +540,38 @@ class _VideoChatState extends State<VideoChat>
|
|||
),
|
||||
],
|
||||
)
|
||||
: SafeArea(
|
||||
bottom: false,
|
||||
left:
|
||||
settingsStore.landscapeCutout !=
|
||||
LandscapeCutoutType.left &&
|
||||
settingsStore.landscapeCutout !=
|
||||
LandscapeCutoutType.both,
|
||||
right:
|
||||
settingsStore.landscapeCutout !=
|
||||
LandscapeCutoutType.right &&
|
||||
settingsStore.landscapeCutout !=
|
||||
LandscapeCutoutType.both,
|
||||
child: LayoutBuilder(
|
||||
: NativeDeviceOrientationReader(
|
||||
useSensor: true,
|
||||
builder: (context) {
|
||||
final orientation =
|
||||
NativeDeviceOrientationReader.orientation(
|
||||
context,
|
||||
);
|
||||
|
||||
// Determine which side to fill based on setting
|
||||
final bool fillLeft;
|
||||
final bool fillRight;
|
||||
|
||||
if (settingsStore.landscapeFillAllEdges) {
|
||||
fillLeft = true;
|
||||
fillRight = true;
|
||||
} else {
|
||||
// Auto mode: fill the physical bottom side (opposite of notch)
|
||||
// landscapeLeft = notch on left → fill right
|
||||
// landscapeRight = notch on right → fill left
|
||||
fillLeft =
|
||||
orientation ==
|
||||
NativeDeviceOrientation.landscapeRight;
|
||||
fillRight =
|
||||
orientation ==
|
||||
NativeDeviceOrientation.landscapeLeft;
|
||||
}
|
||||
|
||||
return SafeArea(
|
||||
bottom: false,
|
||||
left: !fillLeft,
|
||||
right: !fillRight,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final availableWidth = constraints.maxWidth;
|
||||
final chatWidth = _chatStore.expandChat
|
||||
|
|
@ -646,6 +665,8 @@ class _VideoChatState extends State<VideoChat>
|
|||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: SafeArea(child: chat),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -232,17 +232,14 @@ class _ChatSettingsState extends State<ChatSettings> {
|
|||
onChanged: (newValue) =>
|
||||
settingsStore.landscapeForceVerticalChat = newValue,
|
||||
),
|
||||
SettingsListSelect(
|
||||
title: 'Fill notch side',
|
||||
subtitle:
|
||||
'Overrides and fills the available space in devices with a display notch.',
|
||||
selectedOption:
|
||||
landscapeCutoutNames[settingsStore.landscapeCutout.index],
|
||||
options: landscapeCutoutNames,
|
||||
onChanged: (newValue) => settingsStore.landscapeCutout =
|
||||
LandscapeCutoutType.values[landscapeCutoutNames.indexOf(
|
||||
newValue,
|
||||
)],
|
||||
SettingsListSwitch(
|
||||
title: 'Fill all edges',
|
||||
subtitle: const Text(
|
||||
'Fills both edges instead of just the bottom edge.',
|
||||
),
|
||||
value: settingsStore.landscapeFillAllEdges,
|
||||
onChanged: (newValue) =>
|
||||
settingsStore.landscapeFillAllEdges = newValue,
|
||||
),
|
||||
SettingsListSlider(
|
||||
title: 'Chat overlay opacity',
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ abstract class _SettingsStoreBase with Store {
|
|||
// Landscape mode defaults
|
||||
static const defaultLandscapeChatLeftSide = false;
|
||||
static const defaultLandscapeForceVerticalChat = false;
|
||||
static const defaultLandscapeCutout = LandscapeCutoutType.none;
|
||||
static const defaultLandscapeFillAllEdges = false;
|
||||
static const defaultChatWidth = 0.2;
|
||||
static const defaultFullScreenChatOverlayOpacity = 0.5;
|
||||
|
||||
|
|
@ -231,9 +231,9 @@ abstract class _SettingsStoreBase with Store {
|
|||
@observable
|
||||
var landscapeForceVerticalChat = defaultLandscapeForceVerticalChat;
|
||||
|
||||
@JsonKey(defaultValue: defaultLandscapeCutout)
|
||||
@JsonKey(defaultValue: defaultLandscapeFillAllEdges)
|
||||
@observable
|
||||
var landscapeCutout = defaultLandscapeCutout;
|
||||
var landscapeFillAllEdges = defaultLandscapeFillAllEdges;
|
||||
|
||||
@JsonKey(defaultValue: defaultChatWidth)
|
||||
@observable
|
||||
|
|
@ -321,7 +321,7 @@ abstract class _SettingsStoreBase with Store {
|
|||
|
||||
landscapeChatLeftSide = defaultLandscapeChatLeftSide;
|
||||
landscapeForceVerticalChat = defaultLandscapeForceVerticalChat;
|
||||
landscapeCutout = defaultLandscapeCutout;
|
||||
landscapeFillAllEdges = defaultLandscapeFillAllEdges;
|
||||
chatWidth = defaultChatWidth;
|
||||
fullScreenChatOverlayOpacity = defaultFullScreenChatOverlayOpacity;
|
||||
|
||||
|
|
@ -398,6 +398,3 @@ const timestampNames = ['Disabled', '12-hour', '24-hour'];
|
|||
|
||||
enum TimestampType { disabled, twelve, twentyFour }
|
||||
|
||||
const landscapeCutoutNames = ['None', 'Left', 'Right', 'Both'];
|
||||
|
||||
enum LandscapeCutoutType { none, left, right, both }
|
||||
|
|
|
|||
|
|
@ -49,12 +49,7 @@ SettingsStore _$SettingsStoreFromJson(
|
|||
..landscapeChatLeftSide = json['landscapeChatLeftSide'] as bool? ?? false
|
||||
..landscapeForceVerticalChat =
|
||||
json['landscapeForceVerticalChat'] as bool? ?? false
|
||||
..landscapeCutout =
|
||||
$enumDecodeNullable(
|
||||
_$LandscapeCutoutTypeEnumMap,
|
||||
json['landscapeCutout'],
|
||||
) ??
|
||||
LandscapeCutoutType.none
|
||||
..landscapeFillAllEdges = json['landscapeFillAllEdges'] as bool? ?? false
|
||||
..chatWidth = (json['chatWidth'] as num?)?.toDouble() ?? 0.2
|
||||
..fullScreenChatOverlayOpacity =
|
||||
(json['fullScreenChatOverlayOpacity'] as num?)?.toDouble() ?? 0.5
|
||||
|
|
@ -89,56 +84,55 @@ SettingsStore _$SettingsStoreFromJson(
|
|||
.toList() ??
|
||||
[];
|
||||
|
||||
Map<String, dynamic> _$SettingsStoreToJson(
|
||||
SettingsStore instance,
|
||||
) => <String, dynamic>{
|
||||
'themeType': _$ThemeTypeEnumMap[instance.themeType]!,
|
||||
'accentColor': instance.accentColor,
|
||||
'showThumbnails': instance.showThumbnails,
|
||||
'largeStreamCard': instance.largeStreamCard,
|
||||
'launchUrlExternal': instance.launchUrlExternal,
|
||||
'showVideo': instance.showVideo,
|
||||
'defaultToHighestQuality': instance.defaultToHighestQuality,
|
||||
'useTextureRendering': instance.useTextureRendering,
|
||||
'showOverlay': instance.showOverlay,
|
||||
'toggleableOverlay': instance.toggleableOverlay,
|
||||
'showLatency': instance.showLatency,
|
||||
'badgeScale': instance.badgeScale,
|
||||
'emoteScale': instance.emoteScale,
|
||||
'messageScale': instance.messageScale,
|
||||
'messageSpacing': instance.messageSpacing,
|
||||
'fontSize': instance.fontSize,
|
||||
'showDeletedMessages': instance.showDeletedMessages,
|
||||
'showChatMessageDividers': instance.showChatMessageDividers,
|
||||
'timestampType': _$TimestampTypeEnumMap[instance.timestampType]!,
|
||||
'autoSyncChatDelay': instance.autoSyncChatDelay,
|
||||
'chatDelay': instance.chatDelay,
|
||||
'highlightFirstTimeChatter': instance.highlightFirstTimeChatter,
|
||||
'showUserNotices': instance.showUserNotices,
|
||||
'emoteMenuButtonOnLeft': instance.emoteMenuButtonOnLeft,
|
||||
'landscapeChatLeftSide': instance.landscapeChatLeftSide,
|
||||
'landscapeForceVerticalChat': instance.landscapeForceVerticalChat,
|
||||
'landscapeCutout': _$LandscapeCutoutTypeEnumMap[instance.landscapeCutout]!,
|
||||
'chatWidth': instance.chatWidth,
|
||||
'fullScreenChatOverlayOpacity': instance.fullScreenChatOverlayOpacity,
|
||||
'autocomplete': instance.autocomplete,
|
||||
'showTwitchEmotes': instance.showTwitchEmotes,
|
||||
'showTwitchBadges': instance.showTwitchBadges,
|
||||
'show7TVEmotes': instance.show7TVEmotes,
|
||||
'showBTTVEmotes': instance.showBTTVEmotes,
|
||||
'showBTTVBadges': instance.showBTTVBadges,
|
||||
'showFFZEmotes': instance.showFFZEmotes,
|
||||
'showFFZBadges': instance.showFFZBadges,
|
||||
'showRecentMessages': instance.showRecentMessages,
|
||||
'persistChatTabs': instance.persistChatTabs,
|
||||
'secondaryTabs': instance.secondaryTabs,
|
||||
'mutedWords': instance.mutedWords,
|
||||
'matchWholeWord': instance.matchWholeWord,
|
||||
'shareCrashLogsAndAnalytics': instance.shareCrashLogsAndAnalytics,
|
||||
'fullScreen': instance.fullScreen,
|
||||
'fullScreenChatOverlay': instance.fullScreenChatOverlay,
|
||||
'pinnedChannelIds': instance.pinnedChannelIds,
|
||||
};
|
||||
Map<String, dynamic> _$SettingsStoreToJson(SettingsStore instance) =>
|
||||
<String, dynamic>{
|
||||
'themeType': _$ThemeTypeEnumMap[instance.themeType]!,
|
||||
'accentColor': instance.accentColor,
|
||||
'showThumbnails': instance.showThumbnails,
|
||||
'largeStreamCard': instance.largeStreamCard,
|
||||
'launchUrlExternal': instance.launchUrlExternal,
|
||||
'showVideo': instance.showVideo,
|
||||
'defaultToHighestQuality': instance.defaultToHighestQuality,
|
||||
'useTextureRendering': instance.useTextureRendering,
|
||||
'showOverlay': instance.showOverlay,
|
||||
'toggleableOverlay': instance.toggleableOverlay,
|
||||
'showLatency': instance.showLatency,
|
||||
'badgeScale': instance.badgeScale,
|
||||
'emoteScale': instance.emoteScale,
|
||||
'messageScale': instance.messageScale,
|
||||
'messageSpacing': instance.messageSpacing,
|
||||
'fontSize': instance.fontSize,
|
||||
'showDeletedMessages': instance.showDeletedMessages,
|
||||
'showChatMessageDividers': instance.showChatMessageDividers,
|
||||
'timestampType': _$TimestampTypeEnumMap[instance.timestampType]!,
|
||||
'autoSyncChatDelay': instance.autoSyncChatDelay,
|
||||
'chatDelay': instance.chatDelay,
|
||||
'highlightFirstTimeChatter': instance.highlightFirstTimeChatter,
|
||||
'showUserNotices': instance.showUserNotices,
|
||||
'emoteMenuButtonOnLeft': instance.emoteMenuButtonOnLeft,
|
||||
'landscapeChatLeftSide': instance.landscapeChatLeftSide,
|
||||
'landscapeForceVerticalChat': instance.landscapeForceVerticalChat,
|
||||
'landscapeFillAllEdges': instance.landscapeFillAllEdges,
|
||||
'chatWidth': instance.chatWidth,
|
||||
'fullScreenChatOverlayOpacity': instance.fullScreenChatOverlayOpacity,
|
||||
'autocomplete': instance.autocomplete,
|
||||
'showTwitchEmotes': instance.showTwitchEmotes,
|
||||
'showTwitchBadges': instance.showTwitchBadges,
|
||||
'show7TVEmotes': instance.show7TVEmotes,
|
||||
'showBTTVEmotes': instance.showBTTVEmotes,
|
||||
'showBTTVBadges': instance.showBTTVBadges,
|
||||
'showFFZEmotes': instance.showFFZEmotes,
|
||||
'showFFZBadges': instance.showFFZBadges,
|
||||
'showRecentMessages': instance.showRecentMessages,
|
||||
'persistChatTabs': instance.persistChatTabs,
|
||||
'secondaryTabs': instance.secondaryTabs,
|
||||
'mutedWords': instance.mutedWords,
|
||||
'matchWholeWord': instance.matchWholeWord,
|
||||
'shareCrashLogsAndAnalytics': instance.shareCrashLogsAndAnalytics,
|
||||
'fullScreen': instance.fullScreen,
|
||||
'fullScreenChatOverlay': instance.fullScreenChatOverlay,
|
||||
'pinnedChannelIds': instance.pinnedChannelIds,
|
||||
};
|
||||
|
||||
const _$ThemeTypeEnumMap = {
|
||||
ThemeType.system: 'system',
|
||||
|
|
@ -152,13 +146,6 @@ const _$TimestampTypeEnumMap = {
|
|||
TimestampType.twentyFour: 'twentyFour',
|
||||
};
|
||||
|
||||
const _$LandscapeCutoutTypeEnumMap = {
|
||||
LandscapeCutoutType.none: 'none',
|
||||
LandscapeCutoutType.left: 'left',
|
||||
LandscapeCutoutType.right: 'right',
|
||||
LandscapeCutoutType.both: 'both',
|
||||
};
|
||||
|
||||
// **************************************************************************
|
||||
// StoreGenerator
|
||||
// **************************************************************************
|
||||
|
|
@ -658,22 +645,26 @@ mixin _$SettingsStore on _SettingsStoreBase, Store {
|
|||
);
|
||||
}
|
||||
|
||||
late final _$landscapeCutoutAtom = Atom(
|
||||
name: '_SettingsStoreBase.landscapeCutout',
|
||||
late final _$landscapeFillAllEdgesAtom = Atom(
|
||||
name: '_SettingsStoreBase.landscapeFillAllEdges',
|
||||
context: context,
|
||||
);
|
||||
|
||||
@override
|
||||
LandscapeCutoutType get landscapeCutout {
|
||||
_$landscapeCutoutAtom.reportRead();
|
||||
return super.landscapeCutout;
|
||||
bool get landscapeFillAllEdges {
|
||||
_$landscapeFillAllEdgesAtom.reportRead();
|
||||
return super.landscapeFillAllEdges;
|
||||
}
|
||||
|
||||
@override
|
||||
set landscapeCutout(LandscapeCutoutType value) {
|
||||
_$landscapeCutoutAtom.reportWrite(value, super.landscapeCutout, () {
|
||||
super.landscapeCutout = value;
|
||||
});
|
||||
set landscapeFillAllEdges(bool value) {
|
||||
_$landscapeFillAllEdgesAtom.reportWrite(
|
||||
value,
|
||||
super.landscapeFillAllEdges,
|
||||
() {
|
||||
super.landscapeFillAllEdges = value;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
late final _$chatWidthAtom = Atom(
|
||||
|
|
@ -1136,7 +1127,7 @@ showUserNotices: ${showUserNotices},
|
|||
emoteMenuButtonOnLeft: ${emoteMenuButtonOnLeft},
|
||||
landscapeChatLeftSide: ${landscapeChatLeftSide},
|
||||
landscapeForceVerticalChat: ${landscapeForceVerticalChat},
|
||||
landscapeCutout: ${landscapeCutout},
|
||||
landscapeFillAllEdges: ${landscapeFillAllEdges},
|
||||
chatWidth: ${chatWidth},
|
||||
fullScreenChatOverlayOpacity: ${fullScreenChatOverlayOpacity},
|
||||
autocomplete: ${autocomplete},
|
||||
|
|
|
|||
|
|
@ -784,6 +784,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.7.4"
|
||||
native_device_orientation:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: native_device_orientation
|
||||
sha256: "711aabfd7c67396f6562437cba078d17291f8b7c454c2fbc9739c9d7141b041d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ dependencies:
|
|||
dio: ^5.9.0
|
||||
app_links: ^7.0.0
|
||||
extended_text_field: ^16.0.2
|
||||
native_device_orientation: ^2.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue