diff --git a/apple/InfoPlists/Omnivore.plist b/apple/InfoPlists/Omnivore.plist index be36bec66..40d538289 100644 --- a/apple/InfoPlists/Omnivore.plist +++ b/apple/InfoPlists/Omnivore.plist @@ -2,6 +2,10 @@ + NSUserActivityTypes + + app.omnivore.omnivore.openURL + ITSAppUsesNonExemptEncryption BGTaskSchedulerPermittedIdentifiers diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift index 1f35cd922..ceb322fc2 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift @@ -378,7 +378,6 @@ struct AnimatingCellHeight: AnimatableModifier { } ToolbarItemGroup(placement: .barTrailing) { - if viewModel.appliedFilter?.name == "Deleted" { if viewModel.isEmptyingTrash { ProgressView() @@ -440,7 +439,7 @@ struct AnimatingCellHeight: AnimatableModifier { } ).buttonStyle(.plain) .padding(.horizontal, UIDevice.isIPad ? 5 : 0) - + Button( action: { searchPresented = true diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift index 95ce3f22d..e40cc2052 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift @@ -44,6 +44,8 @@ struct WebReaderContainerView: View { @State var showExplainSheet = false + @State var handoffActivity: NSUserActivity? + @EnvironmentObject var dataService: DataService @EnvironmentObject var audioController: AudioController @Environment(\.openURL) var openURL @@ -422,6 +424,8 @@ struct WebReaderContainerView: View { .statusBar(hidden: prefersHideStatusBarInReader) #endif .onAppear { + startUserActivity() + dataService.updateLinkReadingProgress( itemID: item.unwrappedID, readingProgress: max(item.readingProgress, 0.1), @@ -437,6 +441,9 @@ struct WebReaderContainerView: View { } } } + .onDisappear { + stopUserActivity() + } .confirmationDialog(linkToOpen?.absoluteString ?? "", isPresented: $displayLinkSheet, titleVisibility: .visible) { Button(action: { @@ -708,7 +715,7 @@ struct WebReaderContainerView: View { func share() { shareActionID = UUID() } - + func printReader() { shareActionID = UUID() } @@ -752,4 +759,22 @@ struct WebReaderContainerView: View { openURL(url) } + + func startUserActivity() { + if let slug = item.slug, let webpageURL = URL(string: "https://omnivore.app/me/\(slug)") { + let activity = NSUserActivity(activityType: "com.omnivore.omnivore.openURL") + activity.title = "Open in Safari" + activity.webpageURL = webpageURL + activity.isEligibleForHandoff = true + activity.becomeCurrent() + handoffActivity = activity + } + } + + func stopUserActivity() { + self.handoffActivity = nil + Task { + await NSUserActivity.deleteAllSavedUserActivities() + } + } } diff --git a/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift b/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift index cd3cf2b2c..99740f24e 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift @@ -13273,6 +13273,7 @@ extension Objects { let optInFeature: [String: Unions.OptInFeatureResult] let recommend: [String: Unions.RecommendResult] let recommendHighlights: [String: Unions.RecommendHighlightsResult] + let replyToEmail: [String: Unions.ReplyToEmailResult] let reportItem: [String: Objects.ReportItemResult] let revokeApiKey: [String: Unions.RevokeApiKeyResult] let saveArticleReadingProgress: [String: Unions.SaveArticleReadingProgressResult] @@ -13475,6 +13476,10 @@ extension Objects.Mutation: Decodable { if let value = try container.decode(Unions.RecommendHighlightsResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "replyToEmail": + if let value = try container.decode(Unions.ReplyToEmailResult?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "reportItem": if let value = try container.decode(Objects.ReportItemResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -13647,6 +13652,7 @@ extension Objects.Mutation: Decodable { optInFeature = map["optInFeature"] recommend = map["recommend"] recommendHighlights = map["recommendHighlights"] + replyToEmail = map["replyToEmail"] reportItem = map["reportItem"] revokeApiKey = map["revokeApiKey"] saveArticleReadingProgress = map["saveArticleReadingProgress"] @@ -14404,6 +14410,25 @@ extension Fields where TypeLock == Objects.Mutation { } } + func replyToEmail(recentEmailId: String, reply: Enums.AllowedReply, selection: Selection) throws -> Type { + let field = GraphQLField.composite( + name: "replyToEmail", + arguments: [Argument(name: "recentEmailId", type: "ID!", value: recentEmailId), Argument(name: "reply", type: "AllowedReply!", value: reply)], + selection: selection.selection + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.replyToEmail[field.alias!] { + return try selection.decode(data: data) + } + throw HttpError.badpayload + case .mocking: + return selection.mock() + } + } + func reportItem(input: InputObjects.ReportItemInput, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "reportItem", @@ -17261,6 +17286,8 @@ extension Objects { let from: [String: String] let html: [String: String] let id: [String: String] + let reply: [String: String] + let replyTo: [String: String] let subject: [String: String] let text: [String: String] let to: [String: String] @@ -17300,6 +17327,14 @@ extension Objects.RecentEmail: Decodable { if let value = try container.decode(String?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "reply": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + case "replyTo": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "subject": if let value = try container.decode(String?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -17330,6 +17365,8 @@ extension Objects.RecentEmail: Decodable { from = map["from"] html = map["html"] id = map["id"] + reply = map["reply"] + replyTo = map["replyTo"] subject = map["subject"] text = map["text"] to = map["to"] @@ -17407,6 +17444,36 @@ extension Fields where TypeLock == Objects.RecentEmail { } } + func reply() throws -> String? { + let field = GraphQLField.leaf( + name: "reply", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.reply[field.alias!] + case .mocking: + return nil + } + } + + func replyTo() throws -> String? { + let field = GraphQLField.leaf( + name: "replyTo", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.replyTo[field.alias!] + case .mocking: + return nil + } + } + func subject() throws -> String { let field = GraphQLField.leaf( name: "subject", @@ -18975,6 +19042,136 @@ extension Selection where TypeLock == Never, Type == Never { typealias ReminderSuccess = Selection } +extension Objects { + struct ReplyToEmailError { + let __typename: TypeName = .replyToEmailError + let errorCodes: [String: [Enums.ReplyToEmailErrorCode]] + + enum TypeName: String, Codable { + case replyToEmailError = "ReplyToEmailError" + } + } +} + +extension Objects.ReplyToEmailError: Decodable { + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: DynamicCodingKeys.self) + + var map = HashMap() + for codingKey in container.allKeys { + if codingKey.isTypenameKey { continue } + + let alias = codingKey.stringValue + let field = GraphQLField.getFieldNameFromAlias(alias) + + switch field { + case "errorCodes": + if let value = try container.decode([Enums.ReplyToEmailErrorCode]?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + default: + throw DecodingError.dataCorrupted( + DecodingError.Context( + codingPath: decoder.codingPath, + debugDescription: "Unknown key \(field)." + ) + ) + } + } + + errorCodes = map["errorCodes"] + } +} + +extension Fields where TypeLock == Objects.ReplyToEmailError { + func errorCodes() throws -> [Enums.ReplyToEmailErrorCode] { + let field = GraphQLField.leaf( + name: "errorCodes", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.errorCodes[field.alias!] { + return data + } + throw HttpError.badpayload + case .mocking: + return [] + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias ReplyToEmailError = Selection +} + +extension Objects { + struct ReplyToEmailSuccess { + let __typename: TypeName = .replyToEmailSuccess + let success: [String: Bool] + + enum TypeName: String, Codable { + case replyToEmailSuccess = "ReplyToEmailSuccess" + } + } +} + +extension Objects.ReplyToEmailSuccess: Decodable { + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: DynamicCodingKeys.self) + + var map = HashMap() + for codingKey in container.allKeys { + if codingKey.isTypenameKey { continue } + + let alias = codingKey.stringValue + let field = GraphQLField.getFieldNameFromAlias(alias) + + switch field { + case "success": + if let value = try container.decode(Bool?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + default: + throw DecodingError.dataCorrupted( + DecodingError.Context( + codingPath: decoder.codingPath, + debugDescription: "Unknown key \(field)." + ) + ) + } + } + + success = map["success"] + } +} + +extension Fields where TypeLock == Objects.ReplyToEmailSuccess { + func success() throws -> Bool { + let field = GraphQLField.leaf( + name: "success", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.success[field.alias!] { + return data + } + throw HttpError.badpayload + case .mocking: + return Bool.mockValue + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias ReplyToEmailSuccess = Selection +} + extension Objects { struct ReportItemResult { let __typename: TypeName = .reportItemResult @@ -20445,6 +20642,7 @@ extension Objects { let directionality: [String: Enums.DirectionalityType] let feedContent: [String: String] let folder: [String: String] + let format: [String: String] let highlights: [String: [Objects.Highlight]] let id: [String: String] let image: [String: String] @@ -20545,6 +20743,10 @@ extension Objects.SearchItem: Decodable { if let value = try container.decode(String?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "format": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "highlights": if let value = try container.decode([Objects.Highlight]?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -20699,6 +20901,7 @@ extension Objects.SearchItem: Decodable { directionality = map["directionality"] feedContent = map["feedContent"] folder = map["folder"] + format = map["format"] highlights = map["highlights"] id = map["id"] image = map["image"] @@ -20925,6 +21128,21 @@ extension Fields where TypeLock == Objects.SearchItem { } } + func format() throws -> String? { + let field = GraphQLField.leaf( + name: "format", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.format[field.alias!] + case .mocking: + return nil + } + } + func highlights(selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "highlights", @@ -27785,6 +28003,7 @@ extension Selection where TypeLock == Never, Type == Never { extension Objects { struct UserPersonalization { let __typename: TypeName = .userPersonalization + let digestConfig: [String: String] let fields: [String: String] let fontFamily: [String: String] let fontSize: [String: Int] @@ -27816,6 +28035,10 @@ extension Objects.UserPersonalization: Decodable { let field = GraphQLField.getFieldNameFromAlias(alias) switch field { + case "digestConfig": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "fields": if let value = try container.decode(String?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -27874,6 +28097,7 @@ extension Objects.UserPersonalization: Decodable { } } + digestConfig = map["digestConfig"] fields = map["fields"] fontFamily = map["fontFamily"] fontSize = map["fontSize"] @@ -27890,6 +28114,21 @@ extension Objects.UserPersonalization: Decodable { } extension Fields where TypeLock == Objects.UserPersonalization { + func digestConfig() throws -> String? { + let field = GraphQLField.leaf( + name: "digestConfig", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.digestConfig[field.alias!] + case .mocking: + return nil + } + } + func fields() throws -> String? { let field = GraphQLField.leaf( name: "fields", @@ -33777,6 +34016,80 @@ extension Selection where TypeLock == Never, Type == Never { typealias ReminderResult = Selection } +extension Unions { + struct ReplyToEmailResult { + let __typename: TypeName + let errorCodes: [String: [Enums.ReplyToEmailErrorCode]] + let success: [String: Bool] + + enum TypeName: String, Codable { + case replyToEmailError = "ReplyToEmailError" + case replyToEmailSuccess = "ReplyToEmailSuccess" + } + } +} + +extension Unions.ReplyToEmailResult: Decodable { + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: DynamicCodingKeys.self) + + var map = HashMap() + for codingKey in container.allKeys { + if codingKey.isTypenameKey { continue } + + let alias = codingKey.stringValue + let field = GraphQLField.getFieldNameFromAlias(alias) + + switch field { + case "errorCodes": + if let value = try container.decode([Enums.ReplyToEmailErrorCode]?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + case "success": + if let value = try container.decode(Bool?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + default: + throw DecodingError.dataCorrupted( + DecodingError.Context( + codingPath: decoder.codingPath, + debugDescription: "Unknown key \(field)." + ) + ) + } + } + + __typename = try container.decode(TypeName.self, forKey: DynamicCodingKeys(stringValue: "__typename")!) + + errorCodes = map["errorCodes"] + success = map["success"] + } +} + +extension Fields where TypeLock == Unions.ReplyToEmailResult { + func on(replyToEmailError: Selection, replyToEmailSuccess: Selection) throws -> Type { + select([GraphQLField.fragment(type: "ReplyToEmailError", selection: replyToEmailError.selection), GraphQLField.fragment(type: "ReplyToEmailSuccess", selection: replyToEmailSuccess.selection)]) + + switch response { + case let .decoding(data): + switch data.__typename { + case .replyToEmailError: + let data = Objects.ReplyToEmailError(errorCodes: data.errorCodes) + return try replyToEmailError.decode(data: data) + case .replyToEmailSuccess: + let data = Objects.ReplyToEmailSuccess(success: data.success) + return try replyToEmailSuccess.decode(data: data) + } + case .mocking: + return replyToEmailError.mock() + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias ReplyToEmailResult = Selection +} + extension Unions { struct RevokeApiKeyResult { let __typename: TypeName @@ -37206,6 +37519,19 @@ extension Enums { } } +extension Enums { + /// AllowedReply + enum AllowedReply: String, CaseIterable, Codable { + case confirm = "CONFIRM" + + case okay = "OKAY" + + case subscribe = "SUBSCRIBE" + + case yes = "YES" + } +} + extension Enums { /// ApiKeysErrorCode enum ApiKeysErrorCode: String, CaseIterable, Codable { @@ -38008,6 +38334,13 @@ extension Enums { } } +extension Enums { + /// ReplyToEmailErrorCode + enum ReplyToEmailErrorCode: String, CaseIterable, Codable { + case unauthorized = "UNAUTHORIZED" + } +} + extension Enums { /// ReportType enum ReportType: String, CaseIterable, Codable { @@ -40044,6 +40377,8 @@ extension InputObjects { extension InputObjects { struct SetUserPersonalizationInput: Encodable, Hashable { + var digestConfig: OptionalArgument = .absent() + var fields: OptionalArgument = .absent() var fontFamily: OptionalArgument = .absent() @@ -40068,6 +40403,7 @@ extension InputObjects { func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + if digestConfig.hasValue { try container.encode(digestConfig, forKey: .digestConfig) } if fields.hasValue { try container.encode(fields, forKey: .fields) } if fontFamily.hasValue { try container.encode(fontFamily, forKey: .fontFamily) } if fontSize.hasValue { try container.encode(fontSize, forKey: .fontSize) } @@ -40082,6 +40418,7 @@ extension InputObjects { } enum CodingKeys: String, CodingKey { + case digestConfig case fields case fontFamily case fontSize diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/100.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/100.png index b05446cc4..a77b6d27d 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/100.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/100.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/1024.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/1024.png index 1d730a207..1ea66e520 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/1024.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/1024.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/114.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/114.png index c5b1a9ec7..b0bf59467 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/114.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/114.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/120.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/120.png index 2d29a454a..b637c83f9 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/120.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/120.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/144.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/144.png index 1e85b1eba..d36c7cb85 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/144.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/144.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/152.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/152.png index d67375bc0..f35d31dbd 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/152.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/152.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/167.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/167.png index 112c03700..7673419cd 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/167.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/167.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/180.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/180.png index bd895c1c6..b870712b2 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/180.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/180.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/20.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/20.png index 9d32728b4..08c152eb7 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/20.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/20.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/29.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/29.png index 1f335b31e..3cb71eda1 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/29.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/29.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/40.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/40.png index 8d2bd163f..927bd6b5f 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/40.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/40.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/50.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/50.png index 6e9a82ed0..27334e579 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/50.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/50.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/57.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/57.png index 5bb947b38..91c1cc95d 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/57.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/57.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/58.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/58.png index 3430925c2..582468935 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/58.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/58.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/60.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/60.png index 42ed00f69..62acfc344 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/60.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/60.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/72.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/72.png index 44170f0e8..f4db76e15 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/72.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/72.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/76.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/76.png index bd163096c..82d82dfa0 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/76.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/76.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/80.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/80.png index 2ec51e0bb..1269eaa79 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/80.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/80.png differ diff --git a/apple/Resources/Assets.xcassets/AppIcon.appiconset/87.png b/apple/Resources/Assets.xcassets/AppIcon.appiconset/87.png index f32f5abae..b64e7c375 100644 Binary files a/apple/Resources/Assets.xcassets/AppIcon.appiconset/87.png and b/apple/Resources/Assets.xcassets/AppIcon.appiconset/87.png differ