✨ App shortcuts
This commit is contained in:
@@ -271,6 +271,8 @@ PODS:
|
|||||||
- PromisesObjC (= 2.4.0)
|
- PromisesObjC (= 2.4.0)
|
||||||
- protocol_handler_ios (0.0.1):
|
- protocol_handler_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- quick_actions_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
- receive_sharing_intent (1.8.1):
|
- receive_sharing_intent (1.8.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- record_ios (1.1.0):
|
- record_ios (1.1.0):
|
||||||
@@ -365,6 +367,7 @@ DEPENDENCIES:
|
|||||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||||
- pointer_interceptor_ios (from `.symlinks/plugins/pointer_interceptor_ios/ios`)
|
- pointer_interceptor_ios (from `.symlinks/plugins/pointer_interceptor_ios/ios`)
|
||||||
- protocol_handler_ios (from `.symlinks/plugins/protocol_handler_ios/ios`)
|
- protocol_handler_ios (from `.symlinks/plugins/protocol_handler_ios/ios`)
|
||||||
|
- quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`)
|
||||||
- receive_sharing_intent (from `.symlinks/plugins/receive_sharing_intent/ios`)
|
- receive_sharing_intent (from `.symlinks/plugins/receive_sharing_intent/ios`)
|
||||||
- record_ios (from `.symlinks/plugins/record_ios/ios`)
|
- record_ios (from `.symlinks/plugins/record_ios/ios`)
|
||||||
- sensors_plus (from `.symlinks/plugins/sensors_plus/ios`)
|
- sensors_plus (from `.symlinks/plugins/sensors_plus/ios`)
|
||||||
@@ -481,6 +484,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/pointer_interceptor_ios/ios"
|
:path: ".symlinks/plugins/pointer_interceptor_ios/ios"
|
||||||
protocol_handler_ios:
|
protocol_handler_ios:
|
||||||
:path: ".symlinks/plugins/protocol_handler_ios/ios"
|
:path: ".symlinks/plugins/protocol_handler_ios/ios"
|
||||||
|
quick_actions_ios:
|
||||||
|
:path: ".symlinks/plugins/quick_actions_ios/ios"
|
||||||
receive_sharing_intent:
|
receive_sharing_intent:
|
||||||
:path: ".symlinks/plugins/receive_sharing_intent/ios"
|
:path: ".symlinks/plugins/receive_sharing_intent/ios"
|
||||||
record_ios:
|
record_ios:
|
||||||
@@ -567,6 +572,7 @@ SPEC CHECKSUMS:
|
|||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
||||||
protocol_handler_ios: 59f23ee71f3ec602d67902ca7f669a80957888d5
|
protocol_handler_ios: 59f23ee71f3ec602d67902ca7f669a80957888d5
|
||||||
|
quick_actions_ios: 500fcc11711d9f646739093395c4ae8eec25f779
|
||||||
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
||||||
record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374
|
record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374
|
||||||
SDWebImage: e9c98383c7572d713c1a0d7dd2783b10599b9838
|
SDWebImage: e9c98383c7572d713c1a0d7dd2783b10599b9838
|
||||||
|
|||||||
@@ -216,6 +216,8 @@
|
|||||||
};
|
};
|
||||||
7310A7D52EB10962002C0FD3 /* Solian Watch App */ = {
|
7310A7D52EB10962002C0FD3 /* Solian Watch App */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
);
|
||||||
path = "Solian Watch App";
|
path = "Solian Watch App";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -757,14 +759,10 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
name = "[CP] Copy Pods Resources";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||||
@@ -822,14 +820,10 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
@@ -880,14 +874,10 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App-frameworks.sh\"\n";
|
||||||
|
|||||||
6
ios/Runner/Assets.xcassets/Contents.json
Normal file
6
ios/Runner/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ import 'package:island/services/notify.dart';
|
|||||||
import 'package:island/services/widget_sync_service.dart';
|
import 'package:island/services/widget_sync_service.dart';
|
||||||
import 'package:island/services/timezone.dart';
|
import 'package:island/services/timezone.dart';
|
||||||
import 'package:island/services/app_intents.dart';
|
import 'package:island/services/app_intents.dart';
|
||||||
|
import 'package:island/services/quick_actions.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:relative_time/relative_time.dart';
|
import 'package:relative_time/relative_time.dart';
|
||||||
@@ -111,6 +112,17 @@ void main() async {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
talker.info("[QuickActions] Initializing Quick Actions service...");
|
||||||
|
final quickActionsService = QuickActionsService();
|
||||||
|
await quickActionsService.initialize();
|
||||||
|
talker.info("[QuickActions] Quick Actions service is ready!");
|
||||||
|
} catch (err) {
|
||||||
|
talker.error(
|
||||||
|
"[QuickActions] Failed to initialize Quick Actions service... $err",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
if (!kIsWeb && (Platform.isMacOS || Platform.isLinux || Platform.isWindows)) {
|
if (!kIsWeb && (Platform.isMacOS || Platform.isLinux || Platform.isWindows)) {
|
||||||
|
|||||||
89
lib/services/quick_actions.dart
Normal file
89
lib/services/quick_actions.dart
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:island/route.dart';
|
||||||
|
import 'package:island/services/event_bus.dart';
|
||||||
|
import 'package:island/talker.dart';
|
||||||
|
import 'package:quick_actions/quick_actions.dart';
|
||||||
|
|
||||||
|
class QuickActionsService {
|
||||||
|
static final QuickActionsService _instance = QuickActionsService._internal();
|
||||||
|
factory QuickActionsService() => _instance;
|
||||||
|
QuickActionsService._internal();
|
||||||
|
|
||||||
|
final QuickActions _quickActions = const QuickActions();
|
||||||
|
bool _initialized = false;
|
||||||
|
|
||||||
|
Future<void> initialize() async {
|
||||||
|
if (kIsWeb || (!Platform.isAndroid && !Platform.isIOS)) {
|
||||||
|
talker.warning(
|
||||||
|
'[QuickActions] Quick Actions only supported on Android and iOS',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_initialized) {
|
||||||
|
talker.info('[QuickActions] Already initialized');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
talker.info('[QuickActions] Initializing Quick Actions...');
|
||||||
|
|
||||||
|
// TODO Add icons for these
|
||||||
|
final shortcuts = <ShortcutItem>[
|
||||||
|
const ShortcutItem(type: 'compose_post', localizedTitle: 'New Post'),
|
||||||
|
const ShortcutItem(type: 'explore', localizedTitle: 'Explore'),
|
||||||
|
const ShortcutItem(type: 'chats', localizedTitle: 'Chats'),
|
||||||
|
const ShortcutItem(
|
||||||
|
type: 'notifications',
|
||||||
|
localizedTitle: 'Notifications',
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
await _quickActions.initialize(_handleShortcut);
|
||||||
|
await _quickActions.setShortcutItems(shortcuts);
|
||||||
|
|
||||||
|
_initialized = true;
|
||||||
|
talker.info('[QuickActions] Quick Actions initialized successfully');
|
||||||
|
} catch (e, stack) {
|
||||||
|
talker.error('[QuickActions] Initialization failed', e, stack);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleShortcut(String type) {
|
||||||
|
talker.info('[QuickActions] Shortcut tapped: $type');
|
||||||
|
|
||||||
|
final context = rootNavigatorKey.currentContext;
|
||||||
|
if (context == null) {
|
||||||
|
talker.warning('[QuickActions] Context not available, skipping action');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'compose_post':
|
||||||
|
eventBus.fire(const ShowComposeSheetEvent());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'explore':
|
||||||
|
context.go('/explore');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'chats':
|
||||||
|
context.go('/chat');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'notifications':
|
||||||
|
context.go('/notifications');
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
talker.warning('[QuickActions] Unknown shortcut type: $type');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
_initialized = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
pubspec.lock
32
pubspec.lock
@@ -2229,6 +2229,38 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.0"
|
version: "4.1.0"
|
||||||
|
quick_actions:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: quick_actions
|
||||||
|
sha256: "7e35dd6a21f5bbd21acf6899039eaf85001a5ac26d52cbd6a8a2814505b90798"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
quick_actions_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: quick_actions_android
|
||||||
|
sha256: "23f04632ada7fc16665d84ba54a0c792c09727e7fda6c989c6e6ba1853aa15dc"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.27"
|
||||||
|
quick_actions_ios:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: quick_actions_ios
|
||||||
|
sha256: a2e08ceb01f9d26e1b1826b1c4f5da6b7b6bbf61bcbaacd8e93dfff58b91f996
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.3"
|
||||||
|
quick_actions_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: quick_actions_platform_interface
|
||||||
|
sha256: "1fec7068db5122cd019e9340d3d7be5d36eab099695ef3402c7059ee058329a4"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
recase:
|
recase:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ dependencies:
|
|||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
flutter_hooks: ^0.21.3+1
|
flutter_hooks: ^0.21.3+1
|
||||||
hooks_riverpod: ^3.1.0
|
hooks_riverpod: ^3.1.0
|
||||||
|
quick_actions: ^1.0.8
|
||||||
go_router: ^17.0.1
|
go_router: ^17.0.1
|
||||||
styled_widget: ^0.4.1
|
styled_widget: ^0.4.1
|
||||||
shared_preferences: ^2.5.4
|
shared_preferences: ^2.5.4
|
||||||
|
|||||||
Reference in New Issue
Block a user