update example with extension

This commit is contained in:
Salvatore Giordano
2020-04-06 09:38:13 +02:00
parent 9318934f79
commit 27c3a7f390
8 changed files with 453 additions and 35 deletions
@@ -7,48 +7,140 @@
//
import UserNotifications
import StreamChatCore
import StreamChatClient
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
print("DID RECEIVE")
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
defer {
contentHandler(bestAttemptContent ?? request.content)
}
let apiKey = "s2dxdhpxd94g";
let userId = "user1"
let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoidXNlcjEifQ.NGZPyPMx7KSVisJmh4tJhOIv7ZjCaMQpOh4gTINvCaU"
let sharedDefaults = UserDefaults(suiteName: "group.io.stream.flutter")
let apiKey = sharedDefaults!.string(forKey: "KEY_API_KEY")!
let userId = sharedDefaults!.string(forKey: "KEY_USER_ID")!
let token = sharedDefaults!.string(forKey: "KEY_TOKEN")!
let messageId = bestAttemptContent?.userInfo["message_id"] as! String
print("REQUEST CONTENT \(messageId)")
Client.config = .init(apiKey: apiKey, logOptions: .info)
Client.shared.set(user: User(id: userId, name: ""), token: token)
Client.shared.message(with: messageId).subscribe { res in
print(res)
Client.shared.disconnect()
Client.config = .init(apiKey: apiKey, logOptions: .error)
Client.shared.set(user: User(id: userId), token: token) { res in
if res.isConnected {
Client.shared.message(withId: messageId) { res in
if let message = res.value?.message,
let channel = res.value?.channel {
let messageWrapper = MessageWrapper(id: message.id, channel: ChannelWrapper(id: channel.id, cid: channel.cid, type: channel.type, name: channel.name, imageURL: channel.imageURL, lastMessageDate: channel.lastMessageDate, created: channel.created, deleted: channel.deleted, createdBy: channel.createdBy, config: channel.config, frozen: channel.frozen, extraData: channel.extraData), type: message.type, user: message.user, created: message.created, updated: message.updated, text: message.text, command: message.command, args: message.args, attachments: message.attachments, parentId: message.parentId, showReplyInChannel: message.showReplyInChannel, mentionedUsers: message.mentionedUsers, extraData: message.extraData)
if let encodedData = try? JSONEncoder.stream.encode(messageWrapper) {
let storedMessages = sharedDefaults?.stringArray(forKey: "messageQueue") ?? []
let encodedString = String(data: encodedData, encoding: .utf8)!
sharedDefaults?.setValue(storedMessages + [encodedString], forKey: "messageQueue")
// Modify the notification content here...
self.bestAttemptContent?.title = "[modified] \(self.bestAttemptContent?.title ?? "<NoContent>")"
contentHandler(self.bestAttemptContent ?? request.content)
}
Client.shared.disconnect()
}
}
}
}
// Modify the notification content here...
bestAttemptContent?.title = "[modified] \(bestAttemptContent?.title ?? "<NoContent>")"
}
override func serviceExtensionTimeWillExpire() {
print("serviceExtensionTimeWillExpire")
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
public struct MessageWrapper: Encodable {
private enum CodingKeys: String, CodingKey {
case id
case channel
case type
case user
case created = "created_at"
case updated = "updated_at"
case text
case command
case args
case attachments
case parentId = "parent_id"
case showReplyInChannel = "show_in_channel"
case mentionedUsers = "mentioned_users"
}
/// A message id.
public let id: String
/// The channel cid.
public let channel: ChannelWrapper?
/// A message type (see `MessageType`).
public let type: MessageType
/// A user (see `User`).
public let user: User
/// A created date.
public let created: Date
/// A updated date.
public let updated: Date
/// A text.
public let text: String
/// A used command name.
public let command: String?
/// A used command args.
public let args: String?
/// Attachments (see `Attachment`).
public let attachments: [Attachment]
/// A parent message id.
public let parentId: String?
/// Check if this reply message needs to show in the channel.
public let showReplyInChannel: Bool
/// Mentioned users (see `User`).
public let mentionedUsers: [User]
/// An extra data for the message.
public let extraData: Codable?
}
public struct ChannelWrapper: Encodable {
/// Coding keys for the encoding.
private enum CodingKeys: String, CodingKey {
case id
case cid
case type
case name
case imageURL = "image"
case members
case lastMessageDate = "last_message_at"
case createdBy = "created_by"
case created = "created_at"
case deleted = "deleted_at"
}
/// A channel id.
public let id: String
/// A channel type + id.
public let cid: ChannelId
/// A channel type.
public let type: ChannelType
/// A channel name.
public let name: String?
/// An image of the channel.
public let imageURL: URL?
/// The last message date.
public let lastMessageDate: Date?
/// A channel created date.
public let created: Date
/// A channel deleted date.
public let deleted: Date?
/// A creator of the channel.
public let createdBy: User?
/// A config.
public let config: Channel.Config
/// Checks if the channel is frozen.
public let frozen: Bool
/// A list of user ids of the channel members.
public let members = Set<Member>()
/// An extra data for the channel.
public let extraData: Codable?
}
@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.io.stream.flutter</string>
</array>
</dict>
</plist>
+1 -1
View File
@@ -63,7 +63,7 @@ target 'Runner' do
# Keep pod path relative so it can be checked into Podfile.lock.
pod 'Flutter', :path => 'Flutter'
pod 'StreamChatCore'
pod 'StreamChatClient', :git => 'https://github.com/GetStream/stream-chat-swift.git', :branch => 'release/2.0'
# Plugin Pods
+285
View File
@@ -0,0 +1,285 @@
PODS:
- file_picker (0.0.1):
- Flutter
- Firebase/Core (6.20.0):
- Firebase/CoreOnly
- FirebaseAnalytics (= 6.3.1)
- Firebase/CoreOnly (6.20.0):
- FirebaseCore (= 6.6.4)
- Firebase/Messaging (6.20.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 4.3.0)
- firebase_messaging (0.0.1):
- Firebase/Core
- Firebase/Messaging
- Flutter
- FirebaseAnalytics (6.3.1):
- FirebaseCore (~> 6.6)
- FirebaseInstallations (~> 1.1)
- GoogleAppMeasurement (= 6.3.1)
- GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- GoogleUtilities/MethodSwizzler (~> 6.0)
- GoogleUtilities/Network (~> 6.0)
- "GoogleUtilities/NSData+zlib (~> 6.0)"
- nanopb (= 0.3.9011)
- FirebaseAnalyticsInterop (1.5.0)
- FirebaseCore (6.6.4):
- FirebaseCoreDiagnostics (~> 1.2)
- FirebaseCoreDiagnosticsInterop (~> 1.2)
- GoogleUtilities/Environment (~> 6.5)
- GoogleUtilities/Logger (~> 6.5)
- FirebaseCoreDiagnostics (1.2.2):
- FirebaseCoreDiagnosticsInterop (~> 1.2)
- GoogleDataTransportCCTSupport (~> 2.0)
- GoogleUtilities/Environment (~> 6.5)
- GoogleUtilities/Logger (~> 6.5)
- nanopb (~> 0.3.901)
- FirebaseCoreDiagnosticsInterop (1.2.0)
- FirebaseInstallations (1.1.0):
- FirebaseCore (~> 6.6)
- GoogleUtilities/UserDefaults (~> 6.5)
- PromisesObjC (~> 1.2)
- FirebaseInstanceID (4.3.2):
- FirebaseCore (~> 6.6)
- FirebaseInstallations (~> 1.0)
- GoogleUtilities/Environment (~> 6.5)
- GoogleUtilities/UserDefaults (~> 6.5)
- FirebaseMessaging (4.3.0):
- FirebaseAnalyticsInterop (~> 1.5)
- FirebaseCore (~> 6.6)
- FirebaseInstanceID (~> 4.3)
- GoogleUtilities/AppDelegateSwizzler (~> 6.5)
- GoogleUtilities/Environment (~> 6.5)
- GoogleUtilities/Reachability (~> 6.5)
- GoogleUtilities/UserDefaults (~> 6.5)
- Protobuf (>= 3.9.2, ~> 3.9)
- Flutter (1.0.0)
- flutter_apns (0.0.1):
- Flutter
- flutter_keyboard_visibility (0.7.0):
- Flutter
- flutter_local_notifications (0.0.1):
- Flutter
- flutter_plugin_android_lifecycle (0.0.1):
- Flutter
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- GoogleAppMeasurement (6.3.1):
- GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- GoogleUtilities/MethodSwizzler (~> 6.0)
- GoogleUtilities/Network (~> 6.0)
- "GoogleUtilities/NSData+zlib (~> 6.0)"
- nanopb (= 0.3.9011)
- GoogleDataTransport (5.0.0)
- GoogleDataTransportCCTSupport (2.0.0):
- GoogleDataTransport (~> 5.0)
- nanopb (~> 0.3.901)
- GoogleUtilities/AppDelegateSwizzler (6.5.2):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (6.5.2)
- GoogleUtilities/Logger (6.5.2):
- GoogleUtilities/Environment
- GoogleUtilities/MethodSwizzler (6.5.2):
- GoogleUtilities/Logger
- GoogleUtilities/Network (6.5.2):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (6.5.2)"
- GoogleUtilities/Reachability (6.5.2):
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (6.5.2):
- GoogleUtilities/Logger
- GzipSwift (5.0.0)
- image_picker (0.0.1):
- Flutter
- moor_ffi (0.0.1):
- Flutter
- nanopb (0.3.9011):
- nanopb/decode (= 0.3.9011)
- nanopb/encode (= 0.3.9011)
- nanopb/decode (0.3.9011)
- nanopb/encode (0.3.9011)
- path_provider (0.0.1):
- Flutter
- path_provider_macos (0.0.1):
- Flutter
- PromisesObjC (1.2.8)
- Protobuf (3.11.4)
- ReachabilitySwift (4.3.1)
- shared_preferences (0.0.1):
- Flutter
- shared_preferences_macos (0.0.1):
- Flutter
- shared_preferences_web (0.0.1):
- Flutter
- sqflite (0.0.1):
- Flutter
- FMDB (~> 2.7.2)
- Starscream (3.1.1)
- StreamChatClient (2.0.0):
- GzipSwift (~> 5.0.0)
- ReachabilitySwift (~> 4.3.0)
- Starscream (~> 3.1.0)
- url_launcher (0.0.1):
- Flutter
- url_launcher_macos (0.0.1):
- Flutter
- url_launcher_web (0.0.1):
- Flutter
- video_player (0.0.1):
- Flutter
- video_player_web (0.0.1):
- Flutter
- wakelock (0.0.1):
- Flutter
DEPENDENCIES:
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
- Flutter (from `Flutter`)
- flutter_apns (from `.symlinks/plugins/flutter_apns/ios`)
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`)
- image_picker (from `.symlinks/plugins/image_picker/ios`)
- moor_ffi (from `.symlinks/plugins/moor_ffi/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- shared_preferences_macos (from `.symlinks/plugins/shared_preferences_macos/ios`)
- shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- StreamChatClient (from `https://github.com/GetStream/stream-chat-swift.git`, branch `release/2.0`)
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
- url_launcher_macos (from `.symlinks/plugins/url_launcher_macos/ios`)
- url_launcher_web (from `.symlinks/plugins/url_launcher_web/ios`)
- video_player (from `.symlinks/plugins/video_player/ios`)
- video_player_web (from `.symlinks/plugins/video_player_web/ios`)
- wakelock (from `.symlinks/plugins/wakelock/ios`)
SPEC REPOS:
trunk:
- Firebase
- FirebaseAnalytics
- FirebaseAnalyticsInterop
- FirebaseCore
- FirebaseCoreDiagnostics
- FirebaseCoreDiagnosticsInterop
- FirebaseInstallations
- FirebaseInstanceID
- FirebaseMessaging
- FMDB
- GoogleAppMeasurement
- GoogleDataTransport
- GoogleDataTransportCCTSupport
- GoogleUtilities
- GzipSwift
- nanopb
- PromisesObjC
- Protobuf
- ReachabilitySwift
- Starscream
EXTERNAL SOURCES:
file_picker:
:path: ".symlinks/plugins/file_picker/ios"
firebase_messaging:
:path: ".symlinks/plugins/firebase_messaging/ios"
Flutter:
:path: Flutter
flutter_apns:
:path: ".symlinks/plugins/flutter_apns/ios"
flutter_keyboard_visibility:
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
flutter_local_notifications:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
flutter_plugin_android_lifecycle:
:path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios"
image_picker:
:path: ".symlinks/plugins/image_picker/ios"
moor_ffi:
:path: ".symlinks/plugins/moor_ffi/ios"
path_provider:
:path: ".symlinks/plugins/path_provider/ios"
path_provider_macos:
:path: ".symlinks/plugins/path_provider_macos/ios"
shared_preferences:
:path: ".symlinks/plugins/shared_preferences/ios"
shared_preferences_macos:
:path: ".symlinks/plugins/shared_preferences_macos/ios"
shared_preferences_web:
:path: ".symlinks/plugins/shared_preferences_web/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
StreamChatClient:
:branch: release/2.0
:git: https://github.com/GetStream/stream-chat-swift.git
url_launcher:
:path: ".symlinks/plugins/url_launcher/ios"
url_launcher_macos:
:path: ".symlinks/plugins/url_launcher_macos/ios"
url_launcher_web:
:path: ".symlinks/plugins/url_launcher_web/ios"
video_player:
:path: ".symlinks/plugins/video_player/ios"
video_player_web:
:path: ".symlinks/plugins/video_player_web/ios"
wakelock:
:path: ".symlinks/plugins/wakelock/ios"
CHECKOUT OPTIONS:
StreamChatClient:
:commit: 941fed4d692712fe32a8c3fa7a3acc01a4b6f60e
:git: https://github.com/GetStream/stream-chat-swift.git
SPEC CHECKSUMS:
file_picker: 408623be2125b79a4539cf703be3d4b3abe5e245
Firebase: fe7f74012742ab403451dd283e6909b8f1fb348a
firebase_messaging: cffb57ce40958c6204f03fb0c81713e4cd1e240c
FirebaseAnalytics: 572e467f3d977825266e8ccd52674aa3e6f47eac
FirebaseAnalyticsInterop: 3f86269c38ae41f47afeb43ebf32a001f58fcdae
FirebaseCore: ed0a24c758a57c2b88c5efa8e6a8195e868af589
FirebaseCoreDiagnostics: e9b4cd8ba60dee0f2d13347332e4b7898cca5b61
FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850
FirebaseInstallations: 575cd32f2aec0feeb0e44f5d0110a09e5e60b47b
FirebaseInstanceID: 7ee0d6777013bb952f377b41965bf132b6a075be
FirebaseMessaging: 4ec33842d36b3319e062e51fb8b35a74f726950d
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
flutter_apns: f516b118e423fe7c0a38771180549c4d6cb67c2f
flutter_keyboard_visibility: 6195387fb6d8f46e5cd6dda4a4154e41f800f545
flutter_local_notifications: 9e4738ce2471c5af910d961a6b7eadcf57c50186
flutter_plugin_android_lifecycle: 47de533a02850f070f5696a623995e93eddcdb9b
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
GoogleAppMeasurement: c29d405ff76e18551b5d158eaba6753fda8c7542
GoogleDataTransport: a857c6a002d201b524dd4bc2ed7e7355ed07e785
GoogleDataTransportCCTSupport: 32f75fbe904c82772fcbb6b6bd4525bfb6f2a862
GoogleUtilities: ad0f3b691c67909d03a3327cc205222ab8f42e0e
GzipSwift: 5592f4d62b641e04d06443ba471f8ed76b1363e4
image_picker: e3eacd46b94694dde7cf2705955cece853aa1a8f
moor_ffi: d66c9470c18e9cb333423bbcb493c105c6c774c6
nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd
path_provider: fb74bd0465e96b594bb3b5088ee4a4e7bb1f2a9d
path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0
PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6
Protobuf: 176220c526ad8bd09ab1fb40a978eac3fef665f7
ReachabilitySwift: 4032e2f59586e11e3b0ebe15b167abdd587a388b
shared_preferences: 430726339841afefe5142b9c1f50cb6bd7793e01
shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087
shared_preferences_web: 141cce0c3ed1a1c5bf2a0e44f52d31eeb66e5ea9
sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0
Starscream: 4bb2f9942274833f7b4d296a55504dcfc7edb7b0
StreamChatClient: a5b5a85b0bcccf3ccb26a6847f110912a8c05e92
url_launcher: a1c0cc845906122c4784c542523d8cacbded5626
url_launcher_macos: fd7894421cd39320dce5f292fc99ea9270b2a313
url_launcher_web: e5527357f037c87560776e36436bf2b0288b965c
video_player: 69c5f029fac4ffe4fc8a85ea7f7b793709661549
video_player_web: da8cadb8274ed4f8dbee8d7171b420dedd437ce7
wakelock: 0d4a70faf8950410735e3f61fb15d517c8a6efc4
PODFILE CHECKSUM: fc856097c8855a277ba9200358b7361bf84ee637
COCOAPODS: 1.8.4
@@ -562,6 +562,7 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@@ -702,6 +703,7 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@@ -735,6 +737,7 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
+35 -7
View File
@@ -3,11 +3,39 @@ import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
let sharedDefaults = UserDefaults(suiteName: "group.io.stream.flutter")
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
if let jsonMessage = sharedDefaults?.stringArray(forKey: "messageQueue") {
UserDefaults.standard.setValue(jsonMessage, forKey: "flutter.messageQueue")
sharedDefaults?.removeObject(forKey: "messageQueue")
}
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func applicationDidEnterBackground(_ application: UIApplication) {
if let apiKey = UserDefaults.standard.string(forKey: "flutter.KEY_API_KEY") {
sharedDefaults?.setValue(apiKey, forKey: "KEY_API_KEY")
}
if let token = UserDefaults.standard.string(forKey: "flutter.KEY_TOKEN") {
sharedDefaults?.setValue(token, forKey: "KEY_TOKEN")
}
if let userId = UserDefaults.standard.string(forKey: "flutter.KEY_USER_ID") {
sharedDefaults?.setValue(userId, forKey: "KEY_USER_ID")
}
}
override func applicationWillEnterForeground(_ application: UIApplication) {
if let jsonMessage = sharedDefaults?.stringArray(forKey: "messageQueue") {
UserDefaults.standard.setValue(jsonMessage, forKey: "flutter.messageQueue")
sharedDefaults?.removeObject(forKey: "messageQueue")
}
}
}
+4
View File
@@ -4,5 +4,9 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.io.stream.flutter</string>
</array>
</dict>
</plist>
+1
View File
@@ -229,6 +229,7 @@ class StreamChatState extends State<StreamChat>
client.disconnect();
} else if (state == AppLifecycleState.resumed) {
if (client.wsConnectionStatus.value == ConnectionStatus.disconnected) {
NotificationService.handleIosMessageQueue(client);
client.connect();
}
}