various ui improvements
This commit is contained in:
@@ -6,7 +6,7 @@ part of 'tab.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$tabRepositoryHash() => r'743732f6911372ea901b5a9402791569bfe80137';
|
||||
String _$tabRepositoryHash() => r'9b7ef03bec41f149b3cb456b73d7ee0e1b2804df';
|
||||
|
||||
/// See also [TabRepository].
|
||||
@ProviderFor(TabRepository)
|
||||
|
||||
@@ -39,10 +39,6 @@ class BrowserScreen extends HookConsumerWidget {
|
||||
final displayedSheet = ref.watch(bottomSheetControllerProvider);
|
||||
final displayedOverlay = ref.watch(overlayControllerProvider);
|
||||
|
||||
final selectedTabId = ref.watch(
|
||||
selectedTabStateProvider.select((value) => value?.id),
|
||||
);
|
||||
|
||||
final lastBackButtonPress = useRef<DateTime?>(null);
|
||||
|
||||
final overlayController = useOverlayPortalController();
|
||||
@@ -91,10 +87,7 @@ class BrowserScreen extends HookConsumerWidget {
|
||||
|
||||
return Visibility(
|
||||
visible: !tabInFullScreen,
|
||||
child: BrowserBottomAppBar(
|
||||
selectedTabId: selectedTabId,
|
||||
displayedSheet: displayedSheet,
|
||||
),
|
||||
child: BrowserBottomAppBar(displayedSheet: displayedSheet),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -129,10 +122,7 @@ class BrowserScreen extends HookConsumerWidget {
|
||||
: null,
|
||||
child: BackButtonListener(
|
||||
onBackButtonPressed: () async {
|
||||
final tabState =
|
||||
(selectedTabId != null)
|
||||
? ref.read(tabStateProvider(selectedTabId))
|
||||
: null;
|
||||
final tabState = ref.read(selectedTabStateProvider);
|
||||
|
||||
final tabCount = ref.read(
|
||||
tabListProvider.select((tabs) => tabs.value.length),
|
||||
@@ -167,7 +157,7 @@ class BrowserScreen extends HookConsumerWidget {
|
||||
lastBackButtonPress.value = null;
|
||||
|
||||
final controller = ref.read(
|
||||
tabSessionProvider(tabId: selectedTabId).notifier,
|
||||
selectedTabSessionNotifierProvider,
|
||||
);
|
||||
|
||||
await controller.stopLoading();
|
||||
@@ -176,7 +166,7 @@ class BrowserScreen extends HookConsumerWidget {
|
||||
lastBackButtonPress.value = null;
|
||||
|
||||
final controller = ref.read(
|
||||
tabSessionProvider(tabId: selectedTabId).notifier,
|
||||
selectedTabSessionNotifierProvider,
|
||||
);
|
||||
|
||||
await controller.goBack();
|
||||
@@ -190,7 +180,7 @@ class BrowserScreen extends HookConsumerWidget {
|
||||
|
||||
if (ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.hasLaunchedFromIntent(selectedTabId)) {
|
||||
.hasLaunchedFromIntent(tabState?.id)) {
|
||||
//Mark back as unhandled and navigator will pop
|
||||
await SystemNavigator.pop();
|
||||
return false;
|
||||
|
||||
+14
-8
@@ -7,6 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:lensai/core/routing/routes.dart';
|
||||
import 'package:lensai/features/geckoview/domain/controllers/bottom_sheet.dart';
|
||||
import 'package:lensai/features/geckoview/domain/providers.dart';
|
||||
import 'package:lensai/features/geckoview/domain/providers/selected_tab.dart';
|
||||
import 'package:lensai/features/geckoview/domain/providers/tab_session.dart';
|
||||
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
||||
import 'package:lensai/features/geckoview/domain/providers/web_extensions_state.dart';
|
||||
@@ -24,12 +25,8 @@ import 'package:lensai/utils/ui_helper.dart' as ui_helper;
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
class BrowserBottomAppBar extends HookConsumerWidget {
|
||||
const BrowserBottomAppBar({
|
||||
required this.selectedTabId,
|
||||
required this.displayedSheet,
|
||||
});
|
||||
const BrowserBottomAppBar({required this.displayedSheet});
|
||||
|
||||
final String? selectedTabId;
|
||||
final Sheet? displayedSheet;
|
||||
|
||||
@override
|
||||
@@ -39,17 +36,26 @@ class BrowserBottomAppBar extends HookConsumerWidget {
|
||||
final tabMenuController = useMenuController();
|
||||
final trippleDotMenuController = useMenuController();
|
||||
|
||||
final selectedTabId = ref.watch(selectedTabProvider);
|
||||
final isPrivateTab = ref.watch(
|
||||
selectedTabStateProvider.select((state) => state?.isPrivate ?? false),
|
||||
);
|
||||
|
||||
return BottomAppBar(
|
||||
height: AppBar().preferredSize.height,
|
||||
padding: EdgeInsets.zero,
|
||||
child: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
titleSpacing: 8.0,
|
||||
backgroundColor:
|
||||
(isPrivateTab && displayedSheet is! ViewTabsSheet)
|
||||
? const Color(0x648000D7)
|
||||
: null,
|
||||
title:
|
||||
(selectedTabId != null && displayedSheet is! ViewTabsSheet)
|
||||
? HookConsumer(
|
||||
builder: (context, ref, child) {
|
||||
final tabState = ref.watch(tabStateProvider(selectedTabId));
|
||||
final tabState = ref.watch(selectedTabStateProvider);
|
||||
|
||||
final dragStartPosition = useRef(Offset.zero);
|
||||
|
||||
@@ -111,7 +117,7 @@ class BrowserBottomAppBar extends HookConsumerWidget {
|
||||
onPressed: () async {
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.closeTab(selectedTabId!);
|
||||
.closeTab(selectedTabId);
|
||||
},
|
||||
leadingIcon: const Icon(Icons.close),
|
||||
child: const Text('Close Tab'),
|
||||
@@ -374,7 +380,7 @@ class BrowserBottomAppBar extends HookConsumerWidget {
|
||||
onPressed: () async {
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.closeTab(selectedTabId!);
|
||||
.closeTab(selectedTabId);
|
||||
trippleDotMenuController.close();
|
||||
},
|
||||
icon: const Icon(Icons.close),
|
||||
|
||||
+7
-2
@@ -11,6 +11,7 @@ import 'package:lensai/core/providers/global_drop.dart';
|
||||
import 'package:lensai/core/routing/routes.dart';
|
||||
import 'package:lensai/data/models/drag_data.dart';
|
||||
import 'package:lensai/features/geckoview/domain/providers/selected_tab.dart';
|
||||
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
||||
import 'package:lensai/features/geckoview/features/browser/domain/providers.dart';
|
||||
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/draggable_scrollable_header.dart';
|
||||
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/tab_preview.dart';
|
||||
@@ -91,7 +92,7 @@ class _TabSheetHeader extends HookConsumerWidget {
|
||||
// enableIMEPersonalizedLearning: !incognitoEnabled,
|
||||
decoration: InputDecoration(
|
||||
// border: InputBorder.none,
|
||||
prefixIcon: const Icon(Icons.search),
|
||||
prefixIcon: const Icon(MdiIcons.tabSearch),
|
||||
hintText: 'Search inside tabs...',
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
suffixIcon: Row(
|
||||
@@ -411,7 +412,11 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
|
||||
),
|
||||
child: FloatingActionButton.small(
|
||||
onPressed: () async {
|
||||
await const SearchRoute(tabType: TabType.regular).push(context);
|
||||
final isCurrentPrivate =
|
||||
ref.read(selectedTabStateProvider)?.isPrivate ?? false;
|
||||
await SearchRoute(
|
||||
tabType: isCurrentPrivate ? TabType.private : TabType.regular,
|
||||
).push(context);
|
||||
|
||||
onClose();
|
||||
},
|
||||
|
||||
@@ -87,7 +87,22 @@ class TabPreview extends StatelessWidget {
|
||||
),
|
||||
if (tab.isPrivate) ...[
|
||||
const SizedBox(width: 6.0),
|
||||
const Icon(MdiIcons.dominoMask, color: Color(0xFF8000D7)),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
width: 24,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned(
|
||||
top: -4,
|
||||
child: Icon(
|
||||
MdiIcons.dominoMask,
|
||||
color: Color(0xFF8000D7),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 8.0),
|
||||
],
|
||||
|
||||
+50
-44
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:lensai/features/geckoview/domain/entities/states/readerable.dart';
|
||||
@@ -27,59 +26,66 @@ class ReaderButton extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
|
||||
final icon = useMemoized(
|
||||
() =>
|
||||
readerabilityState.active
|
||||
? Icon(
|
||||
MdiIcons.bookOpen,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
)
|
||||
: const Icon(MdiIcons.bookOpenOutline, color: Colors.white),
|
||||
[readerabilityState.active],
|
||||
);
|
||||
final icon =
|
||||
readerabilityState.active
|
||||
? Icon(
|
||||
MdiIcons.bookOpen,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
)
|
||||
: Icon(
|
||||
MdiIcons.bookOpenOutline,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
);
|
||||
|
||||
return Visibility(
|
||||
visible:
|
||||
readerabilityState.readerable &&
|
||||
(enableReadability || readerabilityState.active),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 15.0, horizontal: 8.0),
|
||||
child: readerChanging.when(
|
||||
skipLoadingOnReload: true,
|
||||
data:
|
||||
(_) => Visibility(
|
||||
visible: readerabilityState.readerable,
|
||||
child: InkWell(
|
||||
onTap:
|
||||
readerChanging.isLoading
|
||||
? null
|
||||
: () async {
|
||||
await ref
|
||||
.read(
|
||||
readerableScreenControllerProvider.notifier,
|
||||
)
|
||||
.toggleReaderView(!readerabilityState.active);
|
||||
},
|
||||
child: readerChanging.when(
|
||||
skipLoadingOnReload: true,
|
||||
data:
|
||||
(_) => Visibility(
|
||||
visible: readerabilityState.readerable,
|
||||
child: InkWell(
|
||||
onTap:
|
||||
readerChanging.isLoading
|
||||
? null
|
||||
: () async {
|
||||
await ref
|
||||
.read(readerableScreenControllerProvider.notifier)
|
||||
.toggleReaderView(!readerabilityState.active);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 15.0,
|
||||
horizontal: 8.0,
|
||||
),
|
||||
child: icon,
|
||||
),
|
||||
),
|
||||
error: (error, stackTrace) => SizedBox.shrink(),
|
||||
loading:
|
||||
() => AnimateGradientShader(
|
||||
duration: const Duration(milliseconds: 500),
|
||||
primaryEnd: Alignment.bottomLeft,
|
||||
secondaryEnd: Alignment.topRight,
|
||||
primaryColors: [
|
||||
colorScheme.primary,
|
||||
colorScheme.primaryContainer,
|
||||
],
|
||||
secondaryColors: [
|
||||
colorScheme.secondary,
|
||||
colorScheme.secondaryContainer,
|
||||
],
|
||||
),
|
||||
error: (error, stackTrace) => SizedBox.shrink(),
|
||||
loading:
|
||||
() => AnimateGradientShader(
|
||||
duration: const Duration(milliseconds: 500),
|
||||
primaryEnd: Alignment.bottomLeft,
|
||||
secondaryEnd: Alignment.topRight,
|
||||
primaryColors: [
|
||||
colorScheme.primary,
|
||||
colorScheme.primaryContainer,
|
||||
],
|
||||
secondaryColors: [
|
||||
colorScheme.secondary,
|
||||
colorScheme.secondaryContainer,
|
||||
],
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 15.0,
|
||||
horizontal: 8.0,
|
||||
),
|
||||
child: icon,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -88,24 +88,33 @@ class SearchScreen extends HookConsumerWidget {
|
||||
pinned: true,
|
||||
automaticallyImplyLeading: false,
|
||||
title: Align(
|
||||
child: SegmentedButton(
|
||||
showSelectedIcon: false,
|
||||
segments: const [
|
||||
ButtonSegment(
|
||||
value: TabType.regular,
|
||||
label: Text('Regular'),
|
||||
icon: Icon(MdiIcons.tab),
|
||||
),
|
||||
ButtonSegment(
|
||||
value: TabType.private,
|
||||
label: Text('Private'),
|
||||
icon: Icon(MdiIcons.tabUnselected),
|
||||
),
|
||||
],
|
||||
selected: {selectedTabType.value},
|
||||
onSelectionChanged: (value) {
|
||||
selectedTabType.value = value.first;
|
||||
},
|
||||
child: Focus(
|
||||
canRequestFocus: false,
|
||||
child: SegmentedButton(
|
||||
showSelectedIcon: false,
|
||||
segments: const [
|
||||
ButtonSegment(
|
||||
value: TabType.regular,
|
||||
label: Text('Regular'),
|
||||
icon: Icon(MdiIcons.tab),
|
||||
),
|
||||
ButtonSegment(
|
||||
value: TabType.private,
|
||||
label: Text('Private'),
|
||||
icon: Icon(MdiIcons.tabUnselected),
|
||||
),
|
||||
],
|
||||
selected: {selectedTabType.value},
|
||||
onSelectionChanged: (value) {
|
||||
selectedTabType.value = value.first;
|
||||
},
|
||||
style: switch (selectedTabType.value) {
|
||||
TabType.regular => null,
|
||||
TabType.private => SegmentedButton.styleFrom(
|
||||
selectedBackgroundColor: const Color(0x648000D7),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
|
||||
@@ -63,6 +63,8 @@ class SelectableChips<T extends S, S, K> extends StatelessWidget {
|
||||
builder: (context, controller) {
|
||||
return ListView.builder(
|
||||
controller: controller,
|
||||
//Improve list performance by not rendering outside screen at all
|
||||
cacheExtent: 0,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: items.length,
|
||||
itemBuilder: (context, index) {
|
||||
|
||||
Reference in New Issue
Block a user