Skip to content

Commit 0801c29

Browse files
committed
Merge branch 'feature/Push' into develop
2 parents 76d8ffd + c47469b commit 0801c29

File tree

11 files changed

+128
-76
lines changed

11 files changed

+128
-76
lines changed

Adamant/AppDelegate.swift

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ extension String.adamantLocalized {
1919
static let chats = NSLocalizedString("Tabs.Chats", comment: "Main tab bar: Chats page")
2020
static let settings = NSLocalizedString("Tabs.Settings", comment: "Main tab bar: Settings page")
2121
}
22+
23+
struct application {
24+
static let deviceTokenSendFailed = NSLocalizedString("Application.deviceTokenErrorFormat", comment: "Application: Failed to send deviceToken to ANS error format. %@ for error description")
25+
}
2226
}
2327

2428
extension StoreKey {
@@ -44,6 +48,10 @@ struct AdamantResources {
4448

4549
static let iosAppSupportEmail = "ios@adamant.im"
4650

51+
// ANS Contact
52+
static let ansAddress = "U10629337621822775991"
53+
static let ansPublicKey = "188b24bd116a556ac8ba905bbbdaa16e237dfb14269f5a4f9a26be77537d977c"
54+
4755
private init() {}
4856
}
4957

@@ -209,6 +217,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
209217

210218
// MARK: - Remote notifications
211219
extension AppDelegate {
220+
private struct RegistrationPayload: Codable {
221+
let token: String
222+
223+
#if DEBUG
224+
let provider: String = "apns-sandbox"
225+
#else
226+
let provider: String = "apns"
227+
#endif
228+
}
229+
212230
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
213231
guard let address = accountService.account?.address, let keypair = accountService.keypair else {
214232
print("Trying to register with no user logged")
@@ -218,7 +236,7 @@ extension AppDelegate {
218236

219237
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
220238

221-
// Checking, if device token had not changed
239+
// MARK: 1. Checking, if device token had not changed
222240
guard let securedStore = container.resolve(SecuredStore.self) else {
223241
fatalError("can't get secured store to get device token hash")
224242
}
@@ -231,19 +249,48 @@ extension AppDelegate {
231249
securedStore.set(tokenHash, for: StoreKey.application.deviceTokenHash)
232250
}
233251

234-
// Storing new token in blockchain
252+
// MARK: 2. Preparing message
253+
guard let adamantCore = container.resolve(AdamantCore.self) else {
254+
fatalError("Can't get AdamantCore to register device token")
255+
}
256+
257+
let payload: String
258+
do {
259+
let data = try JSONEncoder().encode(RegistrationPayload(token: token))
260+
payload = String(data: data, encoding: String.Encoding.utf8)!
261+
} catch {
262+
dialogService.showError(withMessage: "Failed to prepare ANS signal payload", error: error)
263+
return
264+
}
265+
266+
guard let encodedPayload = adamantCore.encodeMessage(payload, recipientPublicKey: AdamantResources.ansPublicKey, privateKey: keypair.privateKey) else {
267+
dialogService.showError(withMessage: "Failed to encode ANS signal. Payload: \(payload)", error: nil)
268+
return
269+
}
270+
271+
// MARK: 3. Send signal to ANS
235272
guard let apiService = container.resolve(ApiService.self) else {
236273
fatalError("can't get api service to register device token")
237274
}
238275

239-
apiService.store(key: "deviceToken", value: token, type: StateType.keyValue, sender: address, keypair: keypair) { [weak self] result in
276+
apiService.sendMessage(senderId: address, recipientId: AdamantResources.ansAddress, keypair: keypair, message: encodedPayload.message, type: ChatType.signal, nonce: encodedPayload.nonce) { [unowned self] result in
240277
switch result {
241278
case .success:
242279
return
243280

244281
case .failure(let error):
245-
print("Failed to store device token: \(error)")
246-
self?.notificationService?.setNotificationsMode(.disabled, completion: nil)
282+
self.notificationService?.setNotificationsMode(.disabled, completion: nil)
283+
284+
switch error {
285+
case .networkError, .notLogged:
286+
self.dialogService.showWarning(withMessage: String.localizedStringWithFormat(String.adamantLocalized.application.deviceTokenSendFailed, error.localized))
287+
288+
case .accountNotFound, .serverError:
289+
self.dialogService.showError(withMessage: String.localizedStringWithFormat(String.adamantLocalized.application.deviceTokenSendFailed, error.localized), error: error)
290+
291+
case .internalError(let message, _):
292+
self.dialogService.showError(withMessage: String.localizedStringWithFormat(String.adamantLocalized.application.deviceTokenSendFailed, message), error: error)
293+
}
247294
}
248295
}
249296
}

Adamant/Assets/l18n/de.lproj/Localizable.strings

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/* System accounts: ADAMANT Tokens */
2+
"Accounts.AdamantTokens" = "ADAMANT Tokens";
3+
14
/* AccountsProvider: Address not valid error, %@ for address */
25
"AccountsProvider.Error.AddressNotValidFormat" = "Ungültige Adresse: %@";
36

@@ -61,8 +64,8 @@
6164
/* Product name */
6265
"ADAMANT" = "ADAMANT";
6366

64-
/* ApiService: No connection message. Generally bad network. */
65-
"ApiService.Error.NoConnection" = "Keine Internetverbindung";
67+
/* Application: Failed to send deviceToken to ANS error format. %@ for error description */
68+
"Application.deviceTokenErrorFormat" = "Failed to reginser in ANS: %@";
6669

6770
/* Serious internal error: Failed to build endpoint url */
6871
"ApiService.InternalError.EndpointBuildFailed" = "Endpoint Build fehlgeschlagen. Bericht senden";
@@ -244,6 +247,9 @@
244247
/* NodesList: 'Node url' plaseholder */
245248
"NodesList.NodeUrl" = "Node-URL";
246249

250+
/* Notifications: scene title */
251+
"Notifications.Title" = "Benachrichtigungen";
252+
247253
/* Notifications: Modes description. Markdown supported. */
248254
"Notifications.ModesDescription" = "#### Benachrichtigungsmodi\n\n#### Deaktiviert\nKeine Benachrichtigungen.\n\n#### Hintergrundaktualisierung\nIhr Gerät erhält neue Nachrichteninformationen automatisch. Keine externen Aufrufe. Die Hintergrundaktualisierung wird von iOS verwaltet, die Zeit wird vom Betriebssystem bestimmt und ist von vielen Faktoren wie Akkustand, Netzwerkauslastung, Nutzungsmuster abhängig und kann nicht vorhergesagt werden. Es können 20 Minuten, 6 Stunden, oder ein Tag sein. Sie können die App trotzdem öffnen und nachschauen, ob eine Nachricht angekommen ist.\n\n#### Push\nBenachrichtigungen werden auf Ihr Gerät vom ADAMANT Benachrichtigungsservice gesendet. Sie erhalten eine Benachrichtigung umgehend, nachdem die Nachricht versendet und von der Blockchain bestätigt wurde - mit einer kleinen Verzögerung. Jedoch erfordert dieser Modus, dass der Gerätetoken Ihres Geräts in der Servicedatenbank registriert ist. Gerätetokens sind sicher, und diese Option ist zu empfehlen.\n\nSie können mehr über die Geräteregistrierung auf der ADAMANTs Github-Seite nachlesen.";
249255

Adamant/Assets/l18n/en.lproj/Localizable.strings

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@
6464
/* Product name */
6565
"ADAMANT" = "ADAMANT";
6666

67-
/* ApiService: No connection message. Generally bad network. */
68-
"ApiService.Error.NoConnection" = "No connection to the Internet";
67+
/* Application: Failed to send deviceToken to ANS error format. %@ for error description */
68+
"Application.deviceTokenErrorFormat" = "Failed to reginser in ANS: %@";
6969

7070
/* Serious internal error: Failed to build endpoint url */
7171
"ApiService.InternalError.EndpointBuildFailed" = "Endpoint build failed. Report a bug";

Adamant/Assets/l18n/ru.lproj/Localizable.strings

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@
6464
/* Product name */
6565
"ADAMANT" = "АДАМАНТ";
6666

67-
/* ApiService: No connection message. Generally bad network. */
68-
"ApiService.Error.NoConnection" = "Нет соединения с сетью";
67+
/* Application: Failed to send deviceToken to ANS error format. %@ for error description */
68+
"Application.deviceTokenErrorFormat" = "Ошибка регистрации в ANS: %@";
6969

7070
/* Serious internal error: Failed to build endpoint url */
7171
"ApiService.InternalError.EndpointBuildFailed" = "Ошибка взаимодействия с блокчейном. Сообщите разработчикам";
@@ -337,21 +337,6 @@
337337
/* Notifications: User has disabled notifications. Head him into settings */
338338
"NotificationsService.NotificationsDisabled" = "Уведомления отключены. Вы можете включить их в Настройках";
339339

340-
/* Notifications: New message notification title */
341-
"NotificationsService.NewMessage.Title" = "Новое сообщение";
342-
343-
/* Notifications: New single message notification body */
344-
"NotificationsService.NewMessage.BodySingle" = "Новое сообщение";
345-
346-
/* Notifications: New transfer transaction title */
347-
"NotificationsService.NewTransfer.Title" = "Новый перевод";
348-
349-
/* Notifications: New single transfer transaction body */
350-
"NotificationsService.NewTransfer.BodySingle" = "Новый перевод";
351-
352-
/* Notifications: User has disabled notifications. Head him into settings */
353-
"NotificationsService.NotificationsDisabled" = "Уведомления отключены. Вы можете включить их в Настройках";
354-
355340
/* Pinpad: Ask user to create new pin */
356341
"Pinpad.EnterNewPin" = "Введите новый PIN-код";
357342

Adamant/Helpers/String+localized.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ extension String {
5252
}
5353

5454
static func remoteServerError(message: String) -> String {
55-
return String.localizedStringWithFormat(NSLocalizedString("Error.RemoteErrorFormat", comment: "Shared error: Remote error format, %@ for message"), message)
55+
return String.localizedStringWithFormat(NSLocalizedString("Error.RemoteServerErrorFormat", comment: "Shared error: Remote error format, %@ for message"), message)
5656
}
5757
}
5858

Adamant/Info.plist

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
<key>CFBundlePackageType</key>
1818
<string>APPL</string>
1919
<key>CFBundleShortVersionString</key>
20-
<string>0.3.12</string>
20+
<string>0.4</string>
2121
<key>CFBundleVersion</key>
22-
<string>32</string>
22+
<string>34</string>
2323
<key>LSRequiresIPhoneOS</key>
2424
<true/>
2525
<key>NSCameraUsageDescription</key>

Adamant/ServiceProtocols/ApiService.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ enum ApiServiceError: Error {
2828
case .accountNotFound:
2929
return String.adamantLocalized.sharedErrors.accountNotFound
3030

31-
case .serverError(error: let error):
32-
return String.localizedStringWithFormat(NSLocalizedString("ApiService.Error.RemoteServerErrorFormat", comment: "ApiService: Remote server returned an error. Using %@ for error description"), error)
31+
case .serverError(let error):
32+
return String.adamantLocalized.sharedErrors.remoteServerError(message: error)
3333

3434
case .internalError(let msg, let error):
3535
let message: String
@@ -109,5 +109,5 @@ protocol ApiService: class {
109109

110110
/// Send text message
111111
/// - completion: Contains processed transactionId, if success, or AdamantError, if fails.
112-
func sendMessage(senderId: String, recipientId: String, keypair: Keypair, message: String, nonce: String, completion: @escaping (ApiServiceResult<UInt64>) -> Void)
112+
func sendMessage(senderId: String, recipientId: String, keypair: Keypair, message: String, type: ChatType, nonce: String, completion: @escaping (ApiServiceResult<UInt64>) -> Void)
113113
}

Adamant/Services/AdamantNotificationService.swift

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,21 +89,7 @@ extension AdamantNotificationsService {
8989
completion?(.success)
9090
return
9191

92-
case .backgroundFetch:
93-
authorizeNotifications { [weak self] (success, error) in
94-
guard success else {
95-
completion?(.denied(error: error))
96-
return
97-
}
98-
99-
AdamantNotificationsService.configureUIApplicationFor(mode: mode)
100-
self?.securedStore.set(mode.toRaw(), for: StoreKey.notificationsService.notificationsMode)
101-
self?.notificationsMode = mode
102-
NotificationCenter.default.post(name: Notification.Name.AdamantNotificationService.notificationsModeChanged, object: self)
103-
completion?(.success)
104-
}
105-
106-
case .push:
92+
case .backgroundFetch, .push:
10793
authorizeNotifications { [weak self] (success, error) in
10894
guard success else {
10995
completion?(.denied(error: error))

Adamant/Services/ApiService/AdamantApi+Chats.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ extension AdamantApiService {
5252
}
5353
}
5454

55-
func sendMessage(senderId: String, recipientId: String, keypair: Keypair, message: String, nonce: String, completion: @escaping (ApiServiceResult<UInt64>) -> Void) {
55+
func sendMessage(senderId: String, recipientId: String, keypair: Keypair, message: String, type: ChatType, nonce: String, completion: @escaping (ApiServiceResult<UInt64>) -> Void) {
5656
// MARK: 1. Prepare params
5757
let params: [String : Any] = [
5858
"type": TransactionType.chatMessage.rawValue,
@@ -61,7 +61,7 @@ extension AdamantApiService {
6161
"publicKey": keypair.publicKey,
6262
"message": message,
6363
"own_message": nonce,
64-
"message_type": ChatType.message.rawValue
64+
"message_type": type.rawValue
6565
]
6666

6767
let headers = [
@@ -112,7 +112,7 @@ extension AdamantApiService {
112112
"chat": [
113113
"message": message,
114114
"own_message": nonce,
115-
"type": ChatType.message.rawValue
115+
"type": type.rawValue
116116
]
117117
]
118118
]

Adamant/Services/DataProviders/AdamantChatsProvider.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -329,11 +329,12 @@ extension AdamantChatsProvider {
329329

330330

331331
// MARK: 3. Create chat transaction
332+
let type = ChatType.message
332333
let transaction = MessageTransaction(entity: MessageTransaction.entity(), insertInto: privateContext)
333334
transaction.date = Date() as NSDate
334335
transaction.recipientId = recipientId
335336
transaction.senderId = senderId
336-
transaction.type = Int16(ChatType.message.rawValue)
337+
transaction.type = Int16(type.rawValue)
337338
transaction.isOutgoing = true
338339
transaction.message = text
339340

@@ -368,7 +369,7 @@ extension AdamantChatsProvider {
368369

369370

370371
// MARK: 6. Send
371-
sendTransaction(transaction, keypair: keypair, recipientPublicKey: recipientPublicKey) { result in
372+
sendTransaction(transaction, type: type, keypair: keypair, recipientPublicKey: recipientPublicKey) { result in
372373
switch result {
373374
case .success:
374375
do {
@@ -436,7 +437,7 @@ extension AdamantChatsProvider {
436437

437438

438439
// MARK: 3. Send
439-
sendTransaction(transaction, keypair: keypair, recipientPublicKey: recipientPublicKey) { result in
440+
sendTransaction(transaction, type: .message, keypair: keypair, recipientPublicKey: recipientPublicKey) { result in
440441
switch result {
441442
case .success:
442443
do {
@@ -488,7 +489,7 @@ extension AdamantChatsProvider {
488489
///
489490
/// If success - update transaction's id and add it to unconfirmed transactions.
490491
/// If fails - set transaction status to .failed
491-
private func sendTransaction(_ transaction: MessageTransaction, keypair: Keypair, recipientPublicKey: String, completion: @escaping (ChatsProviderResult) -> Void) {
492+
private func sendTransaction(_ transaction: MessageTransaction, type: ChatType, keypair: Keypair, recipientPublicKey: String, completion: @escaping (ChatsProviderResult) -> Void) {
492493
// MARK: 0. Prepare
493494
guard let senderId = transaction.senderId,
494495
let recipientId = transaction.recipientId else {
@@ -503,7 +504,7 @@ extension AdamantChatsProvider {
503504
}
504505

505506
// MARK: 2. Send
506-
apiService.sendMessage(senderId: senderId, recipientId: recipientId, keypair: keypair, message: encodedMessage.message, nonce: encodedMessage.nonce) { result in
507+
apiService.sendMessage(senderId: senderId, recipientId: recipientId, keypair: keypair, message: encodedMessage.message, type: type, nonce: encodedMessage.nonce) { result in
507508
switch result {
508509
case .success(let id):
509510
// Update ID with recieved, add to unconfirmed transactions.

0 commit comments

Comments
 (0)