chore: pre-commit ci hook, dart format
This commit is contained in:
@@ -20,7 +20,12 @@ class GridItemContext {
|
||||
/// Callback to navigate to the sidebar (for first-column items).
|
||||
final VoidCallback? navigateToSidebar;
|
||||
|
||||
const GridItemContext({required this.isFirstRow, required this.isFirstColumn, this.isListMode = false, this.navigateToSidebar});
|
||||
const GridItemContext({
|
||||
required this.isFirstRow,
|
||||
required this.isFirstColumn,
|
||||
this.isListMode = false,
|
||||
this.navigateToSidebar,
|
||||
});
|
||||
}
|
||||
|
||||
/// A widget that automatically switches between grid and list view
|
||||
|
||||
@@ -123,12 +123,7 @@ class FolderTreeItem extends StatelessWidget {
|
||||
: AppIcon(expandIcon, fill: 1, size: 20),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
AppIcon(
|
||||
_getIcon(),
|
||||
fill: 1,
|
||||
size: 20,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
AppIcon(_getIcon(), fill: 1, size: 20, color: Theme.of(context).colorScheme.primary),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
@@ -234,7 +229,8 @@ class FolderTreeItem extends StatelessWidget {
|
||||
) {
|
||||
final posterUrl = item.posterThumb(mode: episodePosterMode);
|
||||
final client = serverId != null ? context.getClientForServer(serverId!) : null;
|
||||
final shouldBlur = hideSpoilers && item.shouldHideSpoiler && episodePosterMode == EpisodePosterMode.episodeThumbnail;
|
||||
final shouldBlur =
|
||||
hideSpoilers && item.shouldHideSpoiler && episodePosterMode == EpisodePosterMode.episodeThumbnail;
|
||||
|
||||
Widget image;
|
||||
if (item.usesWideAspectRatio(episodePosterMode)) {
|
||||
@@ -265,10 +261,7 @@ class FolderTreeItem extends StatelessWidget {
|
||||
|
||||
Widget _buildWatchOverlay(BuildContext context, bool showUnwatchedCount) {
|
||||
final hasActiveProgress =
|
||||
item.viewOffset != null &&
|
||||
item.duration != null &&
|
||||
item.viewOffset! > 0 &&
|
||||
item.viewOffset! < item.duration!;
|
||||
item.viewOffset != null && item.duration != null && item.viewOffset! > 0 && item.viewOffset! < item.duration!;
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
@@ -356,11 +349,7 @@ class FolderTreeItem extends StatelessWidget {
|
||||
useBackgroundFocus: true,
|
||||
disableScale: true,
|
||||
descendantsAreFocusable: false,
|
||||
child: GestureDetector(
|
||||
onTap: _handleTap,
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: rowContent,
|
||||
),
|
||||
child: GestureDetector(onTap: _handleTap, behavior: HitTestBehavior.opaque, child: rowContent),
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
@@ -159,7 +159,10 @@ class _FolderTreeViewState extends State<FolderTreeView> {
|
||||
bool _isFolder(PlexMetadata item) {
|
||||
// Folders typically don't have a specific type or might have special indicators
|
||||
// Check for common folder indicators
|
||||
return item.key?.contains('/folder') == true || item.type == null || item.type!.isEmpty || item.mediaType == PlexMediaType.unknown;
|
||||
return item.key?.contains('/folder') == true ||
|
||||
item.type == null ||
|
||||
item.type!.isEmpty ||
|
||||
item.mediaType == PlexMediaType.unknown;
|
||||
}
|
||||
|
||||
List<Widget> _buildTreeItems(List<PlexMetadata> items, int depth, [String parentPath = '']) {
|
||||
@@ -227,10 +230,7 @@ class _FolderTreeViewState extends State<FolderTreeView> {
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: _loadRootFolders,
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
children: _buildTreeItems(_rootFolders, 0),
|
||||
),
|
||||
child: ListView(padding: const EdgeInsets.symmetric(horizontal: 8), children: _buildTreeItems(_rootFolders, 0)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,6 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
String? _selectedLibraryGlobalKey;
|
||||
bool _isInitialLoad = true;
|
||||
|
||||
|
||||
/// Flag to prevent onTabChanged from focusing when we're programmatically changing tabs
|
||||
bool _isRestoringTab = false;
|
||||
|
||||
@@ -317,7 +316,6 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
_focusCurrentTab();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_outerScrollController.dispose();
|
||||
@@ -338,9 +336,7 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
if (listEquals(_visibleTabs, newTabs)) return;
|
||||
|
||||
// Save current tab type before changing
|
||||
final currentTabType = _visibleTabs.length > tabController.index
|
||||
? _visibleTabs[tabController.index]
|
||||
: null;
|
||||
final currentTabType = _visibleTabs.length > tabController.index ? _visibleTabs[tabController.index] : null;
|
||||
|
||||
// Dispose old focus nodes and controller
|
||||
for (final node in _tabFocusNodes) {
|
||||
@@ -350,10 +346,7 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
|
||||
// Build new
|
||||
_visibleTabs = newTabs;
|
||||
_tabFocusNodes = List.generate(
|
||||
newTabs.length,
|
||||
(i) => FocusNode(debugLabel: 'tab_chip_${newTabs[i].name}'),
|
||||
);
|
||||
_tabFocusNodes = List.generate(newTabs.length, (i) => FocusNode(debugLabel: 'tab_chip_${newTabs[i].name}'));
|
||||
initTabNavigation();
|
||||
|
||||
// Restore tab position: find current tab type in new set, default to first
|
||||
@@ -370,7 +363,12 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
LibraryTabType.playlists => t.libraries.tabs.playlists,
|
||||
};
|
||||
|
||||
Widget _buildTabContent(LibraryTabType type, {required PlexLibrary library, required bool isActive, required int tabIndex}) {
|
||||
Widget _buildTabContent(
|
||||
LibraryTabType type, {
|
||||
required PlexLibrary library,
|
||||
required bool isActive,
|
||||
required int tabIndex,
|
||||
}) {
|
||||
return switch (type) {
|
||||
LibraryTabType.recommended => LibraryRecommendedTab(
|
||||
key: _recommendedTabKey,
|
||||
@@ -481,7 +479,6 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
_focusCurrentTab();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -605,10 +602,7 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
FocusableButton(
|
||||
autofocus: true,
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
child: TextButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
child: Text(t.common.cancel),
|
||||
),
|
||||
child: TextButton(onPressed: () => Navigator.pop(context, false), child: Text(t.common.cancel)),
|
||||
),
|
||||
FocusableButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
@@ -834,9 +828,8 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
}
|
||||
|
||||
Widget _buildLibraryDropdownTitle(List<PlexLibrary> visibleLibraries) {
|
||||
final selectedLibrary = visibleLibraries
|
||||
.where((lib) => lib.globalKey == _selectedLibraryGlobalKey)
|
||||
.firstOrNull ??
|
||||
final selectedLibrary =
|
||||
visibleLibraries.where((lib) => lib.globalKey == _selectedLibraryGlobalKey).firstOrNull ??
|
||||
visibleLibraries.firstOrNull;
|
||||
if (selectedLibrary == null) return Text(t.libraries.title);
|
||||
|
||||
@@ -900,115 +893,116 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
|
||||
return Scaffold(
|
||||
body: ScrollConfiguration(
|
||||
behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
|
||||
child: CustomScrollView(
|
||||
controller: _outerScrollController,
|
||||
slivers: [
|
||||
DesktopSliverAppBar(
|
||||
title: _buildAppBarTitle(visibleLibraries),
|
||||
pinned: true,
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
scrolledUnderElevation: 0,
|
||||
actions: [
|
||||
FocusableActionBar(
|
||||
key: _actionBarKey,
|
||||
onNavigateLeft: () => getTabChipFocusNode(_visibleTabs.length - 1).requestFocus(),
|
||||
onNavigateDown: _focusCurrentTab,
|
||||
actions: [
|
||||
if (allLibraries.isNotEmpty)
|
||||
FocusableAction(
|
||||
icon: Symbols.edit_rounded,
|
||||
tooltip: t.libraries.manageLibraries,
|
||||
onPressed: _showLibraryManagementSheet,
|
||||
),
|
||||
behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
|
||||
child: CustomScrollView(
|
||||
controller: _outerScrollController,
|
||||
slivers: [
|
||||
DesktopSliverAppBar(
|
||||
title: _buildAppBarTitle(visibleLibraries),
|
||||
pinned: true,
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
scrolledUnderElevation: 0,
|
||||
actions: [
|
||||
FocusableActionBar(
|
||||
key: _actionBarKey,
|
||||
onNavigateLeft: () => getTabChipFocusNode(_visibleTabs.length - 1).requestFocus(),
|
||||
onNavigateDown: _focusCurrentTab,
|
||||
actions: [
|
||||
if (allLibraries.isNotEmpty)
|
||||
FocusableAction(
|
||||
icon: Symbols.refresh_rounded,
|
||||
tooltip: t.common.refresh,
|
||||
onPressed: _refreshCurrentTab,
|
||||
icon: Symbols.edit_rounded,
|
||||
tooltip: t.libraries.manageLibraries,
|
||||
onPressed: _showLibraryManagementSheet,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
if (isLoadingLibraries)
|
||||
const SliverFillRemaining(child: Center(child: CircularProgressIndicator()))
|
||||
else if (_errorMessage != null && visibleLibraries.isEmpty)
|
||||
SliverFillRemaining(
|
||||
child: ErrorStateWidget(
|
||||
message: _errorMessage!,
|
||||
icon: Symbols.error_outline_rounded,
|
||||
onRetry: () {
|
||||
final librariesProvider = context.read<LibrariesProvider>();
|
||||
librariesProvider.refresh();
|
||||
},
|
||||
),
|
||||
)
|
||||
else if (visibleLibraries.isEmpty)
|
||||
SliverFillRemaining(
|
||||
child: EmptyStateWidget(message: t.libraries.noLibrariesFound, icon: Symbols.video_library_rounded),
|
||||
)
|
||||
else ...[
|
||||
// Tab selector chips (only on mobile - desktop has them in app bar)
|
||||
if (selectedLibrary != null && !PlatformDetector.shouldUseSideNavigation(context))
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: [
|
||||
for (int i = 0; i < _visibleTabs.length; i++) ...[
|
||||
if (i > 0) const SizedBox(width: 8),
|
||||
buildTabChip(
|
||||
_getTabLabel(_visibleTabs[i]),
|
||||
i,
|
||||
onSelectWhenActive: _focusCurrentTab,
|
||||
onNavigateDown: _focusCurrentTabFromTabBar,
|
||||
onNavigateRightFromLast: () => _actionBarKey.currentState?.requestFocusOnFirst(),
|
||||
FocusableAction(
|
||||
icon: Symbols.refresh_rounded,
|
||||
tooltip: t.common.refresh,
|
||||
onPressed: _refreshCurrentTab,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
if (isLoadingLibraries)
|
||||
const SliverFillRemaining(child: Center(child: CircularProgressIndicator()))
|
||||
else if (_errorMessage != null && visibleLibraries.isEmpty)
|
||||
SliverFillRemaining(
|
||||
child: ErrorStateWidget(
|
||||
message: _errorMessage!,
|
||||
icon: Symbols.error_outline_rounded,
|
||||
onRetry: () {
|
||||
final librariesProvider = context.read<LibrariesProvider>();
|
||||
librariesProvider.refresh();
|
||||
},
|
||||
),
|
||||
)
|
||||
else if (visibleLibraries.isEmpty)
|
||||
SliverFillRemaining(
|
||||
child: EmptyStateWidget(message: t.libraries.noLibrariesFound, icon: Symbols.video_library_rounded),
|
||||
)
|
||||
else ...[
|
||||
// Tab selector chips (only on mobile - desktop has them in app bar)
|
||||
if (selectedLibrary != null && !PlatformDetector.shouldUseSideNavigation(context))
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: [
|
||||
for (int i = 0; i < _visibleTabs.length; i++) ...[
|
||||
if (i > 0) const SizedBox(width: 8),
|
||||
buildTabChip(
|
||||
_getTabLabel(_visibleTabs[i]),
|
||||
i,
|
||||
onSelectWhenActive: _focusCurrentTab,
|
||||
onNavigateDown: _focusCurrentTabFromTabBar,
|
||||
onNavigateRightFromLast: () => _actionBarKey.currentState?.requestFocusOnFirst(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Tab content
|
||||
if (selectedLibrary != null)
|
||||
SliverFillRemaining(
|
||||
child: TabBarView(
|
||||
key: ValueKey(_selectedLibraryGlobalKey),
|
||||
controller: tabController,
|
||||
// Disable swipe on desktop - trackpad scrolling triggers accidental tab switches
|
||||
// See: https://github.com/flutter/flutter/issues/11132
|
||||
physics: PlatformDetector.isDesktop(context) ? const NeverScrollableScrollPhysics() : null,
|
||||
// Wrap each tab in ClipRect so horizontal overflow (e.g. hub rows
|
||||
// with Clip.none) doesn't bleed into adjacent tabs during swipe transitions.
|
||||
// The TabBarView's own clipBehavior only clips at the viewport level,
|
||||
// not per-page, so we need per-child clipping.
|
||||
children: [
|
||||
for (int i = 0; i < _visibleTabs.length; i++)
|
||||
ClipRect(child: _buildTabContent(
|
||||
// Tab content
|
||||
if (selectedLibrary != null)
|
||||
SliverFillRemaining(
|
||||
child: TabBarView(
|
||||
key: ValueKey(_selectedLibraryGlobalKey),
|
||||
controller: tabController,
|
||||
// Disable swipe on desktop - trackpad scrolling triggers accidental tab switches
|
||||
// See: https://github.com/flutter/flutter/issues/11132
|
||||
physics: PlatformDetector.isDesktop(context) ? const NeverScrollableScrollPhysics() : null,
|
||||
// Wrap each tab in ClipRect so horizontal overflow (e.g. hub rows
|
||||
// with Clip.none) doesn't bleed into adjacent tabs during swipe transitions.
|
||||
// The TabBarView's own clipBehavior only clips at the viewport level,
|
||||
// not per-page, so we need per-child clipping.
|
||||
children: [
|
||||
for (int i = 0; i < _visibleTabs.length; i++)
|
||||
ClipRect(
|
||||
child: _buildTabContent(
|
||||
_visibleTabs[i],
|
||||
library: selectedLibrary,
|
||||
isActive: tabController.index == i,
|
||||
tabIndex: i,
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LibraryManagementSheet extends StatefulWidget {
|
||||
|
||||
final bool isDialog;
|
||||
final List<PlexLibrary> allLibraries;
|
||||
final Set<String> hiddenLibraryKeys;
|
||||
|
||||
@@ -146,24 +146,27 @@ class _SortBottomSheetState extends State<SortBottomSheet> {
|
||||
title: Text(sort.title),
|
||||
value: sort,
|
||||
secondary: isSelected
|
||||
? SegmentedButton<bool>(
|
||||
showSelectedIcon: false,
|
||||
segments: const [
|
||||
ButtonSegment(value: false, icon: AppIcon(Symbols.arrow_upward_rounded, fill: 1, size: 16)),
|
||||
ButtonSegment(
|
||||
value: true,
|
||||
icon: AppIcon(Symbols.arrow_downward_rounded, fill: 1, size: 16),
|
||||
),
|
||||
],
|
||||
selected: {_currentDescending},
|
||||
onSelectionChanged: (Set<bool> newSelection) {
|
||||
_handleDirectionChange(sort, newSelection.first);
|
||||
},
|
||||
)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
},
|
||||
? SegmentedButton<bool>(
|
||||
showSelectedIcon: false,
|
||||
segments: const [
|
||||
ButtonSegment(
|
||||
value: false,
|
||||
icon: AppIcon(Symbols.arrow_upward_rounded, fill: 1, size: 16),
|
||||
),
|
||||
ButtonSegment(
|
||||
value: true,
|
||||
icon: AppIcon(Symbols.arrow_downward_rounded, fill: 1, size: 16),
|
||||
),
|
||||
],
|
||||
selected: {_currentDescending},
|
||||
onSelectionChanged: (Set<bool> newSelection) {
|
||||
_handleDirectionChange(sort, newSelection.first);
|
||||
},
|
||||
)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -643,52 +643,54 @@ class _LibraryBrowseTabState extends BaseLibraryTabState<PlexMetadata, LibraryBr
|
||||
SelectKeyUpSuppressor.suppressSelectUntilKeyUp();
|
||||
final options = _getGroupingOptions();
|
||||
final controller = OverlaySheetController.of(context);
|
||||
controller.show<String>(
|
||||
showDragHandle: true,
|
||||
builder: (sheetContext) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 4, 16, 8),
|
||||
child: Text(
|
||||
t.libraries.groupings.title,
|
||||
style: Theme.of(sheetContext).textTheme.titleMedium,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: options.map((grouping) {
|
||||
final isSelected = _selectedGrouping == grouping;
|
||||
return FocusableListTile(
|
||||
dense: true,
|
||||
leading: AppIcon(
|
||||
isSelected ? Symbols.radio_button_checked_rounded : Symbols.radio_button_unchecked_rounded,
|
||||
fill: 1,
|
||||
),
|
||||
title: Text(_getGroupingLabel(grouping)),
|
||||
onTap: () => controller.close(grouping),
|
||||
);
|
||||
}).toList(),
|
||||
controller
|
||||
.show<String>(
|
||||
showDragHandle: true,
|
||||
builder: (sheetContext) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 4, 16, 8),
|
||||
child: Text(
|
||||
t.libraries.groupings.title,
|
||||
style: Theme.of(sheetContext).textTheme.titleMedium,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: options.map((grouping) {
|
||||
final isSelected = _selectedGrouping == grouping;
|
||||
return FocusableListTile(
|
||||
dense: true,
|
||||
leading: AppIcon(
|
||||
isSelected ? Symbols.radio_button_checked_rounded : Symbols.radio_button_unchecked_rounded,
|
||||
fill: 1,
|
||||
),
|
||||
title: Text(_getGroupingLabel(grouping)),
|
||||
onTap: () => controller.close(grouping),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
).then((value) {
|
||||
if (!mounted || value == null || value == _selectedGrouping) return;
|
||||
setState(() {
|
||||
_selectedGrouping = value;
|
||||
});
|
||||
StorageService.getInstance().then((storage) {
|
||||
storage.saveLibraryGrouping(widget.library.globalKey, value);
|
||||
});
|
||||
_loadItems();
|
||||
_loadFirstCharacters();
|
||||
});
|
||||
)
|
||||
.then((value) {
|
||||
if (!mounted || value == null || value == _selectedGrouping) return;
|
||||
setState(() {
|
||||
_selectedGrouping = value;
|
||||
});
|
||||
StorageService.getInstance().then((storage) {
|
||||
storage.saveLibraryGrouping(widget.library.globalKey, value);
|
||||
});
|
||||
_loadItems();
|
||||
_loadFirstCharacters();
|
||||
});
|
||||
}
|
||||
|
||||
void _showFiltersBottomSheet() {
|
||||
@@ -776,7 +778,10 @@ class _LibraryBrowseTabState extends BaseLibraryTabState<PlexMetadata, LibraryBr
|
||||
|
||||
if (_totalSize == 0) return;
|
||||
|
||||
final targetIndex = shouldRestoreGridFocus && lastFocusedGridIndex! < _totalSize && _loadedItems.containsKey(lastFocusedGridIndex!) ? lastFocusedGridIndex! : 0;
|
||||
final targetIndex =
|
||||
shouldRestoreGridFocus && lastFocusedGridIndex! < _totalSize && _loadedItems.containsKey(lastFocusedGridIndex!)
|
||||
? lastFocusedGridIndex!
|
||||
: 0;
|
||||
|
||||
// Use firstItemFocusNode for index 0 (matches _buildMediaCardItem)
|
||||
if (targetIndex == 0) {
|
||||
@@ -1227,8 +1232,7 @@ class _LibraryBrowseTabState extends BaseLibraryTabState<PlexMetadata, LibraryBr
|
||||
final settingsProvider = context.read<SettingsProvider>();
|
||||
final maxExtent = GridSizeCalculator.getMaxCrossAxisExtent(context, settingsProvider.libraryDensity);
|
||||
final crossAxisSpacing = GridLayoutConstants.crossAxisSpacing;
|
||||
final columnCount =
|
||||
((screenSize.width + crossAxisSpacing) / (maxExtent + crossAxisSpacing)).ceil().clamp(1, 100);
|
||||
final columnCount = ((screenSize.width + crossAxisSpacing) / (maxExtent + crossAxisSpacing)).ceil().clamp(1, 100);
|
||||
final itemWidth = screenSize.width / columnCount;
|
||||
final itemHeight = itemWidth / GridLayoutConstants.posterAspectRatio;
|
||||
final rowHeight = itemHeight + GridLayoutConstants.mainAxisSpacing;
|
||||
@@ -1551,10 +1555,7 @@ class _SkeletonCard extends StatelessWidget {
|
||||
FractionallySizedBox(
|
||||
alignment: Alignment.centerLeft,
|
||||
widthFactor: 0.6,
|
||||
child: SkeletonLoader(
|
||||
borderRadius: BorderRadius.all(Radius.circular(4)),
|
||||
child: SizedBox(height: 11),
|
||||
),
|
||||
child: SkeletonLoader(borderRadius: BorderRadius.all(Radius.circular(4)), child: SizedBox(height: 11)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user