Command pattle basis

This commit is contained in:
2025-12-20 22:49:09 +08:00
parent 18c81503f1
commit 8c83ee9b88
12 changed files with 531 additions and 62 deletions

View File

@@ -93,7 +93,6 @@ class ChatSubscribeNotifier extends _$ChatSubscribeNotifier {
// Set up periodic subscribe timer (every 5 minutes) // Set up periodic subscribe timer (every 5 minutes)
_periodicSubscribeTimer = Timer.periodic(const Duration(minutes: 5), (_) { _periodicSubscribeTimer = Timer.periodic(const Duration(minutes: 5), (_) {
final wsState = ref.read(websocketStateProvider.notifier);
wsState.sendMessage( wsState.sendMessage(
jsonEncode( jsonEncode(
WebSocketPacket( WebSocketPacket(

View File

@@ -9,6 +9,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/pods/chat/chat_room.dart'; import 'package:island/pods/chat/chat_room.dart';
import 'package:island/pods/event_calendar.dart'; import 'package:island/pods/event_calendar.dart';
import 'package:island/screens/chat/chat.dart'; import 'package:island/screens/chat/chat.dart';
import 'package:island/services/event_bus.dart';
import 'package:island/services/responsive.dart'; import 'package:island/services/responsive.dart';
import 'package:island/widgets/account/fortune_graph.dart'; import 'package:island/widgets/account/fortune_graph.dart';
import 'package:island/widgets/account/friends_overview.dart'; import 'package:island/widgets/account/friends_overview.dart';
@@ -59,16 +60,27 @@ class DashboardGrid extends HookConsumerWidget {
constraints: const BoxConstraints(minHeight: 56), constraints: const BoxConstraints(minHeight: 56),
leading: const Icon(Symbols.search).padding(horizontal: 24), leading: const Icon(Symbols.search).padding(horizontal: 24),
readOnly: true, readOnly: true,
onTap: () {
eventBus.fire(CommandPaletteTriggerEvent());
},
), ),
), ),
Expanded( Expanded(
child: SingleChildScrollView( child:
SingleChildScrollView(
padding: isWide padding: isWide
? const EdgeInsets.symmetric(horizontal: 24) ? const EdgeInsets.symmetric(horizontal: 24)
: const EdgeInsets.only(bottom: 64), : const EdgeInsets.only(bottom: 64),
scrollDirection: isWide ? Axis.horizontal : Axis.vertical, scrollDirection: isWide ? Axis.horizontal : Axis.vertical,
child: isWide ? _DashboardGridWide() : _DashboardGridNarrow(), child: isWide
).clipRRect(topLeft: 12, topRight: 12).padding(horizontal: 24), ? _DashboardGridWide()
: _DashboardGridNarrow(),
)
.clipRRect(
topLeft: isWide ? 0 : 12,
topRight: isWide ? 0 : 12,
)
.padding(horizontal: isWide ? 0 : 24),
), ),
], ],
), ),
@@ -545,16 +557,22 @@ class FortuneCard extends HookWidget {
margin: EdgeInsets.zero, margin: EdgeInsets.zero,
color: Theme.of(context).colorScheme.surfaceContainer, color: Theme.of(context).colorScheme.surfaceContainer,
shape: const RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)), borderRadius: BorderRadius.all(Radius.circular(12)),
), ),
child: Row( child: Row(
spacing: 8, spacing: 8,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Expanded(child: Text(fortune['text']!)), Expanded(
child: Text(
fortune['text']!,
maxLines: 2,
overflow: TextOverflow.fade,
),
),
Text(fortune['author']!).bold(), Text(fortune['author']!).bold(),
], ],
).padding(horizontal: 24), ).padding(horizontal: 16),
).height(48); ).height(48);
} }
} }

View File

@@ -23,3 +23,8 @@ class OidcAuthCallbackEvent {
const OidcAuthCallbackEvent(this.challengeId); const OidcAuthCallbackEvent(this.challengeId);
} }
/// Event fired to trigger the command palette
class CommandPaletteTriggerEvent {
const CommandPaletteTriggerEvent();
}

View File

@@ -12,8 +12,10 @@ import 'package:island/pods/config.dart';
import 'package:island/route.dart'; import 'package:island/route.dart';
import 'package:island/pods/userinfo.dart'; import 'package:island/pods/userinfo.dart';
import 'package:island/pods/websocket.dart'; import 'package:island/pods/websocket.dart';
import 'package:island/services/event_bus.dart';
import 'package:island/services/responsive.dart'; import 'package:island/services/responsive.dart';
import 'package:island/widgets/alert.dart'; import 'package:island/widgets/alert.dart';
import 'package:island/widgets/cmp/pattle.dart';
import 'package:island/widgets/upload_overlay.dart'; import 'package:island/widgets/upload_overlay.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
@@ -36,6 +38,14 @@ class WindowScaffold extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final isMaximized = useState(false); final isMaximized = useState(false);
final showPalette = useState(false);
final lastShiftTime = useState<DateTime?>(null);
final keyboardFocusNode = useFocusNode();
useEffect(() {
keyboardFocusNode.requestFocus();
return null;
}, []);
// Add window resize listener for desktop platforms // Add window resize listener for desktop platforms
useEffect(() { useEffect(() {
@@ -68,6 +78,15 @@ class WindowScaffold extends HookConsumerWidget {
return null; return null;
}, []); }, []);
// Event bus listener for command palette
final subscription = useMemoized(
() => eventBus.on<CommandPaletteTriggerEvent>().listen(
(_) => showPalette.value = true,
),
[],
);
useEffect(() => subscription.cancel, [subscription]);
final router = ref.watch(routerProvider); final router = ref.watch(routerProvider);
final pageActionsButton = [ final pageActionsButton = [
@@ -98,6 +117,20 @@ class WindowScaffold extends HookConsumerWidget {
shortcuts: <LogicalKeySet, Intent>{ shortcuts: <LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.escape): const PopIntent(), LogicalKeySet(LogicalKeyboardKey.escape): const PopIntent(),
}, },
child: KeyboardListener(
focusNode: keyboardFocusNode,
onKeyEvent: (event) {
if (event is KeyDownEvent &&
(event.logicalKey == LogicalKeyboardKey.shiftLeft ||
event.logicalKey == LogicalKeyboardKey.shiftRight)) {
final now = DateTime.now();
if (lastShiftTime.value != null &&
now.difference(lastShiftTime.value!).inMilliseconds < 300) {
showPalette.value = true;
}
lastShiftTime.value = now;
}
},
child: Actions( child: Actions(
actions: <Type, Action<Intent>>{PopIntent: PopAction(ref)}, actions: <Type, Action<Intent>>{PopIntent: PopAction(ref)},
child: Material( child: Material(
@@ -108,8 +141,7 @@ class WindowScaffold extends HookConsumerWidget {
Column( Column(
children: [ children: [
DragToMoveArea( DragToMoveArea(
child: child: Platform.isMacOS
Platform.isMacOS
? Stack( ? Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
@@ -126,8 +158,7 @@ class WindowScaffold extends HookConsumerWidget {
'Solar Network', 'Solar Network',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
color: color: Theme.of(
Theme.of(
context, context,
).colorScheme.onSurface, ).colorScheme.onSurface,
), ),
@@ -199,10 +230,15 @@ class WindowScaffold extends HookConsumerWidget {
), ),
_WebSocketIndicator(), _WebSocketIndicator(),
const UploadOverlay(), const UploadOverlay(),
if (showPalette.value)
CommandPattleWidget(
onDismiss: () => showPalette.value = false,
),
], ],
), ),
), ),
), ),
),
); );
} }
@@ -210,6 +246,20 @@ class WindowScaffold extends HookConsumerWidget {
shortcuts: <LogicalKeySet, Intent>{ shortcuts: <LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.escape): const PopIntent(), LogicalKeySet(LogicalKeyboardKey.escape): const PopIntent(),
}, },
child: KeyboardListener(
focusNode: keyboardFocusNode,
onKeyEvent: (event) {
if (event is KeyDownEvent &&
(event.logicalKey == LogicalKeyboardKey.shiftLeft ||
event.logicalKey == LogicalKeyboardKey.shiftRight)) {
final now = DateTime.now();
if (lastShiftTime.value != null &&
now.difference(lastShiftTime.value!).inMilliseconds < 300) {
showPalette.value = true;
}
lastShiftTime.value = now;
}
},
child: Actions( child: Actions(
actions: <Type, Action<Intent>>{PopIntent: PopAction(ref)}, actions: <Type, Action<Intent>>{PopIntent: PopAction(ref)},
child: Stack( child: Stack(
@@ -218,9 +268,12 @@ class WindowScaffold extends HookConsumerWidget {
Positioned.fill(child: child), Positioned.fill(child: child),
_WebSocketIndicator(), _WebSocketIndicator(),
const UploadOverlay(), const UploadOverlay(),
if (showPalette.value)
CommandPattleWidget(onDismiss: () => showPalette.value = false),
], ],
), ),
), ),
),
); );
} }
} }
@@ -463,8 +516,7 @@ class AppBackground extends ConsumerWidget {
); );
}, },
loading: () => const SizedBox(), loading: () => const SizedBox(),
error: error: (_, _) => Material(
(_, _) => Material(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surface,
child: child, child: child,
), ),
@@ -537,8 +589,7 @@ class _WebSocketIndicator extends HookConsumerWidget {
duration: Duration(milliseconds: 300), duration: Duration(milliseconds: 300),
color: indicatorColor, color: indicatorColor,
child: Center( child: Center(
child: child: Text(
Text(
indicatorText, indicatorText,
style: TextStyle(color: Colors.white, fontSize: 16), style: TextStyle(color: Colors.white, fontSize: 16),
).tr(), ).tr(),

336
lib/widgets/cmp/pattle.dart Normal file
View File

@@ -0,0 +1,336 @@
import 'dart:io';
import 'dart:math' as math;
import 'dart:ui';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:island/models/chat.dart';
import 'package:island/pods/chat/chat_room.dart';
import 'package:island/pods/chat/chat_summary.dart';
import 'package:island/pods/userinfo.dart';
import 'package:island/route.dart';
import 'package:island/services/responsive.dart';
import 'package:island/widgets/content/cloud_files.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:relative_time/relative_time.dart';
import 'package:styled_widget/styled_widget.dart';
class CommandPattleWidget extends HookConsumerWidget {
final VoidCallback onDismiss;
const CommandPattleWidget({super.key, required this.onDismiss});
@override
Widget build(BuildContext context, WidgetRef ref) {
final textController = useTextEditingController();
final focusNode = useFocusNode();
final searchQuery = useState('');
final focusedIndex = useState<int?>(null);
useEffect(() {
focusNode.requestFocus();
return null;
}, []);
useEffect(() {
void listener() {
searchQuery.value = textController.text;
// Reset focused index when search changes
focusedIndex.value = null;
}
textController.addListener(listener);
return () => textController.removeListener(listener);
}, [textController]);
final chatRooms = ref.watch(chatRoomJoinedProvider);
final userInfo = ref.watch(userInfoProvider);
bool isDesktop() =>
kIsWeb ||
(!kIsWeb &&
(Platform.isWindows || Platform.isLinux || Platform.isMacOS));
final filteredRooms = chatRooms.maybeWhen(
data: (rooms) {
if (searchQuery.value.isEmpty) return <SnChatRoom>[];
return rooms
.where((room) {
final title = room.name ?? '';
final desc = room.description ?? '';
final query = searchQuery.value.toLowerCase();
return title.toLowerCase().contains(query) ||
desc.toLowerCase().contains(query) ||
(room.members?.any(
(member) =>
member.account.name.contains(query) ||
member.account.nick.contains(query),
) ??
false);
})
.take(5) // Limit to 5 results
.toList();
},
orElse: () => <SnChatRoom>[],
);
return KeyboardListener(
focusNode: FocusNode(),
onKeyEvent: (event) {
if (event is KeyDownEvent) {
if (event.logicalKey == LogicalKeyboardKey.escape) {
onDismiss();
} else if (isDesktop()) {
if (event.logicalKey == LogicalKeyboardKey.enter ||
event.logicalKey == LogicalKeyboardKey.numpadEnter) {
if (focusedIndex.value != null &&
focusedIndex.value! < filteredRooms.length) {
_navigateToRoom(
context,
ref,
filteredRooms[focusedIndex.value!],
);
}
} else if (event.logicalKey == LogicalKeyboardKey.arrowUp) {
if (filteredRooms.isNotEmpty) {
if (focusedIndex.value == null) {
focusedIndex.value = 0;
} else {
focusedIndex.value = math.max(0, focusedIndex.value! - 1);
}
}
} else if (event.logicalKey == LogicalKeyboardKey.arrowDown) {
if (filteredRooms.isNotEmpty) {
if (focusedIndex.value == null) {
focusedIndex.value = 0;
} else {
focusedIndex.value = math.min(
filteredRooms.length - 1,
focusedIndex.value! + 1,
);
}
}
}
}
}
},
child: GestureDetector(
onTap: onDismiss,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: Container(
color: Colors.black.withOpacity(0.5),
child: Center(
child: GestureDetector(
onTap: () {}, // Prevent tap from dismissing when tapping inside
child: Container(
width: math.max(MediaQuery.of(context).size.width * 0.6, 320),
constraints: const BoxConstraints(
maxWidth: 600,
maxHeight: 500,
),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(24),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
blurRadius: 10,
spreadRadius: 2,
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SearchBar(
controller: textController,
focusNode: focusNode,
hintText: 'Search chats...',
leading: const Icon(
Symbols.keyboard_command_key,
).padding(horizontal: 8),
onSubmitted: (_) {
if (filteredRooms.isNotEmpty) {
_navigateToRoom(context, ref, filteredRooms.first);
}
},
),
if (filteredRooms.isNotEmpty)
Flexible(
child: ListView.builder(
shrinkWrap: true,
itemCount: filteredRooms.length,
itemBuilder: (context, index) {
final room = filteredRooms[index];
return _ChatRoomSearchResult(
room: room,
isFocused: index == focusedIndex.value,
onTap: () =>
_navigateToRoom(context, ref, room),
);
},
),
),
],
),
),
),
),
),
),
),
);
}
void _navigateToRoom(BuildContext context, WidgetRef ref, SnChatRoom room) {
onDismiss();
if (isWideScreen(context)) {
ref
.read(routerProvider)
.replaceNamed('chatRoom', pathParameters: {'id': room.id});
} else {
ref
.read(routerProvider)
.pushNamed('chatRoom', pathParameters: {'id': room.id});
}
}
}
class _ChatRoomSearchResult extends HookConsumerWidget {
final SnChatRoom room;
final bool isFocused;
final VoidCallback onTap;
const _ChatRoomSearchResult({
required this.room,
required this.isFocused,
required this.onTap,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final userInfo = ref.watch(userInfoProvider);
final summary = ref
.watch(chatSummaryProvider)
.whenData((summaries) => summaries[room.id]);
var validMembers = room.members ?? [];
if (validMembers.isNotEmpty && userInfo.value != null) {
validMembers = validMembers
.where((e) => e.accountId != userInfo.value!.id)
.toList();
}
String titleText;
if (room.type == 1 && room.name == null) {
if (room.members?.isNotEmpty ?? false) {
titleText = validMembers.map((e) => e.account.nick).join(', ');
} else {
titleText = 'Direct Message';
}
} else {
titleText = room.name ?? '';
}
Widget buildSubtitle() {
return summary.when(
data: (data) => data == null
? (room.type == 1 && room.description == null
? Text(
validMembers.map((e) => '@${e.account.name}').join(', '),
)
: Text(room.description ?? ''))
: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (data.unreadCount > 0)
Text(
'unreadMessages'.plural(data.unreadCount),
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).colorScheme.primary,
),
),
if (data.lastMessage == null)
room.type == 1 && room.description == null
? Text(
validMembers
.map((e) => '@${e.account.name}')
.join(', '),
)
: Text(room.description ?? '')
else
Row(
spacing: 4,
children: [
Badge(
label: Text(data.lastMessage!.sender.account.nick),
textColor: Theme.of(context).colorScheme.onPrimary,
backgroundColor: Theme.of(
context,
).colorScheme.primary,
),
Expanded(
child: Text(
(data.lastMessage!.content?.isNotEmpty ?? false)
? data.lastMessage!.content!
: 'messageNone'.tr(),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodySmall,
),
),
Align(
alignment: Alignment.centerRight,
child: Text(
RelativeTime(
context,
).format(data.lastMessage!.createdAt),
style: Theme.of(context).textTheme.bodySmall,
),
),
],
),
],
),
loading: () => room.type == 1 && room.description == null
? Text(validMembers.map((e) => '@${e.account.name}').join(', '))
: Text(room.description ?? ''),
error: (_, _) => room.type == 1 && room.description == null
? Text(validMembers.map((e) => '@${e.account.name}').join(', '))
: Text(room.description ?? ''),
);
}
final isDirect = room.type == 1;
return ListTile(
tileColor: isFocused
? Theme.of(context).colorScheme.surfaceContainerHighest
: null,
leading: Badge(
isLabelVisible: summary.maybeWhen(
data: (data) => (data?.unreadCount ?? 0) > 0,
orElse: () => false,
),
child: (isDirect && room.picture?.id == null)
? SplitAvatarWidget(
filesId: validMembers
.map((e) => e.account.profile.picture?.id)
.toList(),
)
: room.picture?.id == null
? CircleAvatar(child: Text((room.name ?? 'DM')[0].toUpperCase()))
: ProfilePictureWidget(
fileId: room.picture?.id,
), // Placeholder for now
),
title: Text(titleText),
subtitle: buildSubtitle(),
onTap: onTap,
);
}
}

View File

@@ -13,6 +13,7 @@
#include <flutter_timezone/flutter_timezone_plugin.h> #include <flutter_timezone/flutter_timezone_plugin.h>
#include <flutter_udid/flutter_udid_plugin.h> #include <flutter_udid/flutter_udid_plugin.h>
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h> #include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
#include <hotkey_manager_linux/hotkey_manager_linux_plugin.h>
#include <irondash_engine_context/irondash_engine_context_plugin.h> #include <irondash_engine_context/irondash_engine_context_plugin.h>
#include <livekit_client/live_kit_plugin.h> #include <livekit_client/live_kit_plugin.h>
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h> #include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
@@ -49,6 +50,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flutter_webrtc_registrar = g_autoptr(FlPluginRegistrar) flutter_webrtc_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterWebRTCPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterWebRTCPlugin");
flutter_web_r_t_c_plugin_register_with_registrar(flutter_webrtc_registrar); flutter_web_r_t_c_plugin_register_with_registrar(flutter_webrtc_registrar);
g_autoptr(FlPluginRegistrar) hotkey_manager_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "HotkeyManagerLinuxPlugin");
hotkey_manager_linux_plugin_register_with_registrar(hotkey_manager_linux_registrar);
g_autoptr(FlPluginRegistrar) irondash_engine_context_registrar = g_autoptr(FlPluginRegistrar) irondash_engine_context_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "IrondashEngineContextPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "IrondashEngineContextPlugin");
irondash_engine_context_plugin_register_with_registrar(irondash_engine_context_registrar); irondash_engine_context_plugin_register_with_registrar(irondash_engine_context_registrar);

View File

@@ -10,6 +10,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
flutter_timezone flutter_timezone
flutter_udid flutter_udid
flutter_webrtc flutter_webrtc
hotkey_manager_linux
irondash_engine_context irondash_engine_context
livekit_client livekit_client
media_kit_libs_linux media_kit_libs_linux

View File

@@ -22,6 +22,7 @@ import flutter_timezone
import flutter_udid import flutter_udid
import flutter_webrtc import flutter_webrtc
import gal import gal
import hotkey_manager_macos
import irondash_engine_context import irondash_engine_context
import livekit_client import livekit_client
import local_auth_darwin import local_auth_darwin
@@ -63,6 +64,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin")) FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin")) FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin"))
GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin")) GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin"))
HotkeyManagerMacosPlugin.register(with: registry.registrar(forPlugin: "HotkeyManagerMacosPlugin"))
IrondashEngineContextPlugin.register(with: registry.registrar(forPlugin: "IrondashEngineContextPlugin")) IrondashEngineContextPlugin.register(with: registry.registrar(forPlugin: "IrondashEngineContextPlugin"))
LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin")) LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin"))
LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin"))

View File

@@ -1309,6 +1309,46 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.3"
hotkey_manager:
dependency: "direct main"
description:
name: hotkey_manager
sha256: "06f0655b76c8dd322fb7101dc615afbdbf39c3d3414df9e059c33892104479cd"
url: "https://pub.dev"
source: hosted
version: "0.2.3"
hotkey_manager_linux:
dependency: transitive
description:
name: hotkey_manager_linux
sha256: "83676bda8210a3377bc6f1977f193bc1dbdd4c46f1bdd02875f44b6eff9a8473"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
hotkey_manager_macos:
dependency: transitive
description:
name: hotkey_manager_macos
sha256: "03b5967e64357b9ac05188ea4a5df6fe4ed4205762cb80aaccf8916ee1713c96"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
hotkey_manager_platform_interface:
dependency: transitive
description:
name: hotkey_manager_platform_interface
sha256: "98ffca25b8cc9081552902747b2942e3bc37855389a4218c9d50ca316b653b13"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
hotkey_manager_windows:
dependency: transitive
description:
name: hotkey_manager_windows
sha256: "0d03ced9fe563ed0b68f0a0e1b22c9ffe26eb8053cb960e401f68a4f070e0117"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
hotreloader: hotreloader:
dependency: transitive dependency: transitive
description: description:
@@ -2948,6 +2988,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.4.0"
uni_platform:
dependency: transitive
description:
name: uni_platform
sha256: e02213a7ee5352212412ca026afd41d269eb00d982faa552f419ffc2debfad84
url: "https://pub.dev"
source: hosted
version: "0.1.3"
universal_io: universal_io:
dependency: transitive dependency: transitive
description: description:

View File

@@ -172,6 +172,7 @@ dependencies:
flutter_code_editor: ^0.3.5 flutter_code_editor: ^0.3.5
skeletonizer: ^2.1.2 skeletonizer: ^2.1.2
permission_handler: ^12.0.1 permission_handler: ^12.0.1
hotkey_manager: ^0.2.3
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@@ -18,6 +18,7 @@
#include <flutter_udid/flutter_udid_plugin_c_api.h> #include <flutter_udid/flutter_udid_plugin_c_api.h>
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h> #include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
#include <gal/gal_plugin_c_api.h> #include <gal/gal_plugin_c_api.h>
#include <hotkey_manager_windows/hotkey_manager_windows_plugin_c_api.h>
#include <irondash_engine_context/irondash_engine_context_plugin_c_api.h> #include <irondash_engine_context/irondash_engine_context_plugin_c_api.h>
#include <livekit_client/live_kit_plugin.h> #include <livekit_client/live_kit_plugin.h>
#include <local_auth_windows/local_auth_plugin.h> #include <local_auth_windows/local_auth_plugin.h>
@@ -62,6 +63,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("FlutterWebRTCPlugin")); registry->GetRegistrarForPlugin("FlutterWebRTCPlugin"));
GalPluginCApiRegisterWithRegistrar( GalPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("GalPluginCApi")); registry->GetRegistrarForPlugin("GalPluginCApi"));
HotkeyManagerWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("HotkeyManagerWindowsPluginCApi"));
IrondashEngineContextPluginCApiRegisterWithRegistrar( IrondashEngineContextPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("IrondashEngineContextPluginCApi")); registry->GetRegistrarForPlugin("IrondashEngineContextPluginCApi"));
LiveKitPluginRegisterWithRegistrar( LiveKitPluginRegisterWithRegistrar(

View File

@@ -15,6 +15,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
flutter_udid flutter_udid
flutter_webrtc flutter_webrtc
gal gal
hotkey_manager_windows
irondash_engine_context irondash_engine_context
livekit_client livekit_client
local_auth_windows local_auth_windows