fix: overlay sheet theme and scope on mobile
This commit is contained in:
@@ -1034,9 +1034,8 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
// Compute visible libraries (filtered from all libraries)
|
||||
final visibleLibraries = allLibraries.where((lib) => !hiddenKeys.contains(lib.globalKey)).toList();
|
||||
|
||||
return OverlaySheetHost(
|
||||
child: Scaffold(
|
||||
body: ScrollConfiguration(
|
||||
return Scaffold(
|
||||
body: ScrollConfiguration(
|
||||
behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
|
||||
child: CustomScrollView(
|
||||
controller: _outerScrollController,
|
||||
@@ -1171,12 +1170,12 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LibraryManagementSheet extends StatefulWidget {
|
||||
|
||||
final bool isDialog;
|
||||
final List<PlexLibrary> allLibraries;
|
||||
final Set<String> hiddenLibraryKeys;
|
||||
|
||||
@@ -822,58 +822,54 @@ class _LibraryBrowseTabState extends BaseLibraryTabState<PlexMetadata, LibraryBr
|
||||
|
||||
// For folders mode, use FolderTreeView instead of grid/list
|
||||
if (_selectedGrouping == 'folders') {
|
||||
return OverlaySheetHost(
|
||||
child: Column(
|
||||
children: [
|
||||
_buildChipsBar(),
|
||||
Expanded(
|
||||
child: FolderTreeView(
|
||||
libraryKey: widget.library.key,
|
||||
serverId: widget.library.serverId,
|
||||
onRefresh: updateItem,
|
||||
firstItemFocusNode: firstItemFocusNode,
|
||||
onNavigateUp: () => _groupingChipFocusNode.requestFocus(),
|
||||
),
|
||||
return Column(
|
||||
children: [
|
||||
_buildChipsBar(),
|
||||
Expanded(
|
||||
child: FolderTreeView(
|
||||
libraryKey: widget.library.key,
|
||||
serverId: widget.library.serverId,
|
||||
onRefresh: updateItem,
|
||||
firstItemFocusNode: firstItemFocusNode,
|
||||
onNavigateUp: () => _groupingChipFocusNode.requestFocus(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// For list/grid modes, use Stack with chips layered on top of grid.
|
||||
// This allows the grid to use Clip.none for focus decorations while
|
||||
// the chips bar (with background) covers any overflow at the top.
|
||||
return OverlaySheetHost(
|
||||
child: Stack(
|
||||
children: [
|
||||
// Grid fills the entire area, with top padding for chips bar
|
||||
Positioned.fill(child: _buildScrollableContent()),
|
||||
// Chips bar on top with solid background
|
||||
Positioned(top: 0, left: 0, right: 0, child: _buildChipsBar()),
|
||||
// Alpha jump bar / scroll handle on the right edge
|
||||
if (_shouldShowAlphaJumpBar)
|
||||
Positioned(
|
||||
top: _chipsBarHeight,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: _isPhone(context)
|
||||
? AlphaScrollHandle(
|
||||
firstCharacters: _firstCharacters,
|
||||
onJump: _jumpToIndex,
|
||||
currentLetter: _currentAlphaLetter,
|
||||
isScrolling: _isScrollActive,
|
||||
)
|
||||
: AlphaJumpBar(
|
||||
firstCharacters: _firstCharacters,
|
||||
onJump: _jumpToIndex,
|
||||
currentLetter: _currentAlphaLetter,
|
||||
focusNode: _alphaJumpBarFocusNode,
|
||||
onNavigateLeft: _navigateToGridNearScroll,
|
||||
onBack: _navigateToGridNearScroll,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
return Stack(
|
||||
children: [
|
||||
// Grid fills the entire area, with top padding for chips bar
|
||||
Positioned.fill(child: _buildScrollableContent()),
|
||||
// Chips bar on top with solid background
|
||||
Positioned(top: 0, left: 0, right: 0, child: _buildChipsBar()),
|
||||
// Alpha jump bar / scroll handle on the right edge
|
||||
if (_shouldShowAlphaJumpBar)
|
||||
Positioned(
|
||||
top: _chipsBarHeight,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: _isPhone(context)
|
||||
? AlphaScrollHandle(
|
||||
firstCharacters: _firstCharacters,
|
||||
onJump: _jumpToIndex,
|
||||
currentLetter: _currentAlphaLetter,
|
||||
isScrolling: _isScrollActive,
|
||||
)
|
||||
: AlphaJumpBar(
|
||||
firstCharacters: _firstCharacters,
|
||||
onJump: _jumpToIndex,
|
||||
currentLetter: _currentAlphaLetter,
|
||||
focusNode: _alphaJumpBarFocusNode,
|
||||
onNavigateLeft: _navigateToGridNearScroll,
|
||||
onBack: _navigateToGridNearScroll,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import '../utils/platform_detector.dart';
|
||||
import '../utils/video_player_navigation.dart';
|
||||
import '../main.dart';
|
||||
import '../mixins/refreshable.dart';
|
||||
import '../widgets/overlay_sheet.dart';
|
||||
import '../mixins/tab_visibility_aware.dart';
|
||||
import '../navigation/navigation_tabs.dart';
|
||||
import '../providers/multi_server_provider.dart';
|
||||
@@ -1054,9 +1055,10 @@ class _MainScreenState extends State<MainScreen> with RouteAware, WindowListener
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
body: IndexedStack(index: _currentIndex, children: _screens),
|
||||
bottomNavigationBar: Column(
|
||||
return OverlaySheetHost(
|
||||
child: Scaffold(
|
||||
body: IndexedStack(index: _currentIndex, children: _screens),
|
||||
bottomNavigationBar: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Reconnect bar when offline
|
||||
@@ -1102,6 +1104,7 @@ class _MainScreenState extends State<MainScreen> with RouteAware, WindowListener
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ class _FileInfoBottomSheetState extends State<FileInfoBottomSheet> {
|
||||
BottomSheetHeader(
|
||||
title: t.fileInfo.title,
|
||||
icon: Symbols.info_rounded,
|
||||
iconColor: Colors.white,
|
||||
titleColor: Colors.white,
|
||||
closeFocusNode: _initialFocusNode,
|
||||
),
|
||||
// Content
|
||||
@@ -50,7 +48,7 @@ class _FileInfoBottomSheetState extends State<FileInfoBottomSheet> {
|
||||
if (widget.title.isNotEmpty) ...[
|
||||
Text(
|
||||
widget.title,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500),
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
@@ -115,7 +113,7 @@ class _FileInfoBottomSheetState extends State<FileInfoBottomSheet> {
|
||||
Widget _buildSectionHeader(String title) {
|
||||
return Text(
|
||||
title,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -127,12 +125,12 @@ class _FileInfoBottomSheetState extends State<FileInfoBottomSheet> {
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 140,
|
||||
child: Text(label, style: TextStyle(color: Colors.grey[400], fontSize: 14)),
|
||||
child: Text(label, style: TextStyle(color: Theme.of(context).textTheme.bodySmall?.color, fontSize: 14)),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
value,
|
||||
style: TextStyle(color: Colors.white, fontSize: 14, fontFamily: isMonospace ? 'monospace' : null),
|
||||
style: TextStyle(fontSize: 14, fontFamily: isMonospace ? 'monospace' : null),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1322,41 +1322,39 @@ class _FocusableContextMenuSheetState extends State<_FocusableContextMenuSheet>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
widget.title,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
widget.title,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
...widget.actions.asMap().entries.map((entry) {
|
||||
final index = entry.key;
|
||||
final action = entry.value;
|
||||
return FocusableListTile(
|
||||
focusNode: index == 0 ? _initialFocusNode : null,
|
||||
leading: AppIcon(action.icon, fill: 1),
|
||||
title: Text(action.label),
|
||||
onTap: () => OverlaySheetController.closeAdaptive(context, action.value),
|
||||
hoverColor: action.hoverColor,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
...widget.actions.asMap().entries.map((entry) {
|
||||
final index = entry.key;
|
||||
final action = entry.value;
|
||||
return FocusableListTile(
|
||||
focusNode: index == 0 ? _initialFocusNode : null,
|
||||
leading: AppIcon(action.icon, fill: 1),
|
||||
title: Text(action.label),
|
||||
onTap: () => OverlaySheetController.closeAdaptive(context, action.value),
|
||||
hoverColor: action.hoverColor,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ class OverlaySheetController {
|
||||
context: context,
|
||||
builder: builder,
|
||||
constraints: constraints,
|
||||
backgroundColor: backgroundColor ?? Colors.grey[900],
|
||||
backgroundColor: backgroundColor ?? Theme.of(context).colorScheme.surface,
|
||||
barrierColor: Colors.black54,
|
||||
isScrollControlled: isScrollControlled,
|
||||
);
|
||||
@@ -187,7 +187,7 @@ class _OverlaySheetHostState extends State<OverlaySheetHost> with SingleTickerPr
|
||||
bool _isClosing = false;
|
||||
bool _barrierDismissible = true;
|
||||
BoxConstraints? _constraints;
|
||||
Color _backgroundColor = Colors.grey[900]!;
|
||||
Color? _explicitBackgroundColor;
|
||||
|
||||
// Drag-to-dismiss state
|
||||
double _dragOffset = 0;
|
||||
@@ -249,7 +249,7 @@ class _OverlaySheetHostState extends State<OverlaySheetHost> with SingleTickerPr
|
||||
_isClosing = false;
|
||||
_barrierDismissible = barrierDismissible;
|
||||
_constraints = constraints;
|
||||
if (backgroundColor != null) _backgroundColor = backgroundColor;
|
||||
_explicitBackgroundColor = backgroundColor;
|
||||
_dragOffset = 0;
|
||||
_isDragging = false;
|
||||
});
|
||||
@@ -454,7 +454,6 @@ class _OverlaySheetHostState extends State<OverlaySheetHost> with SingleTickerPr
|
||||
BoxConstraints(
|
||||
maxWidth: isDesktop ? 700 : double.infinity,
|
||||
maxHeight: isDesktop ? 400 : size.height * 0.75,
|
||||
minHeight: isDesktop ? 300 : size.height * 0.5,
|
||||
);
|
||||
|
||||
Widget sheet = FocusScope(
|
||||
@@ -470,7 +469,7 @@ class _OverlaySheetHostState extends State<OverlaySheetHost> with SingleTickerPr
|
||||
child: Transform.translate(
|
||||
offset: Offset(0, _dragOffset.clamp(0, double.infinity)),
|
||||
child: Material(
|
||||
color: _backgroundColor,
|
||||
color: _explicitBackgroundColor ?? Theme.of(context).colorScheme.surface,
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: SafeArea(
|
||||
|
||||
Reference in New Issue
Block a user