implemented find in page
This commit is contained in:
@@ -7,7 +7,7 @@ part of 'sync.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$bangSyncRepositoryHash() =>
|
String _$bangSyncRepositoryHash() =>
|
||||||
r'1e6341c8daf25aaee61d158f94445564d4450a9e';
|
r'86933b05d01629c67ed0443df91e991c40136423';
|
||||||
|
|
||||||
/// See also [BangSyncRepository].
|
/// See also [BangSyncRepository].
|
||||||
@ProviderFor(BangSyncRepository)
|
@ProviderFor(BangSyncRepository)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'sync.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$hostSyncRepositoryHash() =>
|
String _$hostSyncRepositoryHash() =>
|
||||||
r'22b89d3687c415441f99caa4d77dabaeb4969534';
|
r'5eed0c51e1b1e4dd1241634e297aff283eef01c5';
|
||||||
|
|
||||||
/// See also [HostSyncRepository].
|
/// See also [HostSyncRepository].
|
||||||
@ProviderFor(HostSyncRepository)
|
@ProviderFor(HostSyncRepository)
|
||||||
|
|||||||
@@ -125,3 +125,15 @@ class ActiveChatModel extends _$ActiveChatModel {
|
|||||||
return ChatModel.gpt4o;
|
return ChatModel.gpt4o;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Riverpod(keepAlive: true)
|
||||||
|
class ShowFindInPage extends _$ShowFindInPage {
|
||||||
|
void update(bool show) {
|
||||||
|
state = show;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool build() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -396,5 +396,20 @@ final activeChatModelProvider =
|
|||||||
);
|
);
|
||||||
|
|
||||||
typedef _$ActiveChatModel = Notifier<ChatModel>;
|
typedef _$ActiveChatModel = Notifier<ChatModel>;
|
||||||
|
String _$showFindInPageHash() => r'7ee5703f7d0c7e8a8dd6b0849d7b1e0a41fe24d9';
|
||||||
|
|
||||||
|
/// See also [ShowFindInPage].
|
||||||
|
@ProviderFor(ShowFindInPage)
|
||||||
|
final showFindInPageProvider = NotifierProvider<ShowFindInPage, bool>.internal(
|
||||||
|
ShowFindInPage.new,
|
||||||
|
name: r'showFindInPageProvider',
|
||||||
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$showFindInPageHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef _$ShowFindInPage = Notifier<bool>;
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
||||||
|
|||||||
@@ -434,6 +434,14 @@ class KagiScreen extends HookConsumerWidget {
|
|||||||
child: const Text('Share'),
|
child: const Text('Share'),
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
ref.read(showFindInPageProvider.notifier).update(true);
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(Icons.search),
|
||||||
|
child: const Text('Find in page'),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
MenuItemButton(
|
MenuItemButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await activeWebView?.currentController?.reload();
|
await activeWebView?.currentController?.reload();
|
||||||
|
|||||||
@@ -216,6 +216,28 @@ class _WebViewState extends ConsumerState<WebView> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final webViewProgress = useValueNotifier(100);
|
final webViewProgress = useValueNotifier(100);
|
||||||
|
final inPageSearchResult =
|
||||||
|
useValueNotifier<({int activeMatchOrdinal, int numberOfMatches})?>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
|
final findInteractionController = useMemoized(
|
||||||
|
() => FindInteractionController(
|
||||||
|
onFindResultReceived: (
|
||||||
|
controller,
|
||||||
|
activeMatchOrdinal,
|
||||||
|
numberOfMatches,
|
||||||
|
isDoneCounting,
|
||||||
|
) {
|
||||||
|
if (isDoneCounting) {
|
||||||
|
inPageSearchResult.value = (
|
||||||
|
activeMatchOrdinal: activeMatchOrdinal,
|
||||||
|
numberOfMatches: numberOfMatches,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
useOnAppLifecycleStateChange((previous, current) async {
|
useOnAppLifecycleStateChange((previous, current) async {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
@@ -242,6 +264,7 @@ class _WebViewState extends ConsumerState<WebView> {
|
|||||||
InAppWebView(
|
InAppWebView(
|
||||||
initialUrlRequest: URLRequest(url: WebUri.uri(widget.page.value.url)),
|
initialUrlRequest: URLRequest(url: WebUri.uri(widget.page.value.url)),
|
||||||
initialSettings: initialSettings,
|
initialSettings: initialSettings,
|
||||||
|
findInteractionController: findInteractionController,
|
||||||
contextMenu: ContextMenu(
|
contextMenu: ContextMenu(
|
||||||
menuItems: [
|
menuItems: [
|
||||||
ContextMenuItem(
|
ContextMenuItem(
|
||||||
@@ -524,6 +547,99 @@ class _WebViewState extends ConsumerState<WebView> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: HookConsumer(
|
||||||
|
builder: (context, ref, child) {
|
||||||
|
final showFindInPage = ref.watch(showFindInPageProvider);
|
||||||
|
|
||||||
|
final textController = useTextEditingController();
|
||||||
|
final progress = useValueListenable(webViewProgress);
|
||||||
|
|
||||||
|
return Visibility(
|
||||||
|
visible: showFindInPage,
|
||||||
|
child: Padding(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.only(bottom: (progress < 100) ? 4.0 : 0.0),
|
||||||
|
child: Material(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
controller: textController,
|
||||||
|
autofocus: true,
|
||||||
|
autocorrect: false,
|
||||||
|
decoration: const InputDecoration.collapsed(
|
||||||
|
hintText: 'Find in page',
|
||||||
|
),
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
onSubmitted: (value) async {
|
||||||
|
if (value == '') {
|
||||||
|
inPageSearchResult.value = null;
|
||||||
|
await findInteractionController.clearMatches();
|
||||||
|
} else {
|
||||||
|
await findInteractionController.findAll(
|
||||||
|
find: value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
HookConsumer(
|
||||||
|
builder: (context, ref, child) {
|
||||||
|
final searchResult =
|
||||||
|
useValueListenable(inPageSearchResult);
|
||||||
|
|
||||||
|
if (searchResult != null) {
|
||||||
|
if (searchResult.numberOfMatches == 0) {
|
||||||
|
return const Text('Not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Text(
|
||||||
|
'${searchResult.activeMatchOrdinal + 1} of ${searchResult.numberOfMatches}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_upward),
|
||||||
|
onPressed: () async {
|
||||||
|
await findInteractionController.findNext(
|
||||||
|
forward: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_downward),
|
||||||
|
onPressed: () async {
|
||||||
|
await findInteractionController.findNext();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.clear),
|
||||||
|
onPressed: () async {
|
||||||
|
ref
|
||||||
|
.read(showFindInPageProvider.notifier)
|
||||||
|
.update(false);
|
||||||
|
|
||||||
|
inPageSearchResult.value = null;
|
||||||
|
await findInteractionController.clearMatches();
|
||||||
|
textController.clear();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user