🐛 Bug fixes android sharing, ios notifications and more
This commit is contained in:
parent
243ecb3f71
commit
a23dcfe702
@ -46,12 +46,37 @@
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:mimeType="image/*" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:mimeType="image/*" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="video/*" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="video/*" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/*" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="application/*" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="application/*" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
|
@ -987,7 +987,7 @@
|
||||
INFOPLIST_FILE = SolianNotificationService/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = SolianNotificationService;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@ -1029,7 +1029,7 @@
|
||||
INFOPLIST_FILE = SolianNotificationService/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = SolianNotificationService;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@ -1068,7 +1068,7 @@
|
||||
INFOPLIST_FILE = SolianNotificationService/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = SolianNotificationService;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
@ -11,6 +11,21 @@ import UIKit
|
||||
) -> Bool {
|
||||
UNUserNotificationCenter.current().delegate = notifyDelegate
|
||||
|
||||
let replyableMessageCategory = UNNotificationCategory(
|
||||
identifier: "REPLYABLE_MESSAGE",
|
||||
actions: [
|
||||
UNTextInputNotificationAction(
|
||||
identifier: "reply_action",
|
||||
title: "Reply",
|
||||
options: []
|
||||
),
|
||||
],
|
||||
intentIdentifiers: [],
|
||||
options: []
|
||||
)
|
||||
|
||||
UNUserNotificationCenter.current().setNotificationCategories([replyableMessageCategory])
|
||||
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
|
@ -10,14 +10,26 @@ import Alamofire
|
||||
|
||||
class NotifyDelegate: UIResponder, UNUserNotificationCenterDelegate {
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||
if let textResponse = response as? UNTextInputNotificationResponse {
|
||||
let content = response.notification.request.content
|
||||
guard let metadata = content.userInfo["meta"] as? [AnyHashable: Any] else {
|
||||
guard let textResponse = response as? UNTextInputNotificationResponse else {
|
||||
completionHandler()
|
||||
return
|
||||
}
|
||||
|
||||
var token: String? = UserDefaults.standard.getFlutterToken()
|
||||
if token == nil {
|
||||
let content = response.notification.request.content
|
||||
|
||||
// Only handle replies for new messages
|
||||
guard let notificationType = content.userInfo["type"] as? String, notificationType == "messages.new" else {
|
||||
completionHandler()
|
||||
return
|
||||
}
|
||||
|
||||
guard let metadata = content.userInfo["meta"] as? [AnyHashable: Any] else {
|
||||
completionHandler()
|
||||
return
|
||||
}
|
||||
|
||||
guard let token = UserDefaults.standard.getFlutterToken() else {
|
||||
completionHandler()
|
||||
return
|
||||
}
|
||||
|
||||
@ -30,7 +42,7 @@ class NotifyDelegate: UIResponder, UNUserNotificationCenterDelegate {
|
||||
]
|
||||
|
||||
AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: HTTPHeaders(
|
||||
[HTTPHeader(name: "Authorization", value: "AtField \(token!)")]
|
||||
[HTTPHeader(name: "Authorization", value: "AtField \(token)")]
|
||||
))
|
||||
.validate()
|
||||
.responseString { response in
|
||||
@ -41,9 +53,8 @@ class NotifyDelegate: UIResponder, UNUserNotificationCenterDelegate {
|
||||
print("Failed to send chat reply message: \(error)")
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call completion handler after network request is finished
|
||||
completionHandler()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,21 +60,7 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
|
||||
let pfpIdentifier = meta["pfp"] as? String
|
||||
|
||||
let replyableMessageCategory = UNNotificationCategory(
|
||||
identifier: content.categoryIdentifier,
|
||||
actions: [
|
||||
UNTextInputNotificationAction(
|
||||
identifier: "reply_action",
|
||||
title: "Reply",
|
||||
options: []
|
||||
),
|
||||
],
|
||||
intentIdentifiers: [],
|
||||
options: []
|
||||
)
|
||||
|
||||
UNUserNotificationCenter.current().setNotificationCategories([replyableMessageCategory])
|
||||
content.categoryIdentifier = replyableMessageCategory.identifier
|
||||
content.categoryIdentifier = "REPLYABLE_MESSAGE"
|
||||
|
||||
let metaCopy = meta as? [String: Any] ?? [:]
|
||||
let pfpUrl = pfpIdentifier != nil ? getAttachmentUrl(for: pfpIdentifier!) : nil
|
||||
|
@ -53,7 +53,10 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
// Standalone routes without bottom navigation
|
||||
GoRoute(
|
||||
path: '/posts/compose',
|
||||
builder: (context, state) => const PostComposeScreen(),
|
||||
builder:
|
||||
(context, state) => PostComposeScreen(
|
||||
initialState: state.extra as PostComposeInitialState?,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/posts/:id/edit',
|
||||
|
@ -54,6 +54,7 @@ Future<SnSubscriptionStatus> publisherSubscriptionStatus(
|
||||
|
||||
@riverpod
|
||||
Future<Color?> publisherAppbarForcegroundColor(Ref ref, String pubName) async {
|
||||
try {
|
||||
final publisher = await ref.watch(publisherProvider(pubName).future);
|
||||
if (publisher.background == null) return null;
|
||||
final palette = await PaletteGenerator.fromImageProvider(
|
||||
@ -65,14 +66,14 @@ Future<Color?> publisherAppbarForcegroundColor(Ref ref, String pubName) async {
|
||||
final dominantColor = palette.dominantColor?.color;
|
||||
if (dominantColor == null) return null;
|
||||
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class PublisherProfileScreen extends HookConsumerWidget {
|
||||
final String name;
|
||||
const PublisherProfileScreen({
|
||||
super.key,
|
||||
required this.name,
|
||||
});
|
||||
const PublisherProfileScreen({super.key, required this.name});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
|
@ -186,13 +186,7 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
||||
Future<void> saveToGallery() async {
|
||||
try {
|
||||
// Show loading indicator
|
||||
final scaffold = ScaffoldMessenger.of(context);
|
||||
scaffold.showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Saving image to gallery...'),
|
||||
duration: Duration(seconds: 1),
|
||||
),
|
||||
);
|
||||
showSnackBar('Saving image to gallery...');
|
||||
|
||||
// Get the image URL
|
||||
final client = ref.watch(apiClientProvider);
|
||||
@ -209,12 +203,7 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
||||
await Gal.putImage(filePath, album: 'Solar Network');
|
||||
|
||||
// Show success message
|
||||
scaffold.showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Image saved to gallery'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
showSnackBar('Image saved to gallery');
|
||||
} catch (e) {
|
||||
showErrorAlert(e);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class PublisherCard extends ConsumerWidget {
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
context.push('/publishers/${publisher.id}');
|
||||
context.push('/publishers/${publisher.name}');
|
||||
},
|
||||
child: AspectRatio(
|
||||
aspectRatio: 16 / 7,
|
||||
|
@ -13,6 +13,7 @@ import 'package:island/pods/network.dart';
|
||||
import 'package:island/pods/config.dart';
|
||||
import 'package:island/pods/userinfo.dart';
|
||||
import 'package:island/services/file.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
|
||||
import 'dart:io';
|
||||
import 'package:path/path.dart' as path;
|
||||
@ -149,9 +150,9 @@ class _ShareSheetState extends ConsumerState<ShareSheet> {
|
||||
case ShareContentType.file:
|
||||
if (widget.content.files != null) {
|
||||
// Convert XFiles to UniversalFiles
|
||||
for (final xFile in widget.content.files!) {
|
||||
final file = File(xFile.path);
|
||||
final mimeType = xFile.mimeType;
|
||||
for (final file in widget.content.files!) {
|
||||
var mimeType = file.mimeType;
|
||||
mimeType ??= lookupMimeType(file.path);
|
||||
|
||||
UniversalFileType fileType;
|
||||
if (mimeType?.startsWith('image/') == true) {
|
||||
|
10
pubspec.lock
10
pubspec.lock
@ -1470,7 +1470,7 @@ packages:
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: mime
|
||||
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||
@ -1785,10 +1785,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: record_linux
|
||||
sha256: "29e7735b05c1944bb6c9b72a36c08d4a1b24117e712d6a9523c003bde12bf484"
|
||||
sha256: "0626678a092c75ce6af1e32fe7fd1dea709b92d308bc8e3b6d6348e2430beb95"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.1"
|
||||
record_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -2254,10 +2254,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: synchronized
|
||||
sha256: "0669c70faae6270521ee4f05bffd2919892d42d1276e6c495be80174b6bc0ef6"
|
||||
sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.1"
|
||||
version: "3.4.0"
|
||||
table_calendar:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -126,6 +126,7 @@ dependencies:
|
||||
git:
|
||||
url: https://github.com/lionelmennig/textfield_tags.git
|
||||
ref: fixes/allow-controller-re-registration
|
||||
mime: ^2.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
x
Reference in New Issue
Block a user