From 4a97c0c5a0ab0eec4bbd723ba648e8e2ed1ccbcf Mon Sep 17 00:00:00 2001 From: ThatNerdSquared <72814106+ThatNerdSquared@users.noreply.github.com> Date: Thu, 2 Jan 2025 22:43:59 -0800 Subject: [PATCH] feat: add url scheme support, fix interaction bugs in cmd palette --- ios/Runner/Info.plist | 11 +++++ lib/context_menus.dart | 5 +++ lib/main.dart | 21 +++++++++- lib/widgets/entry_list_view.dart | 14 +++++++ lib/widgets/pret_command_palette.dart | 2 + linux/flutter/generated_plugin_registrant.cc | 4 ++ linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + macos/Podfile.lock | 8 +++- macos/Runner/Info.plist | 11 +++++ pubspec.lock | 40 +++++++++++++++++++ pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 ++ windows/flutter/generated_plugins.cmake | 1 + 14 files changed, 122 insertions(+), 2 deletions(-) diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 2b40b5c..1707f69 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -51,5 +51,16 @@ UIFileSharingEnabled + CFBundleURLTypes + + + CFBundleURLName + peregrine_url + CFBundleURLSchemes + + peregrine + + + diff --git a/lib/context_menus.dart b/lib/context_menus.dart index ffc1355..7368251 100644 --- a/lib/context_menus.dart +++ b/lib/context_menus.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:super_context_menu/super_context_menu.dart' as scm; import 'export_utils.dart'; @@ -69,6 +70,10 @@ scm.Menu buildEntryCardContextMenu({ title: 'Add as ancestor', callback: () => addAncestorCallback(entryId), ), + scm.MenuAction( + title: 'Copy Entry URL', + callback: () => Clipboard.setData(ClipboardData(text: 'peregrine://peregrine/entry/$entryId')), + ), scm.MenuAction( title: isEncrypted ? 'Decrypt Entry' : 'Encrypt Entry', callback: () => !isEncrypted ? toggleEncryptCallback() : null, diff --git a/lib/main.dart b/lib/main.dart index bbf2138..51d9d97 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:app_links/app_links.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:path_provider/path_provider.dart'; @@ -76,10 +77,13 @@ final currentAncestorsProvider = StateNotifierProvider>( (_) => CurrentAncestors(), ); +final currentJumpIdProvider = StateProvider((ref) => ''); FocusNode entryBoxFocusNode = FocusNode(); FocusNode searchBoxFocusNode = FocusNode(); +final appLinks = AppLinks(); + void main() async { WidgetsFlutterBinding.ensureInitialized(); platformAppSupportDir = (await getApplicationDocumentsDirectory()).path; @@ -107,8 +111,23 @@ class MyApp extends ConsumerWidget { class PeregrineHomeView extends ConsumerWidget { const PeregrineHomeView({super.key}); + void _handleUrl(uri, ref) { + final uriParts = uri.pathSegments; + if (uriParts[0] != 'entry') return; + + final entries = ref.read(filteredListProvider).keys.toList(); + final entryIndex = entries.indexOf(uriParts[1]); + if (entryIndex == -1) { + ref.read(entryFilterProvider.notifier).setAllEntriesFilter(); + } + ref + .read(currentJumpIdProvider.notifier) + .update((String state) => (uriParts[1]).toString()); + } + @override Widget build(BuildContext context, WidgetRef ref) { + appLinks.uriLinkStream.listen((uri) => _handleUrl(uri, ref)); final view = PretMainView( leftSidebar: Sidebar( searchBoxFocusNode: searchBoxFocusNode, @@ -127,7 +146,7 @@ class PeregrineHomeView extends ConsumerWidget { return Scaffold( backgroundColor: const Color(0xffb69d7c), body: PretCmdPaletteScope( - searchItems: ref.read(tagsProvider).keys.toList(), + searchItems: ref.watch(tagsProvider).keys.toList(), child: DesktopFrame( entryBoxFocusNode: entryBoxFocusNode, searchBoxFocusNode: searchBoxFocusNode, diff --git a/lib/widgets/entry_list_view.dart b/lib/widgets/entry_list_view.dart index c41833c..b26b539 100644 --- a/lib/widgets/entry_list_view.dart +++ b/lib/widgets/entry_list_view.dart @@ -27,6 +27,7 @@ class EntryListView extends ConsumerStatefulWidget { class EntryListViewState extends ConsumerState { final _scrollController = ScrollController(); + final _listController = ListController(); void scrollToBottom() => _scrollController.jumpTo( _scrollController.position.maxScrollExtent, @@ -35,6 +36,18 @@ class EntryListViewState extends ConsumerState { @override Widget build(BuildContext context) { var entries = ref.watch(filteredListProvider).keys.toList(); + final currentJumpId = ref.watch(currentJumpIdProvider); + + Future(() { + if (currentJumpId != '') { + ref.read(currentJumpIdProvider.notifier).update((state) => ''); + _listController.jumpToItem( + index: entries.indexOf(currentJumpId), + scrollController: _scrollController, + alignment: 0.5); + } + }); + final listView = buildEntryList(entries); return Scaffold( floatingActionButton: Container( @@ -111,6 +124,7 @@ class EntryListViewState extends ConsumerState { padding: EdgeInsets.all(PretConfig.defaultElementSpacing * 1.5), ), SuperSliverList.builder( + listController: _listController, itemCount: entries.length, itemBuilder: (context, index) => PeregrineEntryCard(entryId: entries[index])) diff --git a/lib/widgets/pret_command_palette.dart b/lib/widgets/pret_command_palette.dart index da10784..885febf 100644 --- a/lib/widgets/pret_command_palette.dart +++ b/lib/widgets/pret_command_palette.dart @@ -33,6 +33,8 @@ class PretCmdPaletteScopeState extends ConsumerState { void togglePalette() => setState(() { _isPaletteShown = !_isPaletteShown; + _controller.clear(); + filteredItems = widget.searchItems; selectedIndex = 0; _isPaletteShown ? paletteFocusNode.requestFocus() : null; }); diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index ea69a16..5053509 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,6 +7,7 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include @@ -15,6 +16,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) contextual_menu_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "ContextualMenuPlugin"); contextual_menu_plugin_register_with_registrar(contextual_menu_registrar); + g_autoptr(FlPluginRegistrar) gtk_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin"); + gtk_plugin_register_with_registrar(gtk_registrar); g_autoptr(FlPluginRegistrar) irondash_engine_context_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "IrondashEngineContextPlugin"); irondash_engine_context_plugin_register_with_registrar(irondash_engine_context_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index eeb12bb..d479700 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST contextual_menu + gtk irondash_engine_context super_native_extensions url_launcher_linux diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 00de2ad..b488065 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,7 @@ import FlutterMacOS import Foundation +import app_links import contextual_menu import device_info_plus import irondash_engine_context @@ -13,6 +14,7 @@ import super_native_extensions import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin")) ContextualMenuPlugin.register(with: registry.registrar(forPlugin: "ContextualMenuPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) IrondashEngineContextPlugin.register(with: registry.registrar(forPlugin: "IrondashEngineContextPlugin")) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 913ab43..67dae12 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,4 +1,6 @@ PODS: + - app_links (1.0.0): + - FlutterMacOS - contextual_menu (0.0.1): - FlutterMacOS - device_info_plus (0.0.1): @@ -15,6 +17,7 @@ PODS: - FlutterMacOS DEPENDENCIES: + - app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`) - contextual_menu (from `Flutter/ephemeral/.symlinks/plugins/contextual_menu/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - FlutterMacOS (from `Flutter/ephemeral`) @@ -24,6 +27,8 @@ DEPENDENCIES: - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) EXTERNAL SOURCES: + app_links: + :path: Flutter/ephemeral/.symlinks/plugins/app_links/macos contextual_menu: :path: Flutter/ephemeral/.symlinks/plugins/contextual_menu/macos device_info_plus: @@ -40,6 +45,7 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos SPEC CHECKSUMS: + app_links: 10e0a0ab602ffaf34d142cd4862f29d34b303b2a contextual_menu: 6d35fb15942c0d8769f5eae8d3bda653994a6f5a device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 @@ -50,4 +56,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist index 4789daa..c672ff1 100644 --- a/macos/Runner/Info.plist +++ b/macos/Runner/Info.plist @@ -28,5 +28,16 @@ MainMenu NSPrincipalClass NSApplication + CFBundleURLTypes + + + CFBundleURLName + peregrine_url + CFBundleURLSchemes + + peregrine + + + diff --git a/pubspec.lock b/pubspec.lock index 438beed..c242301 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -30,6 +30,38 @@ packages: url: "https://pub.dev" source: hosted version: "0.11.3" + app_links: + dependency: "direct main" + description: + name: app_links + sha256: "433df2e61b10519407475d7f69e470789d23d593f28224c38ba1068597be7950" + url: "https://pub.dev" + source: hosted + version: "6.3.3" + app_links_linux: + dependency: transitive + description: + name: app_links_linux + sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + app_links_platform_interface: + dependency: transitive + description: + name: app_links_platform_interface + sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + app_links_web: + dependency: transitive + description: + name: app_links_web + sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555 + url: "https://pub.dev" + source: hosted + version: "1.0.4" archive: dependency: transitive description: @@ -317,6 +349,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + gtk: + dependency: transitive + description: + name: gtk + sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c + url: "https://pub.dev" + source: hosted + version: "2.1.0" highlight: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 634cd62..d8f72c8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: file_picker: ^5.5.0 super_sliver_list: ^0.4.1 super_context_menu: ^0.8.15 + app_links: ^6.3.3 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 5dcc333..53ffc77 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,12 +6,15 @@ #include "generated_plugin_registrant.h" +#include #include #include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + AppLinksPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("AppLinksPluginCApi")); ContextualMenuPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ContextualMenuPlugin")); IrondashEngineContextPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index b75e7fa..8053410 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + app_links contextual_menu irondash_engine_context super_native_extensions