avoid using builders
This commit is contained in:
@@ -52,6 +52,112 @@ import 'package:weblibre/features/geckoview/features/readerview/presentation/wid
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
import 'package:weblibre/utils/ui_helper.dart' as ui_helper;
|
||||
|
||||
class _TabBar extends HookConsumerWidget {
|
||||
final ValueNotifier<bool> showAppBar;
|
||||
final ValueNotifier<PersistentBottomSheetController?> sheetController;
|
||||
|
||||
const _TabBar({required this.showAppBar, required this.sheetController});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final tabId = ref.watch(selectedTabProvider);
|
||||
final displayedSheet = ref.watch(bottomSheetControllerProvider);
|
||||
|
||||
final tabInFullScreen = ref.watch(
|
||||
selectedTabStateProvider.select((value) => value?.isFullScreen ?? false),
|
||||
);
|
||||
|
||||
final autoHideTabBar = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(value) => value.autoHideTabBar,
|
||||
),
|
||||
);
|
||||
|
||||
if (!autoHideTabBar) {
|
||||
return Visibility(
|
||||
visible: !tabInFullScreen,
|
||||
child: BrowserBottomAppBar(displayedSheet: displayedSheet),
|
||||
);
|
||||
}
|
||||
|
||||
final appBarVisible = useValueListenable(showAppBar);
|
||||
final diffAcc = useRef(0.0);
|
||||
|
||||
void resetHiddenState() {
|
||||
showAppBar.value = true;
|
||||
diffAcc.value = 0.0;
|
||||
}
|
||||
|
||||
useEffect(() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
resetHiddenState();
|
||||
});
|
||||
|
||||
return null;
|
||||
}, [tabId]);
|
||||
|
||||
useOnAppLifecycleStateChange((previous, current) {
|
||||
if (current == AppLifecycleState.resumed) {
|
||||
resetHiddenState();
|
||||
}
|
||||
});
|
||||
|
||||
ref.listen(tabStateProvider(tabId).select((value) => value?.isLoading), (
|
||||
previous,
|
||||
next,
|
||||
) {
|
||||
if (next == true) {
|
||||
resetHiddenState();
|
||||
}
|
||||
});
|
||||
|
||||
ref.listen(tabStateProvider(tabId).select((value) => value?.historyState), (
|
||||
previous,
|
||||
next,
|
||||
) {
|
||||
if (next != null && previous != null) {
|
||||
if (previous != next) {
|
||||
resetHiddenState();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ref.listen(tabScrollYProvider(tabId, const Duration(milliseconds: 50)), (
|
||||
previous,
|
||||
next,
|
||||
) {
|
||||
if (previous?.value != null && next.value != null) {
|
||||
final diff = previous!.value! - next.value!;
|
||||
if (diff < 0) {
|
||||
if (diffAcc.value > 0) {
|
||||
diffAcc.value = 0.0;
|
||||
}
|
||||
|
||||
diffAcc.value += diff;
|
||||
if (diffAcc.value.abs() > kToolbarHeight * 1.5) {
|
||||
showAppBar.value = false;
|
||||
}
|
||||
} else if (diff > 0) {
|
||||
if (diffAcc.value < 0) {
|
||||
diffAcc.value = 0.0;
|
||||
}
|
||||
|
||||
diffAcc.value += diff;
|
||||
if (diffAcc.value.abs() > (kToolbarHeight / 2)) {
|
||||
resetHiddenState();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Visibility(
|
||||
visible:
|
||||
sheetController.value != null || (!tabInFullScreen && appBarVisible),
|
||||
child: BrowserBottomAppBar(displayedSheet: displayedSheet),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BrowserScreen extends HookConsumerWidget {
|
||||
const BrowserScreen({super.key});
|
||||
|
||||
@@ -114,107 +220,9 @@ class BrowserScreen extends HookConsumerWidget {
|
||||
//This causes issues with a non dismissable barrier pushed, we ahve our own barrier and this does seem to have issues when dismissing, so disable it completely
|
||||
return null;
|
||||
},
|
||||
bottomNavigationBar: HookConsumer(
|
||||
builder: (context, ref, child) {
|
||||
final tabId = ref.watch(selectedTabProvider);
|
||||
final displayedSheet = ref.watch(bottomSheetControllerProvider);
|
||||
|
||||
final tabInFullScreen = ref.watch(
|
||||
selectedTabStateProvider.select(
|
||||
(value) => value?.isFullScreen ?? false,
|
||||
),
|
||||
);
|
||||
|
||||
final autoHideTabBar = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(value) => value.autoHideTabBar,
|
||||
),
|
||||
);
|
||||
|
||||
if (!autoHideTabBar) {
|
||||
return Visibility(
|
||||
visible: !tabInFullScreen,
|
||||
child: BrowserBottomAppBar(displayedSheet: displayedSheet),
|
||||
);
|
||||
}
|
||||
|
||||
final appBarVisible = useValueListenable(showAppBar);
|
||||
final diffAcc = useRef(0.0);
|
||||
|
||||
void resetHiddenState() {
|
||||
showAppBar.value = true;
|
||||
diffAcc.value = 0.0;
|
||||
}
|
||||
|
||||
useEffect(() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
resetHiddenState();
|
||||
});
|
||||
|
||||
return null;
|
||||
}, [tabId]);
|
||||
|
||||
useOnAppLifecycleStateChange((previous, current) {
|
||||
if (current == AppLifecycleState.resumed) {
|
||||
resetHiddenState();
|
||||
}
|
||||
});
|
||||
|
||||
ref.listen(
|
||||
tabStateProvider(tabId).select((value) => value?.isLoading),
|
||||
(previous, next) {
|
||||
if (next == true) {
|
||||
resetHiddenState();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
ref.listen(
|
||||
tabStateProvider(tabId).select((value) => value?.historyState),
|
||||
(previous, next) {
|
||||
if (next != null && previous != null) {
|
||||
if (previous != next) {
|
||||
resetHiddenState();
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
ref.listen(
|
||||
tabScrollYProvider(tabId, const Duration(milliseconds: 50)),
|
||||
(previous, next) {
|
||||
if (previous?.value != null && next.value != null) {
|
||||
final diff = previous!.value! - next.value!;
|
||||
if (diff < 0) {
|
||||
if (diffAcc.value > 0) {
|
||||
diffAcc.value = 0.0;
|
||||
}
|
||||
|
||||
diffAcc.value += diff;
|
||||
if (diffAcc.value.abs() > kToolbarHeight * 1.5) {
|
||||
showAppBar.value = false;
|
||||
}
|
||||
} else if (diff > 0) {
|
||||
if (diffAcc.value < 0) {
|
||||
diffAcc.value = 0.0;
|
||||
}
|
||||
|
||||
diffAcc.value += diff;
|
||||
if (diffAcc.value.abs() > (kToolbarHeight / 2)) {
|
||||
resetHiddenState();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return Visibility(
|
||||
visible:
|
||||
sheetController.value != null ||
|
||||
(!tabInFullScreen && appBarVisible),
|
||||
child: BrowserBottomAppBar(displayedSheet: displayedSheet),
|
||||
);
|
||||
},
|
||||
bottomNavigationBar: _TabBar(
|
||||
showAppBar: showAppBar,
|
||||
sheetController: sheetController,
|
||||
),
|
||||
body: _Browser(
|
||||
overlayController: overlayController,
|
||||
|
||||
@@ -370,45 +370,14 @@ class _TabViewHeader extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class ViewTabsWidget extends HookConsumerWidget {
|
||||
class _TabView extends HookConsumerWidget {
|
||||
final ScrollController scrollController;
|
||||
final DraggableScrollableController? draggableScrollableController;
|
||||
final VoidCallback onClose;
|
||||
final bool showNewTabFab;
|
||||
|
||||
const ViewTabsWidget({
|
||||
required this.onClose,
|
||||
required this.scrollController,
|
||||
this.draggableScrollableController,
|
||||
required this.showNewTabFab,
|
||||
super.key,
|
||||
});
|
||||
const _TabView({required this.scrollController, required this.onClose});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Stack(
|
||||
alignment: Alignment.bottomRight,
|
||||
children: [
|
||||
NestedScrollView(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
||||
SliverToBoxAdapter(
|
||||
child:
|
||||
draggableScrollableController.mapNotNull(
|
||||
(draggableScrollableController) =>
|
||||
DraggableScrollableHeader(
|
||||
controller: draggableScrollableController,
|
||||
child: _TabViewHeader(
|
||||
onClose: onClose,
|
||||
treeViewEnabled: false,
|
||||
),
|
||||
),
|
||||
) ??
|
||||
_TabViewHeader(onClose: onClose, treeViewEnabled: false),
|
||||
),
|
||||
],
|
||||
body: HookConsumer(
|
||||
builder: (context, ref, child) {
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
|
||||
final containerId = ref.watch(selectedContainerProvider);
|
||||
@@ -418,16 +387,12 @@ class ViewTabsWidget extends HookConsumerWidget {
|
||||
searchPartition: TabSearchPartition.preview,
|
||||
// ignore: document_ignores using fast equatable
|
||||
// ignore: provider_parameters
|
||||
containerFilter: ContainerFilterById(
|
||||
containerId: containerId,
|
||||
),
|
||||
containerFilter: ContainerFilterById(containerId: containerId),
|
||||
groupTrees: false,
|
||||
),
|
||||
);
|
||||
|
||||
final tabSuggestionsEnabled = ref.watch(
|
||||
tabSuggestionsControllerProvider,
|
||||
);
|
||||
final tabSuggestionsEnabled = ref.watch(tabSuggestionsControllerProvider);
|
||||
|
||||
final suggestedTabEntities = tabSuggestionsEnabled
|
||||
? ref.watch(suggestedTabEntitiesProvider(containerId))
|
||||
@@ -509,10 +474,7 @@ class ViewTabsWidget extends HookConsumerWidget {
|
||||
ref.read(willAcceptDropProvider.notifier).clear();
|
||||
},
|
||||
onReorderPositions: (positions) async {
|
||||
assert(
|
||||
positions.length == 1,
|
||||
'Not ready for multiple reorders',
|
||||
);
|
||||
assert(positions.length == 1, 'Not ready for multiple reorders');
|
||||
|
||||
final oldIndex = positions.first.oldIndex;
|
||||
final newIndex = positions.first.newIndex;
|
||||
@@ -533,24 +495,19 @@ class ViewTabsWidget extends HookConsumerWidget {
|
||||
|
||||
final String key;
|
||||
if (newIndex <= 0) {
|
||||
key = await containerRepository.getLeadingOrderKey(
|
||||
containerId,
|
||||
);
|
||||
} else if (newIndex >=
|
||||
filteredTabEntities.value.length - 1) {
|
||||
key = await containerRepository.getLeadingOrderKey(containerId);
|
||||
} else if (newIndex >= filteredTabEntities.value.length - 1) {
|
||||
key = await containerRepository.getTrailingOrderKey(
|
||||
containerId,
|
||||
);
|
||||
} else {
|
||||
if (newIndex < oldIndex) {
|
||||
key = (await containerRepository
|
||||
.getOrderKeyAfterTab(
|
||||
key = (await containerRepository.getOrderKeyAfterTab(
|
||||
filteredTabEntities.value[newIndex - 1].tabId,
|
||||
containerId,
|
||||
))!;
|
||||
} else {
|
||||
key = await containerRepository
|
||||
.getOrderKeyBeforeTab(
|
||||
key = await containerRepository.getOrderKeyBeforeTab(
|
||||
filteredTabEntities.value[newIndex + 1].tabId,
|
||||
containerId,
|
||||
);
|
||||
@@ -579,16 +536,12 @@ class ViewTabsWidget extends HookConsumerWidget {
|
||||
tab = CustomDraggable(
|
||||
key: Key(entity.tabId),
|
||||
data: TabDragData(entity.tabId),
|
||||
child: _TabDraggable(
|
||||
entity: entity,
|
||||
onClose: onClose,
|
||||
),
|
||||
child: _TabDraggable(entity: entity, onClose: onClose),
|
||||
);
|
||||
} else {
|
||||
final suggestedIndex =
|
||||
index - filteredTabEntities.value.length;
|
||||
final entity =
|
||||
suggestedTabEntities.value[suggestedIndex];
|
||||
final entity = suggestedTabEntities.value[suggestedIndex];
|
||||
|
||||
tab = CustomDraggable(
|
||||
key: Key('suggested_${entity.tabId}'),
|
||||
@@ -610,9 +563,48 @@ class ViewTabsWidget extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
class ViewTabsWidget extends HookConsumerWidget {
|
||||
final ScrollController scrollController;
|
||||
final DraggableScrollableController? draggableScrollableController;
|
||||
final VoidCallback onClose;
|
||||
final bool showNewTabFab;
|
||||
|
||||
const ViewTabsWidget({
|
||||
required this.onClose,
|
||||
required this.scrollController,
|
||||
this.draggableScrollableController,
|
||||
required this.showNewTabFab,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Stack(
|
||||
alignment: Alignment.bottomRight,
|
||||
children: [
|
||||
NestedScrollView(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
||||
SliverToBoxAdapter(
|
||||
child:
|
||||
draggableScrollableController.mapNotNull(
|
||||
(draggableScrollableController) =>
|
||||
DraggableScrollableHeader(
|
||||
controller: draggableScrollableController,
|
||||
child: _TabViewHeader(
|
||||
onClose: onClose,
|
||||
treeViewEnabled: false,
|
||||
),
|
||||
),
|
||||
) ??
|
||||
_TabViewHeader(onClose: onClose, treeViewEnabled: false),
|
||||
),
|
||||
],
|
||||
body: _TabView(scrollController: scrollController, onClose: onClose),
|
||||
),
|
||||
if (showNewTabFab)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
|
||||
@@ -38,14 +38,12 @@ class ContainerListScreen extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Containers')),
|
||||
body: HookConsumer(
|
||||
builder: (context, ref, child) {
|
||||
final containersAsync = ref.watch(watchContainersWithCountProvider);
|
||||
final selectedContainer = ref.watch(selectedContainerProvider);
|
||||
|
||||
return Skeletonizer(
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Containers')),
|
||||
body: Skeletonizer(
|
||||
enabled: containersAsync.isLoading,
|
||||
child: containersAsync.when(
|
||||
skipLoadingOnReload: true,
|
||||
@@ -73,9 +71,7 @@ class ContainerListScreen extends HookConsumerWidget {
|
||||
result ==
|
||||
SetContainerResult.successHasProxy) {
|
||||
await ref
|
||||
.read(
|
||||
startProxyControllerProvider.notifier,
|
||||
)
|
||||
.read(startProxyControllerProvider.notifier)
|
||||
.maybeStartProxy(context);
|
||||
}
|
||||
},
|
||||
@@ -150,8 +146,6 @@ class ContainerListScreen extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () async {
|
||||
|
||||
+2
-7
@@ -36,13 +36,10 @@ class ContainerSelectionScreen extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final containersAsync = ref.watch(watchContainersWithCountProvider);
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Select Container')),
|
||||
body: HookConsumer(
|
||||
builder: (context, ref, child) {
|
||||
final containersAsync = ref.watch(watchContainersWithCountProvider);
|
||||
|
||||
return Skeletonizer(
|
||||
body: Skeletonizer(
|
||||
enabled: containersAsync.isLoading,
|
||||
child: containersAsync.when(
|
||||
skipLoadingOnReload: true,
|
||||
@@ -75,8 +72,6 @@ class ContainerSelectionScreen extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () async {
|
||||
|
||||
@@ -37,14 +37,12 @@ class FeedArticleListScreen extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Scaffold(
|
||||
body: NestedScrollView(
|
||||
floatHeaderSlivers: true,
|
||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||
return [
|
||||
HookConsumer(
|
||||
builder: (context, ref, child) {
|
||||
final tags = ref.watch(articleFilterProvider);
|
||||
final articlesAsync = ref.watch(
|
||||
// ignore: provider_parameters
|
||||
filteredArticleListProvider(feedId),
|
||||
);
|
||||
|
||||
final feedTitle = ref.watch(
|
||||
feedDataProvider(
|
||||
feedId,
|
||||
@@ -75,7 +73,12 @@ class FeedArticleListScreen extends HookConsumerWidget {
|
||||
return height;
|
||||
}, [tags.isNotEmpty]);
|
||||
|
||||
return SliverAppBar(
|
||||
return Scaffold(
|
||||
body: NestedScrollView(
|
||||
floatHeaderSlivers: true,
|
||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||
return [
|
||||
SliverAppBar(
|
||||
floating: true,
|
||||
title: Text(feedTitle ?? 'Articles'),
|
||||
bottom: PreferredSize(
|
||||
@@ -99,8 +102,7 @@ class FeedArticleListScreen extends HookConsumerWidget {
|
||||
)
|
||||
: SpeechToTextButton(
|
||||
onTextReceived: (data) {
|
||||
searchTextController.text = data
|
||||
.toString();
|
||||
searchTextController.text = data.toString();
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -148,19 +150,10 @@ class FeedArticleListScreen extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
];
|
||||
},
|
||||
body: Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final articlesAsync = ref.watch(
|
||||
// ignore: provider_parameters
|
||||
filteredArticleListProvider(feedId),
|
||||
);
|
||||
|
||||
return articlesAsync.when(
|
||||
body: articlesAsync.when(
|
||||
skipLoadingOnReload: true,
|
||||
data: (articles) {
|
||||
return RefreshIndicator(
|
||||
@@ -199,8 +192,6 @@ class FeedArticleListScreen extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
loading: () => const SizedBox.shrink(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user