From 770313983394302b036742f1aa95a7c96240808c Mon Sep 17 00:00:00 2001 From: snishimura Date: Mon, 26 Aug 2024 22:54:46 +0900 Subject: [PATCH 1/6] add ATT command (#465) * add ATT command * fix project file * add test * update version * fix CHANGELOG --------- Co-authored-by: Sojiro Nishimura --- .spm-version | 2 +- CHANGELOG.md | 8 ++- Karte.xcodeproj/project.pbxproj | 12 +++- KarteCore.podspec | 2 +- KarteCore/Core/Command/CommandHandler.swift | 3 +- .../Core/Command/RequestATTCommand.swift | 49 +++++++++++++++ .../Core/RequestATTCommandSpec.swift | 61 +++++++++++++++++++ 7 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 KarteCore/Core/Command/RequestATTCommand.swift create mode 100644 KarteTests/KarteCoreTests/UnitTests/Core/RequestATTCommandSpec.swift diff --git a/.spm-version b/.spm-version index 6618ab54..cf869073 100644 --- a/.spm-version +++ b/.spm-version @@ -1 +1 @@ -2.17.0 \ No newline at end of file +2.18.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 08ef51ec..4e3078ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ | モジュール名 | Description | 最新のバージョン | | :-- | :-- | :-- | -| KarteCore | イベントトラッキング機能を提供します。 | 2.29.0 | +| KarteCore | イベントトラッキング機能を提供します。 | 2.30.0 | | KarteInAppMessaging | アプリ内メッセージ機能を提供します。 | 2.18.0 | | KarteRemoteNotification | プッシュ通知の受信および効果測定機能を提供します。 | 2.11.0 | | KarteVariables | 設定値配信機能を提供します。 | 2.10.0 | @@ -11,6 +11,12 @@ | KarteUtilities | KarteCore モジュール等が利用するUtility機能を提供します。通常直接参照する必要はありません。 | 3.12.0 | | KarteNotificationServiceExtension | リッチプッシュ通知機能を提供します。 | 1.2.0 | +# Releases - xxxx.xx.xx + +### Core 2.30.0 +** 🎉 FEATURE** +- Native機能呼び出しにATT許諾ダイアログ表示を追加しました。 + # Releases - 2024.08.26 ## Version 2.17.0 diff --git a/Karte.xcodeproj/project.pbxproj b/Karte.xcodeproj/project.pbxproj index 3e7ad43f..5ead936a 100644 --- a/Karte.xcodeproj/project.pbxproj +++ b/Karte.xcodeproj/project.pbxproj @@ -434,6 +434,8 @@ AF0A5F2F29546BB000209D4E /* Logger+Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2E29546BB000209D4E /* Logger+Tag.swift */; }; AF0A5F31295475B300209D4E /* KarteInbox.m in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F30295475B300209D4E /* KarteInbox.m */; }; AF0A5F352959986F00209D4E /* InboxLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F342959986F00209D4E /* InboxLoader.m */; }; + AF38FD9E2C7C7313009C1C20 /* RequestATTCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF38FD9D2C7C7313009C1C20 /* RequestATTCommand.swift */; }; + AF38FDA02C7C8108009C1C20 /* RequestATTCommandSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF38FD9F2C7C8108009C1C20 /* RequestATTCommandSpec.swift */; }; AF49FAA1296ED953005A7575 /* CallerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF49FAA0296ED953005A7575 /* CallerSpec.swift */; }; AF5EDEB329C1C49000D05825 /* OpenMessagesRequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF5EDEB229C1C49000D05825 /* OpenMessagesRequestSpec.swift */; }; AF5EDEB529C1C5A600D05825 /* OpenMessagesRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF5EDEB429C1C5A600D05825 /* OpenMessagesRequest.swift */; }; @@ -1031,6 +1033,8 @@ AF0A5F2E29546BB000209D4E /* Logger+Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logger+Tag.swift"; sourceTree = ""; }; AF0A5F30295475B300209D4E /* KarteInbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KarteInbox.m; sourceTree = ""; }; AF0A5F342959986F00209D4E /* InboxLoader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InboxLoader.m; sourceTree = ""; }; + AF38FD9D2C7C7313009C1C20 /* RequestATTCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestATTCommand.swift; sourceTree = ""; }; + AF38FD9F2C7C8108009C1C20 /* RequestATTCommandSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestATTCommandSpec.swift; sourceTree = ""; }; AF49FAA0296ED953005A7575 /* CallerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallerSpec.swift; sourceTree = ""; }; AF5EDEB229C1C49000D05825 /* OpenMessagesRequestSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenMessagesRequestSpec.swift; sourceTree = ""; }; AF5EDEB429C1C5A600D05825 /* OpenMessagesRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenMessagesRequest.swift; sourceTree = ""; }; @@ -2255,6 +2259,7 @@ 0CE33A0523F40C2200E2EB98 /* UserSyncParameterSpec.swift */, 681E83982483B54800A95083 /* RequestReviewCommandSpec.swift */, 681E839A2483B5C800A95083 /* OpenSettingsCommandSpec.swift */, + AF38FD9F2C7C8108009C1C20 /* RequestATTCommandSpec.swift */, ); path = Core; sourceTree = ""; @@ -2383,6 +2388,7 @@ 681E83942482A90E00A95083 /* OpenSettingsCommand.swift */, 680DB3C72480F74E00AE6800 /* Command.swift */, 681E838C248246B700A95083 /* RequestReviewCommand.swift */, + AF38FD9D2C7C7313009C1C20 /* RequestATTCommand.swift */, 681E838E2482510200A95083 /* CommandHandler.swift */, 681E8390248252EE00A95083 /* CommandHandlerLoader.m */, ); @@ -3112,6 +3118,7 @@ 777D605D274267FC00339D7E /* InvalidEventFieldNameFilterRule.swift in Sources */, 0C69D40F24EB9DB200D75893 /* InitializationEventFilterRule.swift in Sources */, 0C0822FB24EA615C0038EBDA /* CommandBundlerApplicationStateProvider.swift in Sources */, + AF38FD9E2C7C7313009C1C20 /* RequestATTCommand.swift in Sources */, 0C83928F2406C6AA0014C2BF /* InstallationStatus.swift in Sources */, 0C69D3FC24EB9D9D00D75893 /* TrackClientState.swift in Sources */, 0C8392B72406C7010014C2BF /* Module.swift in Sources */, @@ -3380,6 +3387,7 @@ 0CE79327238653AD00F0D932 /* SpecConfiguration.swift in Sources */, 0CC648B8238CCFC3009EB5DF /* StubBuilder.swift in Sources */, 0CCFA7B524A5814100E0F184 /* FCMTokenRegistrarSpec.swift in Sources */, + AF38FDA02C7C8108009C1C20 /* RequestATTCommandSpec.swift in Sources */, 0C839316240838050014C2BF /* ActionAppropriateViewDetectorSpec.swift in Sources */, 363F25F12582A1EB007E6E4B /* DefinitionsRequestSpec.swift in Sources */, 0C520BCC2990995000480B77 /* JSONConvertibleSpec.swift in Sources */, @@ -3852,7 +3860,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 2.29.0; + MARKETING_VERSION = 2.30.0; PRODUCT_BUNDLE_IDENTIFIER = io.karte.KarteCore; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; @@ -3887,7 +3895,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 2.29.0; + MARKETING_VERSION = 2.30.0; PRODUCT_BUNDLE_IDENTIFIER = io.karte.KarteCore; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; diff --git a/KarteCore.podspec b/KarteCore.podspec index 2c080587..276233de 100644 --- a/KarteCore.podspec +++ b/KarteCore.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'KarteCore' - s.version = '2.29.0' + s.version = '2.30.0' s.summary = 'KARTE Core SDK' s.homepage = 'https://karte.io' s.author = { 'PLAID' => 'dev.share@plaid.co.jp' } diff --git a/KarteCore/Core/Command/CommandHandler.swift b/KarteCore/Core/Command/CommandHandler.swift index 992e42dd..bc7a20e8 100644 --- a/KarteCore/Core/Command/CommandHandler.swift +++ b/KarteCore/Core/Command/CommandHandler.swift @@ -62,7 +62,8 @@ extension CommandHandler: DeepLinkModule { public func handle(app: UIApplication, open url: URL) -> Bool { let commands: [Command] = [ RequestReviewCommand(), - OpenSettingsCommand() + OpenSettingsCommand(), + RequestATTCommand() ] return commands.map { $0.run(url: url) }.contains(true) } diff --git a/KarteCore/Core/Command/RequestATTCommand.swift b/KarteCore/Core/Command/RequestATTCommand.swift new file mode 100644 index 00000000..48ff435b --- /dev/null +++ b/KarteCore/Core/Command/RequestATTCommand.swift @@ -0,0 +1,49 @@ +// +// Copyright 2024 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import AppTrackingTransparency + +internal struct RequestATTCommand: Command { + func validate(_ url: URL) -> Bool { + url.host == "request-att" + } + + func execute() { + if #available(iOS 14.5, *) { + guard ATTrackingManager.trackingAuthorizationStatus == .notDetermined else { + Logger.warn(tag: .core, message: "ATT is already determined, status = \(ATTrackingManager.trackingAuthorizationStatus)") + return + } + + ATTrackingManager.requestTrackingAuthorization { status in + switch status { + case .authorized: + Logger.info(tag: .core, message: "ATT status is authorized") + case .denied: + Logger.info(tag: .core, message: "ATT status is denied") + case .notDetermined: + Logger.info(tag: .core, message: "ATT status is notDetermined") + case .restricted: + Logger.info(tag: .core, message: "ATT status is restricted") + @unknown default: + Logger.warn(tag: .core, message: "ATT status is unknown: \(status)") + } + } + } else { + Logger.warn(tag: .core, message: "iOS version must be over 14.5, ATT is not available") + } + } +} diff --git a/KarteTests/KarteCoreTests/UnitTests/Core/RequestATTCommandSpec.swift b/KarteTests/KarteCoreTests/UnitTests/Core/RequestATTCommandSpec.swift new file mode 100644 index 00000000..1400d596 --- /dev/null +++ b/KarteTests/KarteCoreTests/UnitTests/Core/RequestATTCommandSpec.swift @@ -0,0 +1,61 @@ +// +// Copyright 2024 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Quick +import Nimble +@testable import KarteCore + +class RequestATTCommandSpec: QuickSpec { + override func spec() { + describe("its run") { + context("when invalid value passed") { + let examples = [ + "test:", + "krt:", + "krt://request-att", + "aaa-karte-sdk://request-att", + "krt-hSZM://request-att", + "krt-hSZMcVyjwg6Y7pdYMa4YPqmyQ77EpALw://request-review", + ] + examples.forEach { (input) in + context("\(input)") { + it("returns false") { + let c = RequestATTCommand() + let u = URL(string: input)! + expect(c.run(url: u)).to(beFalse()) + } + } + } + } + + context("when valid value passed") { + let examples = [ + "krt-hSZMcVyjwg6Y7pdYMa4YPqmyQ77EpALw://request-att", + "krt-HRTwj9QEZGJrTaTkADrtdxFTyuXUJVMh://request-att" + ] + examples.forEach { (input) in + context("\(input)") { + it("returns true") { + let c = RequestATTCommand() + let u = URL(string: input)! + expect(c.run(url: u)).to(beTrue()) + } + } + } + } + } + } +} From 836199285696abb9b90459c301b0b8c9f828fcc6 Mon Sep 17 00:00:00 2001 From: tanako Date: Sat, 21 Sep 2024 18:55:06 +0900 Subject: [PATCH 2/6] =?UTF-8?q?Swift6=E5=AF=BE=E5=BF=9C=E3=81=A8=E3=81=97?= =?UTF-8?q?=E3=81=A6InAppMessagingDelegate=E3=81=AE=E9=96=A2=E6=95=B0?= =?UTF-8?q?=E3=82=92MainActor=E3=81=AB=E9=9A=94=E9=9B=A2=20(#469)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 ++- Karte.xcodeproj/project.pbxproj | 4 +- KarteInAppMessaging.podspec | 2 +- KarteInAppMessaging/IAMProcess.swift | 9 +++- KarteInAppMessaging/InAppMessaging.swift | 4 +- .../InAppMessagingDelegate.swift | 2 +- KarteInAppMessaging/View/IAMWebView.swift | 42 ++++++++++--------- 7 files changed, 41 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e3078ec..8c55d550 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ | モジュール名 | Description | 最新のバージョン | | :-- | :-- | :-- | | KarteCore | イベントトラッキング機能を提供します。 | 2.30.0 | -| KarteInAppMessaging | アプリ内メッセージ機能を提供します。 | 2.18.0 | +| KarteInAppMessaging | アプリ内メッセージ機能を提供します。 | 2.19.0 | | KarteRemoteNotification | プッシュ通知の受信および効果測定機能を提供します。 | 2.11.0 | | KarteVariables | 設定値配信機能を提供します。 | 2.10.0 | | KarteVisualTracking | ビジュアルトラッキング機能を提供します。 | 2.12.0 | @@ -17,6 +17,10 @@ ** 🎉 FEATURE** - Native機能呼び出しにATT許諾ダイアログ表示を追加しました。 +### InAppMessaging 2.19.0 +** 🔨CHANGED** +- InAppMessagingDelegateの処理をMainActorに隔離しました。 + # Releases - 2024.08.26 ## Version 2.17.0 diff --git a/Karte.xcodeproj/project.pbxproj b/Karte.xcodeproj/project.pbxproj index 5ead936a..915e1788 100644 --- a/Karte.xcodeproj/project.pbxproj +++ b/Karte.xcodeproj/project.pbxproj @@ -3928,7 +3928,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 2.18.0; + MARKETING_VERSION = 2.19.0; PRODUCT_BUNDLE_IDENTIFIER = io.karte.KarteInAppMessaging; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; @@ -3961,7 +3961,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 2.18.0; + MARKETING_VERSION = 2.19.0; PRODUCT_BUNDLE_IDENTIFIER = io.karte.KarteInAppMessaging; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; diff --git a/KarteInAppMessaging.podspec b/KarteInAppMessaging.podspec index 1e2a2c8f..c3d75482 100644 --- a/KarteInAppMessaging.podspec +++ b/KarteInAppMessaging.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'KarteInAppMessaging' - s.version = '2.18.0' + s.version = '2.19.0' s.summary = 'KARTE In-app messaging SDK' s.homepage = 'https://karte.io' s.author = { 'PLAID' => 'dev.share@plaid.co.jp' } diff --git a/KarteInAppMessaging/IAMProcess.swift b/KarteInAppMessaging/IAMProcess.swift index 2321c46a..29a06664 100644 --- a/KarteInAppMessaging/IAMProcess.swift +++ b/KarteInAppMessaging/IAMProcess.swift @@ -247,7 +247,13 @@ extension IAMProcess { private func handleJsMessageEvent(_ data: JsMessage.EventData) { Tracker.track(view: window, data: data) - notifyCampaignOpenOrClose(data) + if Thread.isMainThread { + notifyCampaignOpenOrClose(data) + } else { + DispatchQueue.main.async { + self.notifyCampaignOpenOrClose(data) + } + } } private func handleJsMessageOpenURL(_ data: JsMessage.OpenURLData) { @@ -347,6 +353,7 @@ extension IAMProcess: IAMWebViewDelegate { return true } + @MainActor func inAppMessagingWebView(_ webView: IAMWebView, shouldOpenURL url: URL) -> Bool { let iam = InAppMessaging.shared guard let delegate = iam.delegate else { diff --git a/KarteInAppMessaging/InAppMessaging.swift b/KarteInAppMessaging/InAppMessaging.swift index ee5408cd..3e79f511 100644 --- a/KarteInAppMessaging/InAppMessaging.swift +++ b/KarteInAppMessaging/InAppMessaging.swift @@ -222,7 +222,7 @@ extension InAppMessaging { } } - @objc + @MainActor @objc private func observeWindowDidBecomeVisibleNotification(_ notification: Notification) { guard let window = notification.object as? UIWindow else { return @@ -255,7 +255,7 @@ extension InAppMessaging { pool.storeProcess(process) } - @objc + @MainActor @objc private func observeWindowDidBecomeHiddenNotification(_ notification: Notification) { guard let window = notification.object as? UIWindow else { return diff --git a/KarteInAppMessaging/InAppMessagingDelegate.swift b/KarteInAppMessaging/InAppMessagingDelegate.swift index f5c75418..98cbcef8 100644 --- a/KarteInAppMessaging/InAppMessagingDelegate.swift +++ b/KarteInAppMessaging/InAppMessagingDelegate.swift @@ -17,7 +17,7 @@ import UIKit /// アプリ内メッセージで発生するイベントを委譲するためのタイプです。 -@objc(KRTInAppMessagingDelegate) +@preconcurrency @MainActor @objc(KRTInAppMessagingDelegate) public protocol InAppMessagingDelegate: AnyObject { /// アプリ内メッセージ用のWindowが表示されたことを通知します。 /// diff --git a/KarteInAppMessaging/View/IAMWebView.swift b/KarteInAppMessaging/View/IAMWebView.swift index 13d80daa..be742acd 100644 --- a/KarteInAppMessaging/View/IAMWebView.swift +++ b/KarteInAppMessaging/View/IAMWebView.swift @@ -172,34 +172,36 @@ internal class IAMWebView: WKWebView { } func openURL(_ url: URL?, isReset: Bool) { - guard let url = url else { - Logger.debug(tag: .inAppMessaging, message: "Can't open URL because URL is nil.") - return - } + DispatchQueue.main.async { + guard let url = url else { + Logger.debug(tag: .inAppMessaging, message: "Can't open URL because URL is nil.") + return + } - if isReset { - reset(mode: .soft) - } + if isReset { + self.reset(mode: .soft) + } - if let delegate = delegate, !delegate.inAppMessagingWebView(self, shouldOpenURL: url) { - Logger.info(tag: .inAppMessaging, message: "SDK delegates openURL to client app. URL=\(url)") - return - } + if let delegate = self.delegate, !delegate.inAppMessagingWebView(self, shouldOpenURL: url) { + Logger.info(tag: .inAppMessaging, message: "SDK delegates openURL to client app. URL=\(url)") + return + } - if #available(iOS 10.0, *) { - UIApplication.shared.open(url, options: [:]) { successful in - if successful { + if #available(iOS 10.0, *) { + UIApplication.shared.open(url, options: [:]) { successful in + if successful { + Logger.info(tag: .inAppMessaging, message: "Success to open URL: \(url)") + } else { + Logger.error(tag: .inAppMessaging, message: "Failed to open URL: \(url)") + } + } + } else { + if UIApplication.shared.openURL(url) { Logger.info(tag: .inAppMessaging, message: "Success to open URL: \(url)") } else { Logger.error(tag: .inAppMessaging, message: "Failed to open URL: \(url)") } } - } else { - if UIApplication.shared.openURL(url) { - Logger.info(tag: .inAppMessaging, message: "Success to open URL: \(url)") - } else { - Logger.error(tag: .inAppMessaging, message: "Failed to open URL: \(url)") - } } } From a1ffd9f3428d351f7919ecd2f115296ae66e9bb6 Mon Sep 17 00:00:00 2001 From: Hajime Nakamura <5644420+nkmrh@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:06:39 +0900 Subject: [PATCH 3/6] Remove inbox (#474) * remove inbox * Update CHANGELOG.md --- .github/ISSUE_TEMPLATE/bug_report.md | 1 - .github/labeler.yml | 2 - .slather.yml | 1 - .swiftlint.yml | 1 - CHANGELOG.md | 4 + Karte.xcodeproj/project.pbxproj | 299 ------------------ KarteInbox.podspec | 35 -- KarteInbox/API/BaseAPIRequest.swift | 68 ---- KarteInbox/API/Caller.swift | 102 ------ KarteInbox/API/FetchMessagesRequest.swift | 61 ---- KarteInbox/API/InboxClient.swift | 45 --- KarteInbox/API/OpenMessagesRequest.swift | 48 --- KarteInbox/Config.swift | 33 -- KarteInbox/Inbox.swift | 75 ----- KarteInbox/InboxLoader.m | 36 --- KarteInbox/KarteInbox.h | 27 -- KarteInbox/KarteInbox.m | 25 -- KarteInbox/Logger+Tag.swift | 22 -- KarteInbox/Models/InboxMessage.swift | 156 --------- .../IntegrationTests/InboxSpec.swift | 133 -------- KarteTests/KarteInboxTests/TestUtil.swift | 24 -- .../UnitTests/CallerSpec.swift | 67 ---- .../UnitTests/FetchMessagesRequestSpec.swift | 68 ---- .../UnitTests/OpenMessagesRequestSpec.swift | 53 ---- KarteTests/Stub/StubResource.swift | 2 - KarteTests/Stub/success_inbox.json | 36 --- KarteTests/Stub/success_inbox_empty.json | 3 - Package.swift | 7 - scripts/bump_version.sh | 1 - scripts/publish.sh | 2 +- 30 files changed, 5 insertions(+), 1432 deletions(-) delete mode 100644 KarteInbox.podspec delete mode 100644 KarteInbox/API/BaseAPIRequest.swift delete mode 100644 KarteInbox/API/Caller.swift delete mode 100644 KarteInbox/API/FetchMessagesRequest.swift delete mode 100644 KarteInbox/API/InboxClient.swift delete mode 100644 KarteInbox/API/OpenMessagesRequest.swift delete mode 100644 KarteInbox/Config.swift delete mode 100644 KarteInbox/Inbox.swift delete mode 100644 KarteInbox/InboxLoader.m delete mode 100644 KarteInbox/KarteInbox.h delete mode 100644 KarteInbox/KarteInbox.m delete mode 100644 KarteInbox/Logger+Tag.swift delete mode 100644 KarteInbox/Models/InboxMessage.swift delete mode 100644 KarteTests/KarteInboxTests/IntegrationTests/InboxSpec.swift delete mode 100644 KarteTests/KarteInboxTests/TestUtil.swift delete mode 100644 KarteTests/KarteInboxTests/UnitTests/CallerSpec.swift delete mode 100644 KarteTests/KarteInboxTests/UnitTests/FetchMessagesRequestSpec.swift delete mode 100644 KarteTests/KarteInboxTests/UnitTests/OpenMessagesRequestSpec.swift delete mode 100644 KarteTests/Stub/success_inbox.json delete mode 100644 KarteTests/Stub/success_inbox_empty.json diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index ebd56a24..701e0f6d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -36,7 +36,6 @@ Please fill in as much of the template below as you can. - KarteRemoteNotification x.x.x - KarteVariables x.x.x - KarteVisualTracking x.x.x -- KarteInbox x.x.x - KarteUtilities x.x.x - KarteNotificationServiceExtension x.x.x diff --git a/.github/labeler.yml b/.github/labeler.yml index b9719174..451b445d 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -12,8 +12,6 @@ - KarteVariables/** 'Module:VT': - KarteVisualTracking/** -'Module:Inbox': - - KarteInbox/** 'Module:Detectors': - KarteDetectors/** 'Module:Utilities': diff --git a/.slather.yml b/.slather.yml index 1cd7bf16..9ccfcd74 100644 --- a/.slather.yml +++ b/.slather.yml @@ -9,7 +9,6 @@ binary_basename: - KarteRemoteNotification - KarteVisualTracking - KarteVariables - - KarteInbox - KarteCrashReporting - KarteUtilities - KarteNotificationServiceExtension diff --git a/.swiftlint.yml b/.swiftlint.yml index 95a763e6..d0057f4c 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -121,7 +121,6 @@ included: - KarteInAppMessaging - KarteRemoteNotification - KarteVariables - - KarteInbox - KarteVisualTracking - KarteCrashReporting - KarteNotificationServiceExtension diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c55d550..12f6cc80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ # Releases - xxxx.xx.xx +### Inbox +** 🔨CHANGED** +- Inboxモジュール(β版)の公開を停止しました。 + ### Core 2.30.0 ** 🎉 FEATURE** - Native機能呼び出しにATT許諾ダイアログ表示を追加しました。 diff --git a/Karte.xcodeproj/project.pbxproj b/Karte.xcodeproj/project.pbxproj index 915e1788..b5bc02a8 100644 --- a/Karte.xcodeproj/project.pbxproj +++ b/Karte.xcodeproj/project.pbxproj @@ -13,7 +13,6 @@ buildPhases = ( ); dependencies = ( - AFFED73C2976AE0400189320 /* PBXTargetDependency */, 0CFB1F57243636AD00BC8757 /* PBXTargetDependency */, 0CFB1F55243636A900BC8757 /* PBXTargetDependency */, 0CCB411523D82758000B5AB9 /* PBXTargetDependency */, @@ -424,27 +423,8 @@ 843BC1072AF316ED00D1C0A0 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 843BC1062AF316ED00D1C0A0 /* PrivacyInfo.xcprivacy */; }; 843BC1092AF3173C00D1C0A0 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 843BC1082AF3173C00D1C0A0 /* PrivacyInfo.xcprivacy */; }; 93E00F8E28745FF500116B5B /* IAMProcessPoolSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93E00F8D28745FF500116B5B /* IAMProcessPoolSpec.swift */; }; - AF0A5F1C2954674500209D4E /* KarteInbox.h in Headers */ = {isa = PBXBuildFile; fileRef = AF0A5F192954674500209D4E /* KarteInbox.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AF0A5F2129546A6800209D4E /* Inbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2029546A6800209D4E /* Inbox.swift */; }; - AF0A5F2429546AB400209D4E /* InboxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2329546AB400209D4E /* InboxMessage.swift */; }; - AF0A5F2729546AE300209D4E /* InboxClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2629546AE300209D4E /* InboxClient.swift */; }; - AF0A5F2929546AFC00209D4E /* Caller.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2829546AFC00209D4E /* Caller.swift */; }; - AF0A5F2B29546B3500209D4E /* BaseAPIRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2A29546B3500209D4E /* BaseAPIRequest.swift */; }; - AF0A5F2D29546B5B00209D4E /* FetchMessagesRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2C29546B5B00209D4E /* FetchMessagesRequest.swift */; }; - AF0A5F2F29546BB000209D4E /* Logger+Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2E29546BB000209D4E /* Logger+Tag.swift */; }; - AF0A5F31295475B300209D4E /* KarteInbox.m in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F30295475B300209D4E /* KarteInbox.m */; }; - AF0A5F352959986F00209D4E /* InboxLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F342959986F00209D4E /* InboxLoader.m */; }; AF38FD9E2C7C7313009C1C20 /* RequestATTCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF38FD9D2C7C7313009C1C20 /* RequestATTCommand.swift */; }; AF38FDA02C7C8108009C1C20 /* RequestATTCommandSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF38FD9F2C7C8108009C1C20 /* RequestATTCommandSpec.swift */; }; - AF49FAA1296ED953005A7575 /* CallerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF49FAA0296ED953005A7575 /* CallerSpec.swift */; }; - AF5EDEB329C1C49000D05825 /* OpenMessagesRequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF5EDEB229C1C49000D05825 /* OpenMessagesRequestSpec.swift */; }; - AF5EDEB529C1C5A600D05825 /* OpenMessagesRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF5EDEB429C1C5A600D05825 /* OpenMessagesRequest.swift */; }; - AF5EDEB929C30CE700D05825 /* success_inbox_empty.json in Resources */ = {isa = PBXBuildFile; fileRef = AF5EDEB829C30A5400D05825 /* success_inbox_empty.json */; }; - AF9677FD29C86659008C80BC /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF9677FC29C86659008C80BC /* Config.swift */; }; - AF9677FF29CAE5FD008C80BC /* TestUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF9677FE29CAE5FD008C80BC /* TestUtil.swift */; }; - AFA6E8142987B03500111497 /* InboxSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA6E8132987B03500111497 /* InboxSpec.swift */; }; - AFA6E8162987CBD400111497 /* success_inbox.json in Resources */ = {isa = PBXBuildFile; fileRef = AFA6E8152987CBD400111497 /* success_inbox.json */; }; - AFCAF2C4299F6809005B4DCC /* FetchMessagesRequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCAF2C3299F6809005B4DCC /* FetchMessagesRequestSpec.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -581,27 +561,6 @@ remoteGlobalIDString = 0C060E972384D76C006AF974; remoteInfo = KarteUtilities; }; - AF49FAA2296EDA60005A7575 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0C6FE20D22F3F41C00F2FD28 /* Project object */; - proxyType = 1; - remoteGlobalIDString = AF0A5F162954674500209D4E; - remoteInfo = KarteInbox; - }; - AFFED73B2976AE0400189320 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0C6FE20D22F3F41C00F2FD28 /* Project object */; - proxyType = 1; - remoteGlobalIDString = AF0A5F162954674500209D4E; - remoteInfo = KarteInbox; - }; - AFFED73D2976AEA600189320 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0C6FE20D22F3F41C00F2FD28 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 0C89742F2379040700098CD8; - remoteInfo = KarteCore; - }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -1022,28 +981,8 @@ 843BC1082AF3173C00D1C0A0 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 92F48DFCD76A0CA4C901907E /* Pods-KarteTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KarteTests.release.xcconfig"; path = "Target Support Files/Pods-KarteTests/Pods-KarteTests.release.xcconfig"; sourceTree = ""; }; 93E00F8D28745FF500116B5B /* IAMProcessPoolSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IAMProcessPoolSpec.swift; sourceTree = ""; }; - AF0A5F172954674500209D4E /* KarteInbox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KarteInbox.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - AF0A5F192954674500209D4E /* KarteInbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KarteInbox.h; sourceTree = ""; }; - AF0A5F2029546A6800209D4E /* Inbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Inbox.swift; sourceTree = ""; }; - AF0A5F2329546AB400209D4E /* InboxMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboxMessage.swift; sourceTree = ""; }; - AF0A5F2629546AE300209D4E /* InboxClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboxClient.swift; sourceTree = ""; }; - AF0A5F2829546AFC00209D4E /* Caller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Caller.swift; sourceTree = ""; }; - AF0A5F2A29546B3500209D4E /* BaseAPIRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseAPIRequest.swift; sourceTree = ""; }; - AF0A5F2C29546B5B00209D4E /* FetchMessagesRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchMessagesRequest.swift; sourceTree = ""; }; - AF0A5F2E29546BB000209D4E /* Logger+Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logger+Tag.swift"; sourceTree = ""; }; - AF0A5F30295475B300209D4E /* KarteInbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KarteInbox.m; sourceTree = ""; }; - AF0A5F342959986F00209D4E /* InboxLoader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InboxLoader.m; sourceTree = ""; }; AF38FD9D2C7C7313009C1C20 /* RequestATTCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestATTCommand.swift; sourceTree = ""; }; AF38FD9F2C7C8108009C1C20 /* RequestATTCommandSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestATTCommandSpec.swift; sourceTree = ""; }; - AF49FAA0296ED953005A7575 /* CallerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallerSpec.swift; sourceTree = ""; }; - AF5EDEB229C1C49000D05825 /* OpenMessagesRequestSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenMessagesRequestSpec.swift; sourceTree = ""; }; - AF5EDEB429C1C5A600D05825 /* OpenMessagesRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenMessagesRequest.swift; sourceTree = ""; }; - AF5EDEB829C30A5400D05825 /* success_inbox_empty.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = success_inbox_empty.json; sourceTree = ""; }; - AF9677FC29C86659008C80BC /* Config.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = ""; }; - AF9677FE29CAE5FD008C80BC /* TestUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUtil.swift; sourceTree = ""; }; - AFA6E8132987B03500111497 /* InboxSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboxSpec.swift; sourceTree = ""; }; - AFA6E8152987CBD400111497 /* success_inbox.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = success_inbox.json; sourceTree = ""; }; - AFCAF2C3299F6809005B4DCC /* FetchMessagesRequestSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchMessagesRequestSpec.swift; sourceTree = ""; }; BFCBE7E59096A32C44932285 /* Pods-KarteTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KarteTests.debug.xcconfig"; path = "Target Support Files/Pods-KarteTests/Pods-KarteTests.debug.xcconfig"; sourceTree = ""; }; BFF77FFF3DF47D9011A20C08 /* Pods-Karte.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Karte.debug.xcconfig"; path = "Target Support Files/Pods-Karte/Pods-Karte.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1114,13 +1053,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - AF0A5F142954674500209D4E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -1503,7 +1435,6 @@ 0C060E992384D76C006AF974 /* KarteUtilities */, 5013526D277AB8E60026E1F9 /* KarteNotificationServiceExtension */, 0CE792E423862C9C00F0D932 /* KarteTests */, - AF0A5F182954674500209D4E /* KarteInbox */, 0C6FE21722F3F41C00F2FD28 /* Products */, 0C6FE2D222F826CA00F2FD28 /* Frameworks */, 707708FD2279E9E9AA8EDDF6 /* Pods */, @@ -1522,7 +1453,6 @@ 0C060E982384D76C006AF974 /* KarteUtilities.framework */, 0CE792E323862C9C00F0D932 /* KarteTests.xctest */, 5013526C277AB8E60026E1F9 /* KarteNotificationServiceExtension.framework */, - AF0A5F172954674500209D4E /* KarteInbox.framework */, ); name = Products; sourceTree = ""; @@ -2026,8 +1956,6 @@ 0CC648C5238D5559009EB5DF /* success_vt_2.json */, 363F260D2582AE60007E6E4B /* success_vt_definitions.json */, 6857834527478B7000A1AE58 /* success_vt_definitions_with_dynamic_fields.json */, - AFA6E8152987CBD400111497 /* success_inbox.json */, - AF5EDEB829C30A5400D05825 /* success_inbox_empty.json */, ); path = Stub; sourceTree = ""; @@ -2141,7 +2069,6 @@ 0CA52D572387B96D00A575BC /* KarteRemoteNotification */, 0CE7933B2386913B00F0D932 /* KarteVariablesTests */, 0CE7933A2386913000F0D932 /* KarteVisualTrackingTests */, - AF49FA9E296ED81D005A7575 /* KarteInboxTests */, 0CE7932E23865C8B00F0D932 /* KarteUtilitiesTests */, 0CC648AE238A153F009EB5DF /* Stub */, 0CE79308238653AD00F0D932 /* SpecConfiguration.swift */, @@ -2425,69 +2352,6 @@ path = Pods; sourceTree = ""; }; - AF0A5F182954674500209D4E /* KarteInbox */ = { - isa = PBXGroup; - children = ( - AF0A5F2529546AD800209D4E /* API */, - AF0A5F2229546AA200209D4E /* Models */, - AF0A5F342959986F00209D4E /* InboxLoader.m */, - AF0A5F192954674500209D4E /* KarteInbox.h */, - AF0A5F30295475B300209D4E /* KarteInbox.m */, - AF0A5F2029546A6800209D4E /* Inbox.swift */, - AF0A5F2E29546BB000209D4E /* Logger+Tag.swift */, - AF9677FC29C86659008C80BC /* Config.swift */, - ); - path = KarteInbox; - sourceTree = ""; - }; - AF0A5F2229546AA200209D4E /* Models */ = { - isa = PBXGroup; - children = ( - AF0A5F2329546AB400209D4E /* InboxMessage.swift */, - ); - path = Models; - sourceTree = ""; - }; - AF0A5F2529546AD800209D4E /* API */ = { - isa = PBXGroup; - children = ( - AF0A5F2629546AE300209D4E /* InboxClient.swift */, - AF0A5F2829546AFC00209D4E /* Caller.swift */, - AF0A5F2A29546B3500209D4E /* BaseAPIRequest.swift */, - AF0A5F2C29546B5B00209D4E /* FetchMessagesRequest.swift */, - AF5EDEB429C1C5A600D05825 /* OpenMessagesRequest.swift */, - ); - path = API; - sourceTree = ""; - }; - AF49FA9E296ED81D005A7575 /* KarteInboxTests */ = { - isa = PBXGroup; - children = ( - AFA6E8122987AFFF00111497 /* IntegrationTests */, - AF49FA9F296ED85A005A7575 /* UnitTests */, - AF9677FE29CAE5FD008C80BC /* TestUtil.swift */, - ); - path = KarteInboxTests; - sourceTree = ""; - }; - AF49FA9F296ED85A005A7575 /* UnitTests */ = { - isa = PBXGroup; - children = ( - AF49FAA0296ED953005A7575 /* CallerSpec.swift */, - AFCAF2C3299F6809005B4DCC /* FetchMessagesRequestSpec.swift */, - AF5EDEB229C1C49000D05825 /* OpenMessagesRequestSpec.swift */, - ); - path = UnitTests; - sourceTree = ""; - }; - AFA6E8122987AFFF00111497 /* IntegrationTests */ = { - isa = PBXGroup; - children = ( - AFA6E8132987B03500111497 /* InboxSpec.swift */, - ); - path = IntegrationTests; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -2561,14 +2425,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - AF0A5F122954674500209D4E /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - AF0A5F1C2954674500209D4E /* KarteInbox.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -2719,7 +2575,6 @@ buildRules = ( ); dependencies = ( - AF49FAA3296EDA60005A7575 /* PBXTargetDependency */, 0CE7933923867ACF00F0D932 /* PBXTargetDependency */, 0CA52D4E2387A9D200A575BC /* PBXTargetDependency */, 0CA52D502387A9D200A575BC /* PBXTargetDependency */, @@ -2750,25 +2605,6 @@ productReference = 5013526C277AB8E60026E1F9 /* KarteNotificationServiceExtension.framework */; productType = "com.apple.product-type.framework"; }; - AF0A5F162954674500209D4E /* KarteInbox */ = { - isa = PBXNativeTarget; - buildConfigurationList = AF0A5F1F2954674500209D4E /* Build configuration list for PBXNativeTarget "KarteInbox" */; - buildPhases = ( - AF0A5F122954674500209D4E /* Headers */, - AF0A5F132954674500209D4E /* Sources */, - AF0A5F142954674500209D4E /* Frameworks */, - AF0A5F152954674500209D4E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - AFFED73E2976AEA600189320 /* PBXTargetDependency */, - ); - name = KarteInbox; - productName = KarteInbox; - productReference = AF0A5F172954674500209D4E /* KarteInbox.framework */; - productType = "com.apple.product-type.framework"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -2820,10 +2656,6 @@ 5013526B277AB8E60026E1F9 = { CreatedOnToolsVersion = 13.2.1; }; - AF0A5F162954674500209D4E = { - CreatedOnToolsVersion = 14.2; - LastSwiftMigration = 1420; - }; }; }; buildConfigurationList = 0C6FE21022F3F41C00F2FD28 /* Build configuration list for PBXProject "Karte" */; @@ -2844,7 +2676,6 @@ 0C897449237904F700098CD8 /* KarteVariables */, 0C8974562379050600098CD8 /* KarteVisualTracking */, 0C897689237BBA5300098CD8 /* KarteRemoteNotification */, - AF0A5F162954674500209D4E /* KarteInbox */, 0C2B3C6B2382684C008A2708 /* KarteCrashReporting */, 0C060E972384D76C006AF974 /* KarteUtilities */, 5013526B277AB8E60026E1F9 /* KarteNotificationServiceExtension */, @@ -2920,8 +2751,6 @@ 0CF44AFB242E451000CA7F3A /* success_variables_3.json in Resources */, 363F26172582B028007E6E4B /* success_vt_definitions.json in Resources */, 1EE766B7297546440040278E /* Karte-custom-Info.plist in Resources */, - AFA6E8162987CBD400111497 /* success_inbox.json in Resources */, - AF5EDEB929C30CE700D05825 /* success_inbox_empty.json in Resources */, 6857834627478B7000A1AE58 /* success_vt_definitions_with_dynamic_fields.json in Resources */, 36EFDED5271BF26700C60666 /* failure_invalid_request.json in Resources */, 36EFDEDF271BF26B00C60666 /* failure_server_error.json in Resources */, @@ -2939,13 +2768,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - AF0A5F152954674500209D4E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -3356,9 +3178,7 @@ 6837631B252FDAE200E690CE /* SelectorDetectorMock.swift in Sources */, 0C6619CE299DBF08006FF9E1 /* TrackMessageOpenSpec.swift in Sources */, 0CE79311238653AD00F0D932 /* StubActionModule.swift in Sources */, - AF9677FF29CAE5FD008C80BC /* TestUtil.swift in Sources */, 0CD4847A2508716F007F52E1 /* MeasurementSpec.swift in Sources */, - AFA6E8142987B03500111497 /* InboxSpec.swift in Sources */, 0C83931C240838320014C2BF /* DefinitionMatchSpec.swift in Sources */, 0C839309240822A40014C2BF /* RenewVisitorIdEventSpec.swift in Sources */, 0C839317240838050014C2BF /* LogicalOperatorSpec.swift in Sources */, @@ -3379,7 +3199,6 @@ 0CCFA7BB24A5D8D500E0F184 /* NotificationSettingsProviderMock.swift in Sources */, 0C839313240837D40014C2BF /* VariableSpec.swift in Sources */, 0C83931B240838320014C2BF /* DefinitionLoadSpec.swift in Sources */, - AF5EDEB329C1C49000D05825 /* OpenMessagesRequestSpec.swift in Sources */, 93E00F8E28745FF500116B5B /* IAMProcessPoolSpec.swift in Sources */, 0C8392F82407CEC50014C2BF /* VersionServiceSpec.swift in Sources */, 0C839315240838050014C2BF /* ActionSpec.swift in Sources */, @@ -3396,7 +3215,6 @@ 0C520BD02990C50100480B77 /* JSONValueSpec.swift in Sources */, 0C69D3E724EB859900D75893 /* CommandBundlerSpec.swift in Sources */, 0C8392FF240822A40014C2BF /* BackgroundEventSpec.swift in Sources */, - AFCAF2C4299F6809005B4DCC /* FetchMessagesRequestSpec.swift in Sources */, 0C83930F2408294D0014C2BF /* TrackCommonSpec.swift in Sources */, 0C839314240837E70014C2BF /* VariablesSpec.swift in Sources */, 0C839303240822A40014C2BF /* ViewEventSpec.swift in Sources */, @@ -3407,7 +3225,6 @@ 0C83930B240824110014C2BF /* FindMyselfSpec.swift in Sources */, 36404EBA247D5EB400F35ECB /* DeepLinkEventSpec.swift in Sources */, 0C8392FB240810920014C2BF /* UserSyncParameterSpec.swift in Sources */, - AF49FAA1296ED953005A7575 /* CallerSpec.swift in Sources */, 0C0822FF24EA6C2E0038EBDA /* CommandBundlerApplicationStateProviderMock.swift in Sources */, 36EFDE972719738500C60666 /* CircuitBreakerSpec.swift in Sources */, 0CDBACCF23A8719300CEB853 /* Assertions.swift in Sources */, @@ -3447,24 +3264,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - AF0A5F132954674500209D4E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - AF0A5F352959986F00209D4E /* InboxLoader.m in Sources */, - AF0A5F2D29546B5B00209D4E /* FetchMessagesRequest.swift in Sources */, - AF0A5F2B29546B3500209D4E /* BaseAPIRequest.swift in Sources */, - AF0A5F2429546AB400209D4E /* InboxMessage.swift in Sources */, - AF9677FD29C86659008C80BC /* Config.swift in Sources */, - AF0A5F2F29546BB000209D4E /* Logger+Tag.swift in Sources */, - AF0A5F2129546A6800209D4E /* Inbox.swift in Sources */, - AF0A5F2929546AFC00209D4E /* Caller.swift in Sources */, - AF0A5F31295475B300209D4E /* KarteInbox.m in Sources */, - AF0A5F2729546AE300209D4E /* InboxClient.swift in Sources */, - AF5EDEB529C1C5A600D05825 /* OpenMessagesRequest.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -3563,21 +3362,6 @@ target = 0C060E972384D76C006AF974 /* KarteUtilities */; targetProxy = 0CFB1F56243636AD00BC8757 /* PBXContainerItemProxy */; }; - AF49FAA3296EDA60005A7575 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = AF0A5F162954674500209D4E /* KarteInbox */; - targetProxy = AF49FAA2296EDA60005A7575 /* PBXContainerItemProxy */; - }; - AFFED73C2976AE0400189320 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = AF0A5F162954674500209D4E /* KarteInbox */; - targetProxy = AFFED73B2976AE0400189320 /* PBXContainerItemProxy */; - }; - AFFED73E2976AEA600189320 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0C89742F2379040700098CD8 /* KarteCore */; - targetProxy = AFFED73D2976AEA600189320 /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -4313,80 +4097,6 @@ }; name = Release; }; - AF0A5F1D2954674500209D4E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "INBOX_VERSION=$(MARKETING_VERSION)", - ); - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 PLAID, inc. All rights reserved."; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MARKETING_VERSION = 0.1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.karte.KarteInbox; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; - SUPPORTS_MACCATALYST = NO; - SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - AF0A5F1E2954674500209D4E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREPROCESSOR_DEFINITIONS = "INBOX_VERSION=$(MARKETING_VERSION)"; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 PLAID, inc. All rights reserved."; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MARKETING_VERSION = 0.1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.karte.KarteInbox; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; - SUPPORTS_MACCATALYST = NO; - SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -4498,15 +4208,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - AF0A5F1F2954674500209D4E /* Build configuration list for PBXNativeTarget "KarteInbox" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - AF0A5F1D2954674500209D4E /* Debug */, - AF0A5F1E2954674500209D4E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ }; rootObject = 0C6FE20D22F3F41C00F2FD28 /* Project object */; diff --git a/KarteInbox.podspec b/KarteInbox.podspec deleted file mode 100644 index 665d486d..00000000 --- a/KarteInbox.podspec +++ /dev/null @@ -1,35 +0,0 @@ -# -# Be sure to run `pod lib lint KarteTracker.podspec' to ensure this is a -# valid spec before submitting. -# -# Any lines starting with a # are optional, but their use is encouraged -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html -# - -Pod::Spec.new do |s| - s.name = 'KarteInbox' - s.version = '0.1.0' - s.summary = 'KARTE Inbox SDK' - s.homepage = 'https://karte.io' - s.author = { 'PLAID' => 'dev.share@plaid.co.jp' } - s.documentation_url = 'https://developers.karte.io/docs/ios-sdk' - s.license = { :type => 'Apache', :file => 'LICENSE' } - - s.cocoapods_version = '>= 1.7.0' - s.swift_versions = [5.2] - s.static_framework = true - - s.platform = :ios - s.ios.deployment_target = '13.0' - - s.source = { :git => 'https://github.com/plaidev/karte-ios-sdk.git', :tag => "Inbox-#{s.version}" } - s.source_files = 'KarteInbox/**/*.{swift,h,m}' - - s.requires_arc = true - s.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'INBOX_VERSION=' + s.version.to_s - } - - s.dependency 'KarteCore', '~> 2.22' - s.dependency 'KarteUtilities', '~> 3.5' -end diff --git a/KarteInbox/API/BaseAPIRequest.swift b/KarteInbox/API/BaseAPIRequest.swift deleted file mode 100644 index 2333fda8..00000000 --- a/KarteInbox/API/BaseAPIRequest.swift +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright 2022 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import KarteUtilities - -protocol BaseAPIRequest { - associatedtype Response where Response: Decodable - - var apiKey: String { get } - var config: InboxConfig { get } - var version: String { get } - var method: HTTPMethod { get } - var path: String { get } - var headers: [String: String] { get } - var queryItems: [URLQueryItem]? { get } - var bodyParams: [String: Any]? { get } -} - -extension BaseAPIRequest { - var apiKey: String { - Inbox.currentApiKey - } - - var version: String { - "/v2native" - } - - var headers: [String: String] { - [ - "Content-Type": "application/json; charset=utf-8", - "X-KARTE-Api-Key": apiKey - ] - } - - var queryItems: [URLQueryItem]? { - nil - } - - var bodyParams: [String: Any]? { - nil - } - - func asURLRequest() -> URLRequest { - var urlComponents = URLComponents(string: "\(config.baseUrl.absoluteString)\(version)/\(path)")! - urlComponents.queryItems = queryItems - var req = URLRequest(url: urlComponents.url!) - req.allHTTPHeaderFields = headers - req.httpMethod = method.rawValue - if let params = bodyParams { - req.httpBody = try? JSONSerialization.data(withJSONObject: params, options: []) - } - return req - } -} diff --git a/KarteInbox/API/Caller.swift b/KarteInbox/API/Caller.swift deleted file mode 100644 index 4b569076..00000000 --- a/KarteInbox/API/Caller.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// Copyright 2022 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import KarteCore -import KarteUtilities - -protocol Caller { - func callAsFunction(callee request: Request) async -> Request.Response? - func intercept(data: Data, response: URLResponse) -> Data? - func parseError(_ response: URLResponse, _ data: Data) -> (String, String) -} - -extension Caller { - func intercept(data: Data, response: URLResponse) -> Data? { - guard let status = (response as? HTTPURLResponse)?.statusCode else { - Logger.error(tag: .inbox, message: "Invalid response is returned") - return nil - } - - switch status { - case 200..<300: - Logger.verbose(tag: .inbox, message: "\(status): The server returned a normal response") - case 400..<500: - // swiftlint:disable:next no_fallthrough_only - fallthrough - default: - let (path, error) = parseError(response, data) - Logger.error(tag: .inbox, message: "\(status): The server returned an error on \(path): \(error)") - return nil - } - return data - } - - func parseError(_ response: URLResponse, _ data: Data) -> (String, String) { - let path = (response as? HTTPURLResponse)?.url?.pathComponents.joined(separator: "/") - return (String(describing: path), String(data: data, encoding: .utf8) ?? "") - } -} - -@available(iOS 15.0, *) -struct NativeAsyncCaller: Caller { - func callAsFunction(callee request: Request) async -> Request.Response? { - do { - let req = request.asURLRequest() - let (data, response) = try await URLSession.shared.data(for: req) - guard let res = intercept(data: data, response: response) else { - return nil - } - let decoder = createJSONDecoder() - decoder.keyDecodingStrategy = .convertFromSnakeCase - return try decoder.decode(Request.Response.self, from: res) - } catch { - Logger.error(tag: .inbox, message: "At line \(#line) of \(#file): \(error)") - return nil - } - } -} - -struct FallbackAsyncCaller: Caller { - func callAsFunction(callee request: Request) async -> Request.Response? { - let req = request.asURLRequest() - return await withCheckedContinuation { continuation in - URLSession.shared.dataTask(with: req) { (data, response, error) in - do { - guard let data = data, let response = response else { - if let status = (response as? HTTPURLResponse)?.statusCode { - throw ResponseError.unacceptableStatusCode(status) - } else { - throw ResponseError.nonHTTPURLResponse(response) - } - } - - guard let res = intercept(data: data, response: response) else { - continuation.resume(returning: nil) - return - } - let decoder = createJSONDecoder() - decoder.keyDecodingStrategy = .convertFromSnakeCase - let decoded = try decoder.decode(Request.Response.self, from: res) - continuation.resume(returning: decoded) - } catch { - Logger.error(tag: .inbox, message: error.localizedDescription) - continuation.resume(returning: nil) - } - }.resume() - } - } -} diff --git a/KarteInbox/API/FetchMessagesRequest.swift b/KarteInbox/API/FetchMessagesRequest.swift deleted file mode 100644 index e6fa222a..00000000 --- a/KarteInbox/API/FetchMessagesRequest.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright 2022 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import KarteUtilities - -struct FetchMessagesRequest: BaseAPIRequest { - typealias Response = FetchMessagesResponse - - let visitorId: String - let limit: UInt? - let latestMessageId: String? - let config: InboxConfig - - init(visitorId: String, limit: UInt? = nil, latestMessageId: String? = nil, config: InboxConfig) { - self.visitorId = visitorId - self.limit = limit - self.latestMessageId = latestMessageId - self.config = config - } - - var method: HTTPMethod { - .post - } - - var path: String { - "inbox/fetchMessages" - } - - var bodyParams: [String: Any]? { - var body: [String: Any] = [ - "visitorId": visitorId, - "appType": "native_app", - "os": "ios" - ] - if let limit = limit { - body["limit"] = limit - } - if let latest = latestMessageId { - body["latestMessageId"] = latest - } - return body - } -} - -struct FetchMessagesResponse: Decodable { - let messages: [InboxMessage] -} diff --git a/KarteInbox/API/InboxClient.swift b/KarteInbox/API/InboxClient.swift deleted file mode 100644 index 7c8d611c..00000000 --- a/KarteInbox/API/InboxClient.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright 2022 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -struct InboxClient { - private static let config = ProductionConfig() - - private static func call(_ request: Request) async -> Request.Response? { - if #available(iOS 15.0, *) { - let caller = NativeAsyncCaller() - return await caller(callee: request) - } else { - let caller = FallbackAsyncCaller() - return await caller(callee: request) - } - } -} - -extension InboxClient { - static func fetchMessages(by visitorId: String, limit: UInt? = nil, latestMessageId: String? = nil) async -> [InboxMessage]? { - let req = FetchMessagesRequest(visitorId: visitorId, limit: limit, latestMessageId: latestMessageId, config: config) - let res = await call(req) - return res?.messages - } - - static func openMessages(for visitorId: String, messageIds: [String]) async -> Bool { - let req = OpenMessagesRequest(visitorId: visitorId, messageIds: messageIds, config: config) - let res = await call(req) - return res?.success ?? false - } -} diff --git a/KarteInbox/API/OpenMessagesRequest.swift b/KarteInbox/API/OpenMessagesRequest.swift deleted file mode 100644 index f331e643..00000000 --- a/KarteInbox/API/OpenMessagesRequest.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright 2023 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import KarteUtilities - -struct OpenMessagesRequest: BaseAPIRequest { - typealias Response = OpenMessagesResponse - - let visitorId: String - let messageIds: [String] - let config: InboxConfig - - var method: HTTPMethod { - .post - } - - var path: String { - "inbox/openMessages" - } - - var bodyParams: [String: Any]? { - let body: [String: Any] = [ - "visitorId": visitorId, - "appType": "native_app", - "os": "ios", - "messageIds": messageIds - ] - return body - } -} - -struct OpenMessagesResponse: Decodable { - let success: Bool -} diff --git a/KarteInbox/Config.swift b/KarteInbox/Config.swift deleted file mode 100644 index d5cb4a0c..00000000 --- a/KarteInbox/Config.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright 2023 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -protocol InboxConfig { - var baseUrl: URL { get } -} - -struct ProductionConfig: InboxConfig { - var baseUrl: URL { - URL(string: "https://api.karte.io")! - } -} - -struct EvaluationConfig: InboxConfig { - var baseUrl: URL { - URL(string: "https://api-evaluation.dev-karte.com")! - } -} diff --git a/KarteInbox/Inbox.swift b/KarteInbox/Inbox.swift deleted file mode 100644 index 8e45bee1..00000000 --- a/KarteInbox/Inbox.swift +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright 2022 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import KarteCore - -/// Karteから送信したPush通知の履歴を取得するクラスです。 -@objc(KRTInbox) -public class Inbox: NSObject { - static let shared = Inbox() - - private var _apiKey: String? - - public static var currentApiKey: String { - shared._apiKey ?? "" - } - - override private init() {} - - /// ローダークラスが Objective-Cランライムに追加されたタイミングで呼び出されるメソッドです。 - /// 本メソッドが呼び出されたタイミングで、`KarteApp` クラスに本クラスをライブラリとして登録します。 - @objc - public class func _krt_load() { - KarteApp.register(library: self) - } - - /// Push通知の送信履歴を取得します。エラー発生時はnilを返します。 - /// - Parameter limit: 最大取得件数を指定します。デフォルトは最新50件を取得します。 - /// - Parameter latestMessageId: この値で指定されたmessageIdより前の履歴を取得します。指定したmessageIdを持つ履歴は戻り値に含まれません。 - public static func fetchMessages(limit: UInt? = nil, latestMessageId: String? = nil) async -> [InboxMessage]? { - let visitorId = KarteApp.visitorId - return await InboxClient.fetchMessages(by: visitorId, limit: limit, latestMessageId: latestMessageId) - } - - /// Push通知を指定して既読状態にします。 - /// - Parameter messageIds: 既読状態にする対象のメッセージIDの配列。 - /// - Returns リクエスト成功時はtrue, エラー発生時はfalseを返します。 - public static func openMessages(messageIds: [String]) async -> Bool { - let visitorId = KarteApp.visitorId - return await InboxClient.openMessages(for: visitorId, messageIds: messageIds) - } -} - -extension Inbox: Library { - public static var name: String { - "inbox" - } - - public static var version: String { - KRTInboxCurrentLibraryVersion() - } - - public static var isPublic: Bool { - true - } - - public static func configure(app: KarteApp) { - shared._apiKey = app.configuration.apiKey - } - - public static func unconfigure(app: KarteApp) {} -} diff --git a/KarteInbox/InboxLoader.m b/KarteInbox/InboxLoader.m deleted file mode 100644 index 303ea3d7..00000000 --- a/KarteInbox/InboxLoader.m +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright 2022 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#import - -#if __has_include("KarteInbox-Swift.h") -#import "KarteInbox-Swift.h" -#else -#import -#endif - -@interface KRTInboxLoader : NSObject - -@end - -@implementation KRTInboxLoader - -+ (void)load -{ - [KRTInbox _krt_load]; -} - -@end diff --git a/KarteInbox/KarteInbox.h b/KarteInbox/KarteInbox.h deleted file mode 100644 index 30e112c0..00000000 --- a/KarteInbox/KarteInbox.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright 2022 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#import - -//! Project version number for KarteInbox. -FOUNDATION_EXPORT double KarteInboxVersionNumber; - -//! Project version string for KarteInbox. -FOUNDATION_EXPORT const unsigned char KarteInboxVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - -FOUNDATION_EXPORT NSString * KRTInboxCurrentLibraryVersion(void); diff --git a/KarteInbox/KarteInbox.m b/KarteInbox/KarteInbox.m deleted file mode 100644 index 9da9e9ff..00000000 --- a/KarteInbox/KarteInbox.m +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright 2022 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#import -#import "KarteInbox.h" - -#define STR_EXPAND(x) #x -#define STR(x) STR_EXPAND(x) - -NSString * KRTInboxCurrentLibraryVersion(void) { - return [NSString stringWithUTF8String:STR(INBOX_VERSION)]; -} diff --git a/KarteInbox/Logger+Tag.swift b/KarteInbox/Logger+Tag.swift deleted file mode 100644 index fb5221ae..00000000 --- a/KarteInbox/Logger+Tag.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright 2022 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import KarteCore - -extension Logger.Tag { - public static let inbox = Logger.Tag("INBOX", version: KRTInboxCurrentLibraryVersion()) -} diff --git a/KarteInbox/Models/InboxMessage.swift b/KarteInbox/Models/InboxMessage.swift deleted file mode 100644 index 6736e26c..00000000 --- a/KarteInbox/Models/InboxMessage.swift +++ /dev/null @@ -1,156 +0,0 @@ -// -// Copyright 2022 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -/// Karte経由で送信したPush通知を表すタイプです。 -public struct InboxMessage: Decodable { - /// 送信された時間を返します。 - public let timestamp: Date - - /// Push通知のタイトルを返します。 - public let title: String - - /// Push通知の本文を返します。 - public let body: String - - /// Push通知に設定された遷移先リンクURLを返します。
- /// 未設定の場合は空文字を返します。 - public let linkUrl: String - - /// Push通知に設定された画像URLを返します。
- /// 未設定の場合は空文字を返します。 - public let attachmentUrl: String - - /// 接客のキャンペーンIDを返します。 - public let campaignId: String - - /// Push通知のユニークなIDを返します。 - public let messageId: String - - /// Push通知の既読状態を返します。 - public let isRead: Bool - - /// Push通知に設定されたカスタムペイロードを返します。 - public var customPayload: [String: Any?] { - _customPayload.value - } - - // swiftlint:disable:next identifier_name - let _customPayload: CustomPayload - - // swiftlint:disable identifier_name - public init( - timestamp: Date, - title: String, - body: String, - linkUrl: String, - attachmentUrl: String, - campaignId: String, - messageId: String, - isRead: Bool, - _customPayload: CustomPayload - ) { - self.timestamp = timestamp - self.title = title - self.body = body - self.linkUrl = linkUrl - self.attachmentUrl = attachmentUrl - self.campaignId = campaignId - self.messageId = messageId - self.isRead = isRead - self._customPayload = _customPayload - } - - enum CodingKeys: String, CodingKey { - case timestamp, title, body, linkUrl, attachmentUrl, campaignId, messageId, isRead - case _customPayload = "customPayload" - } - - /// カスタムペイロードを表すタイプです。 - /// **SDK内部で利用するタイプであり、通常のSDK利用でこちらのタイプを利用することはありません。** - public struct CustomPayload: Decodable { - fileprivate var value: [String: Any?] = [:] - - // swiftlint:disable:next nesting - struct CodingKeys: CodingKey { - var stringValue: String - var intValue: Int? - - init(stringValue: String) { - self.stringValue = stringValue - } - - init?(intValue: Int) { return nil } - } - - public init(from decoder: Decoder) throws { - if let container = try? decoder.container(keyedBy: CodingKeys.self) { - self.value = decode(fromObject: container) - } - } - - private func decode(fromObject container: KeyedDecodingContainer) -> [String: Any?] { - var result: [String: Any?] = [:] - - for key in container.allKeys { - if let val = try? container.decode(Int.self, forKey: key) { - result[key.stringValue] = val - } else if let val = try? container.decode(UInt.self, forKey: key) { - result[key.stringValue] = val - } else if let val = try? container.decode(Double.self, forKey: key) { - result[key.stringValue] = val - } else if let val = try? container.decode(String.self, forKey: key) { - result[key.stringValue] = val - } else if let val = try? container.decode(Bool.self, forKey: key) { - result[key.stringValue] = val - } else if let nestedContainer = try? container.nestedContainer(keyedBy: CodingKeys.self, forKey: key) { - result[key.stringValue] = decode(fromObject: nestedContainer) - } else if var nestedArray = try? container.nestedUnkeyedContainer(forKey: key) { - result[key.stringValue] = decode(fromArray: &nestedArray) - } else if (try? container.decodeNil(forKey: key)) == true { - result.updateValue(nil, forKey: key.stringValue) - } - } - return result - } - - private func decode(fromArray container: inout UnkeyedDecodingContainer) -> [Any?] { - var result: [Any?] = [] - - while !container.isAtEnd { - if let val = try? container.decode(String.self) { - result.append(val) - } else if let value = try? container.decode(Int.self) { - result.append(value) - } else if let val = try? container.decode(UInt.self) { - result.append(val) - } else if let val = try? container.decode(Double.self) { - result.append(val) - } else if let val = try? container.decode(Bool.self) { - result.append(val) - } else if let nestedContainer = try? container.nestedContainer(keyedBy: CodingKeys.self) { - result.append(decode(fromObject: nestedContainer)) - } else if var nestedArray = try? container.nestedUnkeyedContainer() { - result.append(decode(fromArray: &nestedArray)) - } else if (try? container.decodeNil()) == true { - result.append(nil) - } - } - return result - } - } -} diff --git a/KarteTests/KarteInboxTests/IntegrationTests/InboxSpec.swift b/KarteTests/KarteInboxTests/IntegrationTests/InboxSpec.swift deleted file mode 100644 index 887055e2..00000000 --- a/KarteTests/KarteInboxTests/IntegrationTests/InboxSpec.swift +++ /dev/null @@ -1,133 +0,0 @@ -// -// Copyright 2023 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -import XCTest -import Quick -import Nimble -import Mockingjay -@testable import KarteInbox - -final class InboxSpec: XCTestCase { - func test_fetchMessagesShouldBeParsedWithoutError() async throws { - let successResponse = StubBuilder(test: self, resource: .inbox_success).build() - stub(http(.post, uri: "/v2native/inbox/fetchMessages"), successResponse) - guard let res = await Inbox.fetchMessages() else { - XCTFail("Should never be executed") - return - } - - expect(res.count).to(equal(2)) - expect(res[0].title).to(equal("title1")) - expect(res[0].body).to(equal("body1")) - expect(res[0].campaignId).to(equal("dummy_campaignId_1")) - expect(res[0].messageId).to(equal("dummy_messageId_1")) - expect(res[0].timestamp).notTo(beNil()) - expect(res[0].attachmentUrl).to(beEmpty()) - expect(res[0].linkUrl).to(beEmpty()) - expect(res[0].isRead).to(beTrue()) - - expect(res[1].title).to(equal("title2")) - expect(res[1].body).to(equal("body2")) - expect(res[1].campaignId).to(equal("dummy_campaignId_2")) - expect(res[1].messageId).to(equal("dummy_messageId_2")) - expect(res[1].timestamp).notTo(beNil()) - expect(res[1].attachmentUrl).to(beEmpty()) - expect(res[1].linkUrl).to(beEmpty()) - expect(res[1].isRead).to(beFalse()) - } - - func test_customPayloadShouldBeParsedProperly() async throws { - let successResponse = StubBuilder(test: self, resource: .inbox_success).build() - stub(http(.post, uri: "/v2native/inbox/fetchMessages"), successResponse) - guard let res = await Inbox.fetchMessages(), res.count == 2 else { - XCTFail("Should never be executed") - return - } - - let m1 = res[0] - expect(m1.customPayload["keyStr"] as? String).to(equal("Dummy")) - expect(m1.customPayload["keyInt"] as? Int).to(equal(10)) - expect(m1.customPayload["keyDouble"] as? Double).to(equal(1.11)) - expect(m1.customPayload["keyArray"] as? Array).to(equal([1, 2, 3])) - expect(m1.customPayload["keyNull"]).to(beNil()) - - guard let nestedMap = res[0].customPayload["keyMap"] as? Dictionary else { - XCTFail("Should never be executed: nestedMap in customPayload must be parsed: \(m1.customPayload)") - return - } - expect(nestedMap["prop1"] as? String).to(equal("hoge")) - expect(nestedMap["prop2"] as? Int).to(equal(0)) - - let m2 = res[1] - expect(m2.customPayload.count).to(equal(0)) - } - - func test_fetchMessagesShouldReturnNilWith400Errors() async throws { - let badResponse400 = StubBuilder(test: self, resource: .failure_invalid_request).build(status: 400) - let badResponse401 = StubBuilder(test: self, resource: .failure_invalid_request).build(status: 401) - let badResponse403 = StubBuilder(test: self, resource: .failure_invalid_request).build(status: 403) - let badResponse404 = StubBuilder(test: self, resource: .failure_invalid_request).build(status: 404) - - stub(http(.post, uri: "/v2native/inbox/fetchMessages"), badResponse400) - let res1 = await Inbox.fetchMessages() - expect(res1).to(beNil()) - - stub(http(.post, uri: "/v2native/inbox/fetchMessages"), badResponse401) - let res2 = await Inbox.fetchMessages() - expect(res2).to(beNil()) - - stub(http(.post, uri: "/v2native/inbox/fetchMessages"), badResponse403) - let res3 = await Inbox.fetchMessages() - expect(res3).to(beNil()) - - stub(http(.post, uri: "/v2native/inbox/fetchMessages"), badResponse404) - let res4 = await Inbox.fetchMessages() - expect(res4).to(beNil()) - } - - func test_fetchMessagesShouldReturnNilwith500Error() async throws { - let badResponse500 = StubBuilder(test: self, resource: .failure_server_error).build() - stub(http(.post, uri: "/v2native/inbox/fetchMessages"), badResponse500) - let res = await Inbox.fetchMessages() - expect(res).to(beNil()) - } - - func test_fetchMessagesShouldReturnNilWithInvalidData() async { - let badResponse = """ - { - "messages": [ - { "wrong_key": "invalid value" } - ] - } - """.data(using: .utf8)! - stub(http(.post, uri: "/v2native/inbox/fetchMessages"), jsonData(badResponse)) - let res = await Inbox.fetchMessages() - expect(res).to(beNil()) - } - - func test_openMessagesShouldReturnTrueIfResponseIsSuccess() async throws { - let successResponse = StubBuilder(test: self, resource: .inbox_success_empty).build() - stub(http(.post, uri: "/v2native/inbox/openMessages"), successResponse) - let res = await Inbox.openMessages(messageIds: []) - expect(res).to(beTrue()) - } - - func test_openMessagesShouldReturnFalseIfResponseIsError() async throws { - let badResponse = StubBuilder(test: self, resource: .failure_server_error).build() - stub(http(.post, uri: "/v2native/inbox/openMessages"), badResponse) - let res = await Inbox.openMessages(messageIds: []) - expect(res).to(beFalse()) - } -} diff --git a/KarteTests/KarteInboxTests/TestUtil.swift b/KarteTests/KarteInboxTests/TestUtil.swift deleted file mode 100644 index 9b609093..00000000 --- a/KarteTests/KarteInboxTests/TestUtil.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright 2023 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -@testable import KarteInbox - -struct DummyConfig: InboxConfig { - var baseUrl: URL { - URL(string: "Dummy URL")! - } -} diff --git a/KarteTests/KarteInboxTests/UnitTests/CallerSpec.swift b/KarteTests/KarteInboxTests/UnitTests/CallerSpec.swift deleted file mode 100644 index 4b37e6cc..00000000 --- a/KarteTests/KarteInboxTests/UnitTests/CallerSpec.swift +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright 2023 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Quick -import Nimble -import KarteUtilities -@testable import KarteCore -@testable import KarteInbox - -final class CallerSpec: QuickSpec { - @available(iOS 15.0, *) - func testNativeAsyncCaller_shouldReturnNil_withInvalidUserId() async { - let caller = NativeAsyncCaller() - let req = FetchMessagesRequest(visitorId: "Dummy visitorId", config: EvaluationConfig()) - let res = await caller(callee: req) - expect(res).to(beNil()) - } - - @available(iOS 15.0, *) - func testNativeAsyncCaller_shouldReturnNil_withInvalidURL() async { - let caller = NativeAsyncCaller() - let res = await caller(callee: DummyRequest()) - expect(res).to(beNil()) - } - - func testFallbackAsyncCaller_shouldReturnNil_withInvalidUserId() async { - let caller = FallbackAsyncCaller() - let req = FetchMessagesRequest(visitorId: "Dummy visitorId", config: EvaluationConfig()) - let res = await caller(callee: req) - expect(res).to(beNil()) - } - - func testFallbackAsyncCaller_shouldReturnNil_withInvalidURL() async { - let caller = FallbackAsyncCaller() - let res = await caller(callee: DummyRequest()) - expect(res).to(beNil()) - } -} - -private struct DummyRequest: BaseAPIRequest { - typealias Response = String - - var method: HTTPMethod { - .get - } - - var path: String { - "dummy-url" - } - - var config: InboxConfig { - EvaluationConfig() - } -} diff --git a/KarteTests/KarteInboxTests/UnitTests/FetchMessagesRequestSpec.swift b/KarteTests/KarteInboxTests/UnitTests/FetchMessagesRequestSpec.swift deleted file mode 100644 index 5b2780c8..00000000 --- a/KarteTests/KarteInboxTests/UnitTests/FetchMessagesRequestSpec.swift +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright 2023 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Quick -import Nimble -@testable import KarteInbox - -final class FetchMessagesRequestSpec: QuickSpec { - private let visitorId = "Dummy" - private let config = DummyConfig() - - override func spec() { - describe("a request") { - describe("its init") { - context("when initialized with parameters") { - it("has proper URL with ProductionConfig") { - let req = FetchMessagesRequest(visitorId: self.visitorId, config: ProductionConfig()) - expect(req.asURLRequest().url?.absoluteString).to(equal("https://api.karte.io/v2native/inbox/fetchMessages")) - } - - it("has proper URL with EvaluationConfig") { - let req = FetchMessagesRequest(visitorId: self.visitorId, config: EvaluationConfig()) - expect(req.asURLRequest().url?.absoluteString).to(equal("https://api-evaluation.dev-karte.com/v2native/inbox/fetchMessages")) - } - - it("has correspond visitorId in body") { - let req = FetchMessagesRequest(visitorId: self.visitorId, config: self.config) - expect(req.bodyParams?["visitorId"] as? String).to(equal(self.visitorId)) - } - - it("has correspond limit in body") { - let req = FetchMessagesRequest(visitorId: self.visitorId, limit: 1, config: self.config) - expect(req.bodyParams?["limit"] as? UInt).to(equal(1)) - } - - it("has correspond latestMessageId in body") { - let dummy = "Dummy messageId" - let req = FetchMessagesRequest(visitorId: self.visitorId, latestMessageId: dummy, config: self.config) - expect(req.bodyParams?["latestMessageId"] as? String).to(equal(dummy)) - } - } - - context("when initialized without optional parameters") { - it("has nil for optional body parameters") { - let req = FetchMessagesRequest(visitorId: self.visitorId, config: self.config) - let limit = req.bodyParams?["limit"] - let latestMessageId = req.bodyParams?["latestMessageId"] - expect(limit).to(beNil()) - expect(latestMessageId).to(beNil()) - } - } - } - } - } -} diff --git a/KarteTests/KarteInboxTests/UnitTests/OpenMessagesRequestSpec.swift b/KarteTests/KarteInboxTests/UnitTests/OpenMessagesRequestSpec.swift deleted file mode 100644 index 24fe4335..00000000 --- a/KarteTests/KarteInboxTests/UnitTests/OpenMessagesRequestSpec.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright 2023 PLAID, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Quick -import Nimble -@testable import KarteInbox - -final class OpenMessagesRequestSpec: QuickSpec { - private let visitorId = "Dummy" - private let config = DummyConfig() - - override func spec() { - describe("a request") { - describe("its init") { - context("when initialized with parameters") { - it("has proper URL with ProductionConfig") { - let req = OpenMessagesRequest(visitorId: self.visitorId, messageIds: [], config: ProductionConfig()) - expect(req.asURLRequest().url?.absoluteString).to(equal("https://api.karte.io/v2native/inbox/openMessages")) - } - - it("has proper URL with EvaluationConfig") { - let req = OpenMessagesRequest(visitorId: self.visitorId, messageIds: [], config: EvaluationConfig()) - expect(req.asURLRequest().url?.absoluteString).to(equal("https://api-evaluation.dev-karte.com/v2native/inbox/openMessages")) - } - - it("has correspond visitorId in body") { - let req = OpenMessagesRequest(visitorId: self.visitorId, messageIds: [], config: self.config) - expect(req.bodyParams?["visitorId"] as? String).to(equal(self.visitorId)) - } - - it("has correspond messageIds in body") { - let targets = ["aaa", "bbb", "ccc"] - let req = OpenMessagesRequest(visitorId: self.visitorId, messageIds: targets, config: self.config) - expect(req.bodyParams?["messageIds"] as? [String]).to(equal(targets)) - } - } - } - } - } -} diff --git a/KarteTests/Stub/StubResource.swift b/KarteTests/Stub/StubResource.swift index 89783a81..8a5a2460 100644 --- a/KarteTests/Stub/StubResource.swift +++ b/KarteTests/Stub/StubResource.swift @@ -48,6 +48,4 @@ extension StubResource { static var vt2 = StubResource("success_vt_2.json") static var vt_definitions = StubResource("success_vt_definitions.json") static var vt_definitions_with_dynamic_fields = StubResource("success_vt_definitions_with_dynamic_fields.json") - static var inbox_success = StubResource("success_inbox.json") - static var inbox_success_empty = StubResource("success_inbox_empty.json") } diff --git a/KarteTests/Stub/success_inbox.json b/KarteTests/Stub/success_inbox.json deleted file mode 100644 index d6fa1989..00000000 --- a/KarteTests/Stub/success_inbox.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "messages": [ - { - "attachmentUrl": "", - "body": "body1", - "campaignId": "dummy_campaignId_1", - "linkUrl": "", - "messageId": "dummy_messageId_1", - "timestamp": 1674015317, - "title": "title1", - "isRead": true, - "customPayload": { - "keyStr": "Dummy", - "keyInt": 10, - "keyDouble": 1.11, - "keyArray": [1, 2, 3], - "keyMap": { - "prop1": "hoge", - "prop2": 0 - }, - "keyNull": null - } - }, - { - "attachmentUrl": "", - "body": "body2", - "campaignId": "dummy_campaignId_2", - "linkUrl": "", - "messageId": "dummy_messageId_2", - "timestamp": 1672919717, - "title": "title2", - "isRead": false, - "customPayload": {} - } - ] -} diff --git a/KarteTests/Stub/success_inbox_empty.json b/KarteTests/Stub/success_inbox_empty.json deleted file mode 100644 index 33c0c847..00000000 --- a/KarteTests/Stub/success_inbox_empty.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": true -} diff --git a/Package.swift b/Package.swift index acfb070d..90fbbda6 100644 --- a/Package.swift +++ b/Package.swift @@ -25,10 +25,6 @@ let package = Package( name: "KarteVisualTracking", targets: ["KarteVisualTracking", "KarteCore", "KarteUtilities"] ), - .library( - name: "KarteInbox", - targets: ["KarteInbox", "KarteCore", "KarteUtilities"] - ), .library( name: "KarteRemoteNotification", targets: ["KarteRemoteNotification", "KarteCore", "KarteUtilities"] @@ -65,9 +61,6 @@ let package = Package( .binaryTarget( name: "KarteVisualTracking", url: "https://sdk.karte.io/ios/swiftpm/VisualTracking-2.12.0/KarteVisualTracking.xcframework.zip", checksum: "03364a75282667223acd96c4132afd173e12cf6da6f87a98855842d5e8d2c605" ), - .binaryTarget( - name: "KarteInbox", url: "https://sdk.karte.io/ios/swiftpm/Inbox-0.1.0/KarteInbox.xcframework.zip", checksum: "09850b4f66bca44e95e6cd3f15cd42a56137d6b4143108a8ac33b6b49aff3920" - ), .binaryTarget( name: "KarteRemoteNotification", url: "https://sdk.karte.io/ios/swiftpm/RemoteNotification-2.11.0/KarteRemoteNotification.xcframework.zip", checksum: "58bde3ca6ff813de18787b9dbe3b3b4e3ff9ddbe1713fb941b6be6d34a196ef6" ), diff --git a/scripts/bump_version.sh b/scripts/bump_version.sh index f80d065f..fb5bff8a 100644 --- a/scripts/bump_version.sh +++ b/scripts/bump_version.sh @@ -11,7 +11,6 @@ MODULES=( "KarteCrashReporting" "KarteVariables" "KarteVisualTracking" - "KarteInbox" "KarteUtilities" "KarteNotificationServiceExtension" ) diff --git a/scripts/publish.sh b/scripts/publish.sh index 9c0c90c6..79caf8e8 100644 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -PODSPECS=("KarteUtilities.podspec" "KarteCore.podspec" "KarteInAppMessaging.podspec" "KarteRemoteNotification.podspec" "KarteVariables.podspec" "KarteVisualTracking.podspec" "KarteInbox.podspec" "KarteCrashReporting.podspec" "KarteNotificationServiceExtension.podspec") +PODSPECS=("KarteUtilities.podspec" "KarteCore.podspec" "KarteInAppMessaging.podspec" "KarteRemoteNotification.podspec" "KarteVariables.podspec" "KarteVisualTracking.podspec" "KarteCrashReporting.podspec" "KarteNotificationServiceExtension.podspec") ################################################## # Functions (Sub command functions) From fb25c26bdc5f0241fb290dc330dd9cd08ebc871f Mon Sep 17 00:00:00 2001 From: NewBieChan Date: Wed, 4 Dec 2024 13:24:33 +0900 Subject: [PATCH 4/6] Revert "Remove inbox (#474)" (#475) This reverts commit a1ffd9f3428d351f7919ecd2f115296ae66e9bb6. --- .github/ISSUE_TEMPLATE/bug_report.md | 1 + .github/labeler.yml | 2 + .slather.yml | 1 + .swiftlint.yml | 1 + CHANGELOG.md | 4 - Karte.xcodeproj/project.pbxproj | 299 ++++++++++++++++++ KarteInbox.podspec | 35 ++ KarteInbox/API/BaseAPIRequest.swift | 68 ++++ KarteInbox/API/Caller.swift | 102 ++++++ KarteInbox/API/FetchMessagesRequest.swift | 61 ++++ KarteInbox/API/InboxClient.swift | 45 +++ KarteInbox/API/OpenMessagesRequest.swift | 48 +++ KarteInbox/Config.swift | 33 ++ KarteInbox/Inbox.swift | 75 +++++ KarteInbox/InboxLoader.m | 36 +++ KarteInbox/KarteInbox.h | 27 ++ KarteInbox/KarteInbox.m | 25 ++ KarteInbox/Logger+Tag.swift | 22 ++ KarteInbox/Models/InboxMessage.swift | 156 +++++++++ .../IntegrationTests/InboxSpec.swift | 133 ++++++++ KarteTests/KarteInboxTests/TestUtil.swift | 24 ++ .../UnitTests/CallerSpec.swift | 67 ++++ .../UnitTests/FetchMessagesRequestSpec.swift | 68 ++++ .../UnitTests/OpenMessagesRequestSpec.swift | 53 ++++ KarteTests/Stub/StubResource.swift | 2 + KarteTests/Stub/success_inbox.json | 36 +++ KarteTests/Stub/success_inbox_empty.json | 3 + Package.swift | 7 + scripts/bump_version.sh | 1 + scripts/publish.sh | 2 +- 30 files changed, 1432 insertions(+), 5 deletions(-) create mode 100644 KarteInbox.podspec create mode 100644 KarteInbox/API/BaseAPIRequest.swift create mode 100644 KarteInbox/API/Caller.swift create mode 100644 KarteInbox/API/FetchMessagesRequest.swift create mode 100644 KarteInbox/API/InboxClient.swift create mode 100644 KarteInbox/API/OpenMessagesRequest.swift create mode 100644 KarteInbox/Config.swift create mode 100644 KarteInbox/Inbox.swift create mode 100644 KarteInbox/InboxLoader.m create mode 100644 KarteInbox/KarteInbox.h create mode 100644 KarteInbox/KarteInbox.m create mode 100644 KarteInbox/Logger+Tag.swift create mode 100644 KarteInbox/Models/InboxMessage.swift create mode 100644 KarteTests/KarteInboxTests/IntegrationTests/InboxSpec.swift create mode 100644 KarteTests/KarteInboxTests/TestUtil.swift create mode 100644 KarteTests/KarteInboxTests/UnitTests/CallerSpec.swift create mode 100644 KarteTests/KarteInboxTests/UnitTests/FetchMessagesRequestSpec.swift create mode 100644 KarteTests/KarteInboxTests/UnitTests/OpenMessagesRequestSpec.swift create mode 100644 KarteTests/Stub/success_inbox.json create mode 100644 KarteTests/Stub/success_inbox_empty.json diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 701e0f6d..ebd56a24 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -36,6 +36,7 @@ Please fill in as much of the template below as you can. - KarteRemoteNotification x.x.x - KarteVariables x.x.x - KarteVisualTracking x.x.x +- KarteInbox x.x.x - KarteUtilities x.x.x - KarteNotificationServiceExtension x.x.x diff --git a/.github/labeler.yml b/.github/labeler.yml index 451b445d..b9719174 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -12,6 +12,8 @@ - KarteVariables/** 'Module:VT': - KarteVisualTracking/** +'Module:Inbox': + - KarteInbox/** 'Module:Detectors': - KarteDetectors/** 'Module:Utilities': diff --git a/.slather.yml b/.slather.yml index 9ccfcd74..1cd7bf16 100644 --- a/.slather.yml +++ b/.slather.yml @@ -9,6 +9,7 @@ binary_basename: - KarteRemoteNotification - KarteVisualTracking - KarteVariables + - KarteInbox - KarteCrashReporting - KarteUtilities - KarteNotificationServiceExtension diff --git a/.swiftlint.yml b/.swiftlint.yml index d0057f4c..95a763e6 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -121,6 +121,7 @@ included: - KarteInAppMessaging - KarteRemoteNotification - KarteVariables + - KarteInbox - KarteVisualTracking - KarteCrashReporting - KarteNotificationServiceExtension diff --git a/CHANGELOG.md b/CHANGELOG.md index 12f6cc80..8c55d550 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,10 +13,6 @@ # Releases - xxxx.xx.xx -### Inbox -** 🔨CHANGED** -- Inboxモジュール(β版)の公開を停止しました。 - ### Core 2.30.0 ** 🎉 FEATURE** - Native機能呼び出しにATT許諾ダイアログ表示を追加しました。 diff --git a/Karte.xcodeproj/project.pbxproj b/Karte.xcodeproj/project.pbxproj index b5bc02a8..915e1788 100644 --- a/Karte.xcodeproj/project.pbxproj +++ b/Karte.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ buildPhases = ( ); dependencies = ( + AFFED73C2976AE0400189320 /* PBXTargetDependency */, 0CFB1F57243636AD00BC8757 /* PBXTargetDependency */, 0CFB1F55243636A900BC8757 /* PBXTargetDependency */, 0CCB411523D82758000B5AB9 /* PBXTargetDependency */, @@ -423,8 +424,27 @@ 843BC1072AF316ED00D1C0A0 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 843BC1062AF316ED00D1C0A0 /* PrivacyInfo.xcprivacy */; }; 843BC1092AF3173C00D1C0A0 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 843BC1082AF3173C00D1C0A0 /* PrivacyInfo.xcprivacy */; }; 93E00F8E28745FF500116B5B /* IAMProcessPoolSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93E00F8D28745FF500116B5B /* IAMProcessPoolSpec.swift */; }; + AF0A5F1C2954674500209D4E /* KarteInbox.h in Headers */ = {isa = PBXBuildFile; fileRef = AF0A5F192954674500209D4E /* KarteInbox.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AF0A5F2129546A6800209D4E /* Inbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2029546A6800209D4E /* Inbox.swift */; }; + AF0A5F2429546AB400209D4E /* InboxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2329546AB400209D4E /* InboxMessage.swift */; }; + AF0A5F2729546AE300209D4E /* InboxClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2629546AE300209D4E /* InboxClient.swift */; }; + AF0A5F2929546AFC00209D4E /* Caller.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2829546AFC00209D4E /* Caller.swift */; }; + AF0A5F2B29546B3500209D4E /* BaseAPIRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2A29546B3500209D4E /* BaseAPIRequest.swift */; }; + AF0A5F2D29546B5B00209D4E /* FetchMessagesRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2C29546B5B00209D4E /* FetchMessagesRequest.swift */; }; + AF0A5F2F29546BB000209D4E /* Logger+Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F2E29546BB000209D4E /* Logger+Tag.swift */; }; + AF0A5F31295475B300209D4E /* KarteInbox.m in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F30295475B300209D4E /* KarteInbox.m */; }; + AF0A5F352959986F00209D4E /* InboxLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = AF0A5F342959986F00209D4E /* InboxLoader.m */; }; AF38FD9E2C7C7313009C1C20 /* RequestATTCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF38FD9D2C7C7313009C1C20 /* RequestATTCommand.swift */; }; AF38FDA02C7C8108009C1C20 /* RequestATTCommandSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF38FD9F2C7C8108009C1C20 /* RequestATTCommandSpec.swift */; }; + AF49FAA1296ED953005A7575 /* CallerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF49FAA0296ED953005A7575 /* CallerSpec.swift */; }; + AF5EDEB329C1C49000D05825 /* OpenMessagesRequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF5EDEB229C1C49000D05825 /* OpenMessagesRequestSpec.swift */; }; + AF5EDEB529C1C5A600D05825 /* OpenMessagesRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF5EDEB429C1C5A600D05825 /* OpenMessagesRequest.swift */; }; + AF5EDEB929C30CE700D05825 /* success_inbox_empty.json in Resources */ = {isa = PBXBuildFile; fileRef = AF5EDEB829C30A5400D05825 /* success_inbox_empty.json */; }; + AF9677FD29C86659008C80BC /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF9677FC29C86659008C80BC /* Config.swift */; }; + AF9677FF29CAE5FD008C80BC /* TestUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF9677FE29CAE5FD008C80BC /* TestUtil.swift */; }; + AFA6E8142987B03500111497 /* InboxSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA6E8132987B03500111497 /* InboxSpec.swift */; }; + AFA6E8162987CBD400111497 /* success_inbox.json in Resources */ = {isa = PBXBuildFile; fileRef = AFA6E8152987CBD400111497 /* success_inbox.json */; }; + AFCAF2C4299F6809005B4DCC /* FetchMessagesRequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCAF2C3299F6809005B4DCC /* FetchMessagesRequestSpec.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -561,6 +581,27 @@ remoteGlobalIDString = 0C060E972384D76C006AF974; remoteInfo = KarteUtilities; }; + AF49FAA2296EDA60005A7575 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0C6FE20D22F3F41C00F2FD28 /* Project object */; + proxyType = 1; + remoteGlobalIDString = AF0A5F162954674500209D4E; + remoteInfo = KarteInbox; + }; + AFFED73B2976AE0400189320 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0C6FE20D22F3F41C00F2FD28 /* Project object */; + proxyType = 1; + remoteGlobalIDString = AF0A5F162954674500209D4E; + remoteInfo = KarteInbox; + }; + AFFED73D2976AEA600189320 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0C6FE20D22F3F41C00F2FD28 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0C89742F2379040700098CD8; + remoteInfo = KarteCore; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -981,8 +1022,28 @@ 843BC1082AF3173C00D1C0A0 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 92F48DFCD76A0CA4C901907E /* Pods-KarteTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KarteTests.release.xcconfig"; path = "Target Support Files/Pods-KarteTests/Pods-KarteTests.release.xcconfig"; sourceTree = ""; }; 93E00F8D28745FF500116B5B /* IAMProcessPoolSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IAMProcessPoolSpec.swift; sourceTree = ""; }; + AF0A5F172954674500209D4E /* KarteInbox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KarteInbox.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + AF0A5F192954674500209D4E /* KarteInbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KarteInbox.h; sourceTree = ""; }; + AF0A5F2029546A6800209D4E /* Inbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Inbox.swift; sourceTree = ""; }; + AF0A5F2329546AB400209D4E /* InboxMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboxMessage.swift; sourceTree = ""; }; + AF0A5F2629546AE300209D4E /* InboxClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboxClient.swift; sourceTree = ""; }; + AF0A5F2829546AFC00209D4E /* Caller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Caller.swift; sourceTree = ""; }; + AF0A5F2A29546B3500209D4E /* BaseAPIRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseAPIRequest.swift; sourceTree = ""; }; + AF0A5F2C29546B5B00209D4E /* FetchMessagesRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchMessagesRequest.swift; sourceTree = ""; }; + AF0A5F2E29546BB000209D4E /* Logger+Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logger+Tag.swift"; sourceTree = ""; }; + AF0A5F30295475B300209D4E /* KarteInbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KarteInbox.m; sourceTree = ""; }; + AF0A5F342959986F00209D4E /* InboxLoader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InboxLoader.m; sourceTree = ""; }; AF38FD9D2C7C7313009C1C20 /* RequestATTCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestATTCommand.swift; sourceTree = ""; }; AF38FD9F2C7C8108009C1C20 /* RequestATTCommandSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestATTCommandSpec.swift; sourceTree = ""; }; + AF49FAA0296ED953005A7575 /* CallerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallerSpec.swift; sourceTree = ""; }; + AF5EDEB229C1C49000D05825 /* OpenMessagesRequestSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenMessagesRequestSpec.swift; sourceTree = ""; }; + AF5EDEB429C1C5A600D05825 /* OpenMessagesRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenMessagesRequest.swift; sourceTree = ""; }; + AF5EDEB829C30A5400D05825 /* success_inbox_empty.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = success_inbox_empty.json; sourceTree = ""; }; + AF9677FC29C86659008C80BC /* Config.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = ""; }; + AF9677FE29CAE5FD008C80BC /* TestUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUtil.swift; sourceTree = ""; }; + AFA6E8132987B03500111497 /* InboxSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboxSpec.swift; sourceTree = ""; }; + AFA6E8152987CBD400111497 /* success_inbox.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = success_inbox.json; sourceTree = ""; }; + AFCAF2C3299F6809005B4DCC /* FetchMessagesRequestSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchMessagesRequestSpec.swift; sourceTree = ""; }; BFCBE7E59096A32C44932285 /* Pods-KarteTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KarteTests.debug.xcconfig"; path = "Target Support Files/Pods-KarteTests/Pods-KarteTests.debug.xcconfig"; sourceTree = ""; }; BFF77FFF3DF47D9011A20C08 /* Pods-Karte.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Karte.debug.xcconfig"; path = "Target Support Files/Pods-Karte/Pods-Karte.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1053,6 +1114,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + AF0A5F142954674500209D4E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -1435,6 +1503,7 @@ 0C060E992384D76C006AF974 /* KarteUtilities */, 5013526D277AB8E60026E1F9 /* KarteNotificationServiceExtension */, 0CE792E423862C9C00F0D932 /* KarteTests */, + AF0A5F182954674500209D4E /* KarteInbox */, 0C6FE21722F3F41C00F2FD28 /* Products */, 0C6FE2D222F826CA00F2FD28 /* Frameworks */, 707708FD2279E9E9AA8EDDF6 /* Pods */, @@ -1453,6 +1522,7 @@ 0C060E982384D76C006AF974 /* KarteUtilities.framework */, 0CE792E323862C9C00F0D932 /* KarteTests.xctest */, 5013526C277AB8E60026E1F9 /* KarteNotificationServiceExtension.framework */, + AF0A5F172954674500209D4E /* KarteInbox.framework */, ); name = Products; sourceTree = ""; @@ -1956,6 +2026,8 @@ 0CC648C5238D5559009EB5DF /* success_vt_2.json */, 363F260D2582AE60007E6E4B /* success_vt_definitions.json */, 6857834527478B7000A1AE58 /* success_vt_definitions_with_dynamic_fields.json */, + AFA6E8152987CBD400111497 /* success_inbox.json */, + AF5EDEB829C30A5400D05825 /* success_inbox_empty.json */, ); path = Stub; sourceTree = ""; @@ -2069,6 +2141,7 @@ 0CA52D572387B96D00A575BC /* KarteRemoteNotification */, 0CE7933B2386913B00F0D932 /* KarteVariablesTests */, 0CE7933A2386913000F0D932 /* KarteVisualTrackingTests */, + AF49FA9E296ED81D005A7575 /* KarteInboxTests */, 0CE7932E23865C8B00F0D932 /* KarteUtilitiesTests */, 0CC648AE238A153F009EB5DF /* Stub */, 0CE79308238653AD00F0D932 /* SpecConfiguration.swift */, @@ -2352,6 +2425,69 @@ path = Pods; sourceTree = ""; }; + AF0A5F182954674500209D4E /* KarteInbox */ = { + isa = PBXGroup; + children = ( + AF0A5F2529546AD800209D4E /* API */, + AF0A5F2229546AA200209D4E /* Models */, + AF0A5F342959986F00209D4E /* InboxLoader.m */, + AF0A5F192954674500209D4E /* KarteInbox.h */, + AF0A5F30295475B300209D4E /* KarteInbox.m */, + AF0A5F2029546A6800209D4E /* Inbox.swift */, + AF0A5F2E29546BB000209D4E /* Logger+Tag.swift */, + AF9677FC29C86659008C80BC /* Config.swift */, + ); + path = KarteInbox; + sourceTree = ""; + }; + AF0A5F2229546AA200209D4E /* Models */ = { + isa = PBXGroup; + children = ( + AF0A5F2329546AB400209D4E /* InboxMessage.swift */, + ); + path = Models; + sourceTree = ""; + }; + AF0A5F2529546AD800209D4E /* API */ = { + isa = PBXGroup; + children = ( + AF0A5F2629546AE300209D4E /* InboxClient.swift */, + AF0A5F2829546AFC00209D4E /* Caller.swift */, + AF0A5F2A29546B3500209D4E /* BaseAPIRequest.swift */, + AF0A5F2C29546B5B00209D4E /* FetchMessagesRequest.swift */, + AF5EDEB429C1C5A600D05825 /* OpenMessagesRequest.swift */, + ); + path = API; + sourceTree = ""; + }; + AF49FA9E296ED81D005A7575 /* KarteInboxTests */ = { + isa = PBXGroup; + children = ( + AFA6E8122987AFFF00111497 /* IntegrationTests */, + AF49FA9F296ED85A005A7575 /* UnitTests */, + AF9677FE29CAE5FD008C80BC /* TestUtil.swift */, + ); + path = KarteInboxTests; + sourceTree = ""; + }; + AF49FA9F296ED85A005A7575 /* UnitTests */ = { + isa = PBXGroup; + children = ( + AF49FAA0296ED953005A7575 /* CallerSpec.swift */, + AFCAF2C3299F6809005B4DCC /* FetchMessagesRequestSpec.swift */, + AF5EDEB229C1C49000D05825 /* OpenMessagesRequestSpec.swift */, + ); + path = UnitTests; + sourceTree = ""; + }; + AFA6E8122987AFFF00111497 /* IntegrationTests */ = { + isa = PBXGroup; + children = ( + AFA6E8132987B03500111497 /* InboxSpec.swift */, + ); + path = IntegrationTests; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -2425,6 +2561,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + AF0A5F122954674500209D4E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + AF0A5F1C2954674500209D4E /* KarteInbox.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -2575,6 +2719,7 @@ buildRules = ( ); dependencies = ( + AF49FAA3296EDA60005A7575 /* PBXTargetDependency */, 0CE7933923867ACF00F0D932 /* PBXTargetDependency */, 0CA52D4E2387A9D200A575BC /* PBXTargetDependency */, 0CA52D502387A9D200A575BC /* PBXTargetDependency */, @@ -2605,6 +2750,25 @@ productReference = 5013526C277AB8E60026E1F9 /* KarteNotificationServiceExtension.framework */; productType = "com.apple.product-type.framework"; }; + AF0A5F162954674500209D4E /* KarteInbox */ = { + isa = PBXNativeTarget; + buildConfigurationList = AF0A5F1F2954674500209D4E /* Build configuration list for PBXNativeTarget "KarteInbox" */; + buildPhases = ( + AF0A5F122954674500209D4E /* Headers */, + AF0A5F132954674500209D4E /* Sources */, + AF0A5F142954674500209D4E /* Frameworks */, + AF0A5F152954674500209D4E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + AFFED73E2976AEA600189320 /* PBXTargetDependency */, + ); + name = KarteInbox; + productName = KarteInbox; + productReference = AF0A5F172954674500209D4E /* KarteInbox.framework */; + productType = "com.apple.product-type.framework"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -2656,6 +2820,10 @@ 5013526B277AB8E60026E1F9 = { CreatedOnToolsVersion = 13.2.1; }; + AF0A5F162954674500209D4E = { + CreatedOnToolsVersion = 14.2; + LastSwiftMigration = 1420; + }; }; }; buildConfigurationList = 0C6FE21022F3F41C00F2FD28 /* Build configuration list for PBXProject "Karte" */; @@ -2676,6 +2844,7 @@ 0C897449237904F700098CD8 /* KarteVariables */, 0C8974562379050600098CD8 /* KarteVisualTracking */, 0C897689237BBA5300098CD8 /* KarteRemoteNotification */, + AF0A5F162954674500209D4E /* KarteInbox */, 0C2B3C6B2382684C008A2708 /* KarteCrashReporting */, 0C060E972384D76C006AF974 /* KarteUtilities */, 5013526B277AB8E60026E1F9 /* KarteNotificationServiceExtension */, @@ -2751,6 +2920,8 @@ 0CF44AFB242E451000CA7F3A /* success_variables_3.json in Resources */, 363F26172582B028007E6E4B /* success_vt_definitions.json in Resources */, 1EE766B7297546440040278E /* Karte-custom-Info.plist in Resources */, + AFA6E8162987CBD400111497 /* success_inbox.json in Resources */, + AF5EDEB929C30CE700D05825 /* success_inbox_empty.json in Resources */, 6857834627478B7000A1AE58 /* success_vt_definitions_with_dynamic_fields.json in Resources */, 36EFDED5271BF26700C60666 /* failure_invalid_request.json in Resources */, 36EFDEDF271BF26B00C60666 /* failure_server_error.json in Resources */, @@ -2768,6 +2939,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + AF0A5F152954674500209D4E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -3178,7 +3356,9 @@ 6837631B252FDAE200E690CE /* SelectorDetectorMock.swift in Sources */, 0C6619CE299DBF08006FF9E1 /* TrackMessageOpenSpec.swift in Sources */, 0CE79311238653AD00F0D932 /* StubActionModule.swift in Sources */, + AF9677FF29CAE5FD008C80BC /* TestUtil.swift in Sources */, 0CD4847A2508716F007F52E1 /* MeasurementSpec.swift in Sources */, + AFA6E8142987B03500111497 /* InboxSpec.swift in Sources */, 0C83931C240838320014C2BF /* DefinitionMatchSpec.swift in Sources */, 0C839309240822A40014C2BF /* RenewVisitorIdEventSpec.swift in Sources */, 0C839317240838050014C2BF /* LogicalOperatorSpec.swift in Sources */, @@ -3199,6 +3379,7 @@ 0CCFA7BB24A5D8D500E0F184 /* NotificationSettingsProviderMock.swift in Sources */, 0C839313240837D40014C2BF /* VariableSpec.swift in Sources */, 0C83931B240838320014C2BF /* DefinitionLoadSpec.swift in Sources */, + AF5EDEB329C1C49000D05825 /* OpenMessagesRequestSpec.swift in Sources */, 93E00F8E28745FF500116B5B /* IAMProcessPoolSpec.swift in Sources */, 0C8392F82407CEC50014C2BF /* VersionServiceSpec.swift in Sources */, 0C839315240838050014C2BF /* ActionSpec.swift in Sources */, @@ -3215,6 +3396,7 @@ 0C520BD02990C50100480B77 /* JSONValueSpec.swift in Sources */, 0C69D3E724EB859900D75893 /* CommandBundlerSpec.swift in Sources */, 0C8392FF240822A40014C2BF /* BackgroundEventSpec.swift in Sources */, + AFCAF2C4299F6809005B4DCC /* FetchMessagesRequestSpec.swift in Sources */, 0C83930F2408294D0014C2BF /* TrackCommonSpec.swift in Sources */, 0C839314240837E70014C2BF /* VariablesSpec.swift in Sources */, 0C839303240822A40014C2BF /* ViewEventSpec.swift in Sources */, @@ -3225,6 +3407,7 @@ 0C83930B240824110014C2BF /* FindMyselfSpec.swift in Sources */, 36404EBA247D5EB400F35ECB /* DeepLinkEventSpec.swift in Sources */, 0C8392FB240810920014C2BF /* UserSyncParameterSpec.swift in Sources */, + AF49FAA1296ED953005A7575 /* CallerSpec.swift in Sources */, 0C0822FF24EA6C2E0038EBDA /* CommandBundlerApplicationStateProviderMock.swift in Sources */, 36EFDE972719738500C60666 /* CircuitBreakerSpec.swift in Sources */, 0CDBACCF23A8719300CEB853 /* Assertions.swift in Sources */, @@ -3264,6 +3447,24 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + AF0A5F132954674500209D4E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AF0A5F352959986F00209D4E /* InboxLoader.m in Sources */, + AF0A5F2D29546B5B00209D4E /* FetchMessagesRequest.swift in Sources */, + AF0A5F2B29546B3500209D4E /* BaseAPIRequest.swift in Sources */, + AF0A5F2429546AB400209D4E /* InboxMessage.swift in Sources */, + AF9677FD29C86659008C80BC /* Config.swift in Sources */, + AF0A5F2F29546BB000209D4E /* Logger+Tag.swift in Sources */, + AF0A5F2129546A6800209D4E /* Inbox.swift in Sources */, + AF0A5F2929546AFC00209D4E /* Caller.swift in Sources */, + AF0A5F31295475B300209D4E /* KarteInbox.m in Sources */, + AF0A5F2729546AE300209D4E /* InboxClient.swift in Sources */, + AF5EDEB529C1C5A600D05825 /* OpenMessagesRequest.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -3362,6 +3563,21 @@ target = 0C060E972384D76C006AF974 /* KarteUtilities */; targetProxy = 0CFB1F56243636AD00BC8757 /* PBXContainerItemProxy */; }; + AF49FAA3296EDA60005A7575 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = AF0A5F162954674500209D4E /* KarteInbox */; + targetProxy = AF49FAA2296EDA60005A7575 /* PBXContainerItemProxy */; + }; + AFFED73C2976AE0400189320 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = AF0A5F162954674500209D4E /* KarteInbox */; + targetProxy = AFFED73B2976AE0400189320 /* PBXContainerItemProxy */; + }; + AFFED73E2976AEA600189320 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0C89742F2379040700098CD8 /* KarteCore */; + targetProxy = AFFED73D2976AEA600189320 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -4097,6 +4313,80 @@ }; name = Release; }; + AF0A5F1D2954674500209D4E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "INBOX_VERSION=$(MARKETING_VERSION)", + ); + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 PLAID, inc. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 0.1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.karte.KarteInbox; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + AF0A5F1E2954674500209D4E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = "INBOX_VERSION=$(MARKETING_VERSION)"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 PLAID, inc. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 0.1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.karte.KarteInbox; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -4208,6 +4498,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + AF0A5F1F2954674500209D4E /* Build configuration list for PBXNativeTarget "KarteInbox" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AF0A5F1D2954674500209D4E /* Debug */, + AF0A5F1E2954674500209D4E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 0C6FE20D22F3F41C00F2FD28 /* Project object */; diff --git a/KarteInbox.podspec b/KarteInbox.podspec new file mode 100644 index 00000000..665d486d --- /dev/null +++ b/KarteInbox.podspec @@ -0,0 +1,35 @@ +# +# Be sure to run `pod lib lint KarteTracker.podspec' to ensure this is a +# valid spec before submitting. +# +# Any lines starting with a # are optional, but their use is encouraged +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# + +Pod::Spec.new do |s| + s.name = 'KarteInbox' + s.version = '0.1.0' + s.summary = 'KARTE Inbox SDK' + s.homepage = 'https://karte.io' + s.author = { 'PLAID' => 'dev.share@plaid.co.jp' } + s.documentation_url = 'https://developers.karte.io/docs/ios-sdk' + s.license = { :type => 'Apache', :file => 'LICENSE' } + + s.cocoapods_version = '>= 1.7.0' + s.swift_versions = [5.2] + s.static_framework = true + + s.platform = :ios + s.ios.deployment_target = '13.0' + + s.source = { :git => 'https://github.com/plaidev/karte-ios-sdk.git', :tag => "Inbox-#{s.version}" } + s.source_files = 'KarteInbox/**/*.{swift,h,m}' + + s.requires_arc = true + s.pod_target_xcconfig = { + 'GCC_PREPROCESSOR_DEFINITIONS' => 'INBOX_VERSION=' + s.version.to_s + } + + s.dependency 'KarteCore', '~> 2.22' + s.dependency 'KarteUtilities', '~> 3.5' +end diff --git a/KarteInbox/API/BaseAPIRequest.swift b/KarteInbox/API/BaseAPIRequest.swift new file mode 100644 index 00000000..2333fda8 --- /dev/null +++ b/KarteInbox/API/BaseAPIRequest.swift @@ -0,0 +1,68 @@ +// +// Copyright 2022 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import KarteUtilities + +protocol BaseAPIRequest { + associatedtype Response where Response: Decodable + + var apiKey: String { get } + var config: InboxConfig { get } + var version: String { get } + var method: HTTPMethod { get } + var path: String { get } + var headers: [String: String] { get } + var queryItems: [URLQueryItem]? { get } + var bodyParams: [String: Any]? { get } +} + +extension BaseAPIRequest { + var apiKey: String { + Inbox.currentApiKey + } + + var version: String { + "/v2native" + } + + var headers: [String: String] { + [ + "Content-Type": "application/json; charset=utf-8", + "X-KARTE-Api-Key": apiKey + ] + } + + var queryItems: [URLQueryItem]? { + nil + } + + var bodyParams: [String: Any]? { + nil + } + + func asURLRequest() -> URLRequest { + var urlComponents = URLComponents(string: "\(config.baseUrl.absoluteString)\(version)/\(path)")! + urlComponents.queryItems = queryItems + var req = URLRequest(url: urlComponents.url!) + req.allHTTPHeaderFields = headers + req.httpMethod = method.rawValue + if let params = bodyParams { + req.httpBody = try? JSONSerialization.data(withJSONObject: params, options: []) + } + return req + } +} diff --git a/KarteInbox/API/Caller.swift b/KarteInbox/API/Caller.swift new file mode 100644 index 00000000..4b569076 --- /dev/null +++ b/KarteInbox/API/Caller.swift @@ -0,0 +1,102 @@ +// +// Copyright 2022 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import KarteCore +import KarteUtilities + +protocol Caller { + func callAsFunction(callee request: Request) async -> Request.Response? + func intercept(data: Data, response: URLResponse) -> Data? + func parseError(_ response: URLResponse, _ data: Data) -> (String, String) +} + +extension Caller { + func intercept(data: Data, response: URLResponse) -> Data? { + guard let status = (response as? HTTPURLResponse)?.statusCode else { + Logger.error(tag: .inbox, message: "Invalid response is returned") + return nil + } + + switch status { + case 200..<300: + Logger.verbose(tag: .inbox, message: "\(status): The server returned a normal response") + case 400..<500: + // swiftlint:disable:next no_fallthrough_only + fallthrough + default: + let (path, error) = parseError(response, data) + Logger.error(tag: .inbox, message: "\(status): The server returned an error on \(path): \(error)") + return nil + } + return data + } + + func parseError(_ response: URLResponse, _ data: Data) -> (String, String) { + let path = (response as? HTTPURLResponse)?.url?.pathComponents.joined(separator: "/") + return (String(describing: path), String(data: data, encoding: .utf8) ?? "") + } +} + +@available(iOS 15.0, *) +struct NativeAsyncCaller: Caller { + func callAsFunction(callee request: Request) async -> Request.Response? { + do { + let req = request.asURLRequest() + let (data, response) = try await URLSession.shared.data(for: req) + guard let res = intercept(data: data, response: response) else { + return nil + } + let decoder = createJSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + return try decoder.decode(Request.Response.self, from: res) + } catch { + Logger.error(tag: .inbox, message: "At line \(#line) of \(#file): \(error)") + return nil + } + } +} + +struct FallbackAsyncCaller: Caller { + func callAsFunction(callee request: Request) async -> Request.Response? { + let req = request.asURLRequest() + return await withCheckedContinuation { continuation in + URLSession.shared.dataTask(with: req) { (data, response, error) in + do { + guard let data = data, let response = response else { + if let status = (response as? HTTPURLResponse)?.statusCode { + throw ResponseError.unacceptableStatusCode(status) + } else { + throw ResponseError.nonHTTPURLResponse(response) + } + } + + guard let res = intercept(data: data, response: response) else { + continuation.resume(returning: nil) + return + } + let decoder = createJSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + let decoded = try decoder.decode(Request.Response.self, from: res) + continuation.resume(returning: decoded) + } catch { + Logger.error(tag: .inbox, message: error.localizedDescription) + continuation.resume(returning: nil) + } + }.resume() + } + } +} diff --git a/KarteInbox/API/FetchMessagesRequest.swift b/KarteInbox/API/FetchMessagesRequest.swift new file mode 100644 index 00000000..e6fa222a --- /dev/null +++ b/KarteInbox/API/FetchMessagesRequest.swift @@ -0,0 +1,61 @@ +// +// Copyright 2022 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import KarteUtilities + +struct FetchMessagesRequest: BaseAPIRequest { + typealias Response = FetchMessagesResponse + + let visitorId: String + let limit: UInt? + let latestMessageId: String? + let config: InboxConfig + + init(visitorId: String, limit: UInt? = nil, latestMessageId: String? = nil, config: InboxConfig) { + self.visitorId = visitorId + self.limit = limit + self.latestMessageId = latestMessageId + self.config = config + } + + var method: HTTPMethod { + .post + } + + var path: String { + "inbox/fetchMessages" + } + + var bodyParams: [String: Any]? { + var body: [String: Any] = [ + "visitorId": visitorId, + "appType": "native_app", + "os": "ios" + ] + if let limit = limit { + body["limit"] = limit + } + if let latest = latestMessageId { + body["latestMessageId"] = latest + } + return body + } +} + +struct FetchMessagesResponse: Decodable { + let messages: [InboxMessage] +} diff --git a/KarteInbox/API/InboxClient.swift b/KarteInbox/API/InboxClient.swift new file mode 100644 index 00000000..7c8d611c --- /dev/null +++ b/KarteInbox/API/InboxClient.swift @@ -0,0 +1,45 @@ +// +// Copyright 2022 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +struct InboxClient { + private static let config = ProductionConfig() + + private static func call(_ request: Request) async -> Request.Response? { + if #available(iOS 15.0, *) { + let caller = NativeAsyncCaller() + return await caller(callee: request) + } else { + let caller = FallbackAsyncCaller() + return await caller(callee: request) + } + } +} + +extension InboxClient { + static func fetchMessages(by visitorId: String, limit: UInt? = nil, latestMessageId: String? = nil) async -> [InboxMessage]? { + let req = FetchMessagesRequest(visitorId: visitorId, limit: limit, latestMessageId: latestMessageId, config: config) + let res = await call(req) + return res?.messages + } + + static func openMessages(for visitorId: String, messageIds: [String]) async -> Bool { + let req = OpenMessagesRequest(visitorId: visitorId, messageIds: messageIds, config: config) + let res = await call(req) + return res?.success ?? false + } +} diff --git a/KarteInbox/API/OpenMessagesRequest.swift b/KarteInbox/API/OpenMessagesRequest.swift new file mode 100644 index 00000000..f331e643 --- /dev/null +++ b/KarteInbox/API/OpenMessagesRequest.swift @@ -0,0 +1,48 @@ +// +// Copyright 2023 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import KarteUtilities + +struct OpenMessagesRequest: BaseAPIRequest { + typealias Response = OpenMessagesResponse + + let visitorId: String + let messageIds: [String] + let config: InboxConfig + + var method: HTTPMethod { + .post + } + + var path: String { + "inbox/openMessages" + } + + var bodyParams: [String: Any]? { + let body: [String: Any] = [ + "visitorId": visitorId, + "appType": "native_app", + "os": "ios", + "messageIds": messageIds + ] + return body + } +} + +struct OpenMessagesResponse: Decodable { + let success: Bool +} diff --git a/KarteInbox/Config.swift b/KarteInbox/Config.swift new file mode 100644 index 00000000..d5cb4a0c --- /dev/null +++ b/KarteInbox/Config.swift @@ -0,0 +1,33 @@ +// +// Copyright 2023 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +protocol InboxConfig { + var baseUrl: URL { get } +} + +struct ProductionConfig: InboxConfig { + var baseUrl: URL { + URL(string: "https://api.karte.io")! + } +} + +struct EvaluationConfig: InboxConfig { + var baseUrl: URL { + URL(string: "https://api-evaluation.dev-karte.com")! + } +} diff --git a/KarteInbox/Inbox.swift b/KarteInbox/Inbox.swift new file mode 100644 index 00000000..8e45bee1 --- /dev/null +++ b/KarteInbox/Inbox.swift @@ -0,0 +1,75 @@ +// +// Copyright 2022 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import KarteCore + +/// Karteから送信したPush通知の履歴を取得するクラスです。 +@objc(KRTInbox) +public class Inbox: NSObject { + static let shared = Inbox() + + private var _apiKey: String? + + public static var currentApiKey: String { + shared._apiKey ?? "" + } + + override private init() {} + + /// ローダークラスが Objective-Cランライムに追加されたタイミングで呼び出されるメソッドです。 + /// 本メソッドが呼び出されたタイミングで、`KarteApp` クラスに本クラスをライブラリとして登録します。 + @objc + public class func _krt_load() { + KarteApp.register(library: self) + } + + /// Push通知の送信履歴を取得します。エラー発生時はnilを返します。 + /// - Parameter limit: 最大取得件数を指定します。デフォルトは最新50件を取得します。 + /// - Parameter latestMessageId: この値で指定されたmessageIdより前の履歴を取得します。指定したmessageIdを持つ履歴は戻り値に含まれません。 + public static func fetchMessages(limit: UInt? = nil, latestMessageId: String? = nil) async -> [InboxMessage]? { + let visitorId = KarteApp.visitorId + return await InboxClient.fetchMessages(by: visitorId, limit: limit, latestMessageId: latestMessageId) + } + + /// Push通知を指定して既読状態にします。 + /// - Parameter messageIds: 既読状態にする対象のメッセージIDの配列。 + /// - Returns リクエスト成功時はtrue, エラー発生時はfalseを返します。 + public static func openMessages(messageIds: [String]) async -> Bool { + let visitorId = KarteApp.visitorId + return await InboxClient.openMessages(for: visitorId, messageIds: messageIds) + } +} + +extension Inbox: Library { + public static var name: String { + "inbox" + } + + public static var version: String { + KRTInboxCurrentLibraryVersion() + } + + public static var isPublic: Bool { + true + } + + public static func configure(app: KarteApp) { + shared._apiKey = app.configuration.apiKey + } + + public static func unconfigure(app: KarteApp) {} +} diff --git a/KarteInbox/InboxLoader.m b/KarteInbox/InboxLoader.m new file mode 100644 index 00000000..303ea3d7 --- /dev/null +++ b/KarteInbox/InboxLoader.m @@ -0,0 +1,36 @@ +// +// Copyright 2022 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#if __has_include("KarteInbox-Swift.h") +#import "KarteInbox-Swift.h" +#else +#import +#endif + +@interface KRTInboxLoader : NSObject + +@end + +@implementation KRTInboxLoader + ++ (void)load +{ + [KRTInbox _krt_load]; +} + +@end diff --git a/KarteInbox/KarteInbox.h b/KarteInbox/KarteInbox.h new file mode 100644 index 00000000..30e112c0 --- /dev/null +++ b/KarteInbox/KarteInbox.h @@ -0,0 +1,27 @@ +// +// Copyright 2022 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +//! Project version number for KarteInbox. +FOUNDATION_EXPORT double KarteInboxVersionNumber; + +//! Project version string for KarteInbox. +FOUNDATION_EXPORT const unsigned char KarteInboxVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + +FOUNDATION_EXPORT NSString * KRTInboxCurrentLibraryVersion(void); diff --git a/KarteInbox/KarteInbox.m b/KarteInbox/KarteInbox.m new file mode 100644 index 00000000..9da9e9ff --- /dev/null +++ b/KarteInbox/KarteInbox.m @@ -0,0 +1,25 @@ +// +// Copyright 2022 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import +#import "KarteInbox.h" + +#define STR_EXPAND(x) #x +#define STR(x) STR_EXPAND(x) + +NSString * KRTInboxCurrentLibraryVersion(void) { + return [NSString stringWithUTF8String:STR(INBOX_VERSION)]; +} diff --git a/KarteInbox/Logger+Tag.swift b/KarteInbox/Logger+Tag.swift new file mode 100644 index 00000000..fb5221ae --- /dev/null +++ b/KarteInbox/Logger+Tag.swift @@ -0,0 +1,22 @@ +// +// Copyright 2022 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import KarteCore + +extension Logger.Tag { + public static let inbox = Logger.Tag("INBOX", version: KRTInboxCurrentLibraryVersion()) +} diff --git a/KarteInbox/Models/InboxMessage.swift b/KarteInbox/Models/InboxMessage.swift new file mode 100644 index 00000000..6736e26c --- /dev/null +++ b/KarteInbox/Models/InboxMessage.swift @@ -0,0 +1,156 @@ +// +// Copyright 2022 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +/// Karte経由で送信したPush通知を表すタイプです。 +public struct InboxMessage: Decodable { + /// 送信された時間を返します。 + public let timestamp: Date + + /// Push通知のタイトルを返します。 + public let title: String + + /// Push通知の本文を返します。 + public let body: String + + /// Push通知に設定された遷移先リンクURLを返します。
+ /// 未設定の場合は空文字を返します。 + public let linkUrl: String + + /// Push通知に設定された画像URLを返します。
+ /// 未設定の場合は空文字を返します。 + public let attachmentUrl: String + + /// 接客のキャンペーンIDを返します。 + public let campaignId: String + + /// Push通知のユニークなIDを返します。 + public let messageId: String + + /// Push通知の既読状態を返します。 + public let isRead: Bool + + /// Push通知に設定されたカスタムペイロードを返します。 + public var customPayload: [String: Any?] { + _customPayload.value + } + + // swiftlint:disable:next identifier_name + let _customPayload: CustomPayload + + // swiftlint:disable identifier_name + public init( + timestamp: Date, + title: String, + body: String, + linkUrl: String, + attachmentUrl: String, + campaignId: String, + messageId: String, + isRead: Bool, + _customPayload: CustomPayload + ) { + self.timestamp = timestamp + self.title = title + self.body = body + self.linkUrl = linkUrl + self.attachmentUrl = attachmentUrl + self.campaignId = campaignId + self.messageId = messageId + self.isRead = isRead + self._customPayload = _customPayload + } + + enum CodingKeys: String, CodingKey { + case timestamp, title, body, linkUrl, attachmentUrl, campaignId, messageId, isRead + case _customPayload = "customPayload" + } + + /// カスタムペイロードを表すタイプです。 + /// **SDK内部で利用するタイプであり、通常のSDK利用でこちらのタイプを利用することはありません。** + public struct CustomPayload: Decodable { + fileprivate var value: [String: Any?] = [:] + + // swiftlint:disable:next nesting + struct CodingKeys: CodingKey { + var stringValue: String + var intValue: Int? + + init(stringValue: String) { + self.stringValue = stringValue + } + + init?(intValue: Int) { return nil } + } + + public init(from decoder: Decoder) throws { + if let container = try? decoder.container(keyedBy: CodingKeys.self) { + self.value = decode(fromObject: container) + } + } + + private func decode(fromObject container: KeyedDecodingContainer) -> [String: Any?] { + var result: [String: Any?] = [:] + + for key in container.allKeys { + if let val = try? container.decode(Int.self, forKey: key) { + result[key.stringValue] = val + } else if let val = try? container.decode(UInt.self, forKey: key) { + result[key.stringValue] = val + } else if let val = try? container.decode(Double.self, forKey: key) { + result[key.stringValue] = val + } else if let val = try? container.decode(String.self, forKey: key) { + result[key.stringValue] = val + } else if let val = try? container.decode(Bool.self, forKey: key) { + result[key.stringValue] = val + } else if let nestedContainer = try? container.nestedContainer(keyedBy: CodingKeys.self, forKey: key) { + result[key.stringValue] = decode(fromObject: nestedContainer) + } else if var nestedArray = try? container.nestedUnkeyedContainer(forKey: key) { + result[key.stringValue] = decode(fromArray: &nestedArray) + } else if (try? container.decodeNil(forKey: key)) == true { + result.updateValue(nil, forKey: key.stringValue) + } + } + return result + } + + private func decode(fromArray container: inout UnkeyedDecodingContainer) -> [Any?] { + var result: [Any?] = [] + + while !container.isAtEnd { + if let val = try? container.decode(String.self) { + result.append(val) + } else if let value = try? container.decode(Int.self) { + result.append(value) + } else if let val = try? container.decode(UInt.self) { + result.append(val) + } else if let val = try? container.decode(Double.self) { + result.append(val) + } else if let val = try? container.decode(Bool.self) { + result.append(val) + } else if let nestedContainer = try? container.nestedContainer(keyedBy: CodingKeys.self) { + result.append(decode(fromObject: nestedContainer)) + } else if var nestedArray = try? container.nestedUnkeyedContainer() { + result.append(decode(fromArray: &nestedArray)) + } else if (try? container.decodeNil()) == true { + result.append(nil) + } + } + return result + } + } +} diff --git a/KarteTests/KarteInboxTests/IntegrationTests/InboxSpec.swift b/KarteTests/KarteInboxTests/IntegrationTests/InboxSpec.swift new file mode 100644 index 00000000..887055e2 --- /dev/null +++ b/KarteTests/KarteInboxTests/IntegrationTests/InboxSpec.swift @@ -0,0 +1,133 @@ +// +// Copyright 2023 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +import XCTest +import Quick +import Nimble +import Mockingjay +@testable import KarteInbox + +final class InboxSpec: XCTestCase { + func test_fetchMessagesShouldBeParsedWithoutError() async throws { + let successResponse = StubBuilder(test: self, resource: .inbox_success).build() + stub(http(.post, uri: "/v2native/inbox/fetchMessages"), successResponse) + guard let res = await Inbox.fetchMessages() else { + XCTFail("Should never be executed") + return + } + + expect(res.count).to(equal(2)) + expect(res[0].title).to(equal("title1")) + expect(res[0].body).to(equal("body1")) + expect(res[0].campaignId).to(equal("dummy_campaignId_1")) + expect(res[0].messageId).to(equal("dummy_messageId_1")) + expect(res[0].timestamp).notTo(beNil()) + expect(res[0].attachmentUrl).to(beEmpty()) + expect(res[0].linkUrl).to(beEmpty()) + expect(res[0].isRead).to(beTrue()) + + expect(res[1].title).to(equal("title2")) + expect(res[1].body).to(equal("body2")) + expect(res[1].campaignId).to(equal("dummy_campaignId_2")) + expect(res[1].messageId).to(equal("dummy_messageId_2")) + expect(res[1].timestamp).notTo(beNil()) + expect(res[1].attachmentUrl).to(beEmpty()) + expect(res[1].linkUrl).to(beEmpty()) + expect(res[1].isRead).to(beFalse()) + } + + func test_customPayloadShouldBeParsedProperly() async throws { + let successResponse = StubBuilder(test: self, resource: .inbox_success).build() + stub(http(.post, uri: "/v2native/inbox/fetchMessages"), successResponse) + guard let res = await Inbox.fetchMessages(), res.count == 2 else { + XCTFail("Should never be executed") + return + } + + let m1 = res[0] + expect(m1.customPayload["keyStr"] as? String).to(equal("Dummy")) + expect(m1.customPayload["keyInt"] as? Int).to(equal(10)) + expect(m1.customPayload["keyDouble"] as? Double).to(equal(1.11)) + expect(m1.customPayload["keyArray"] as? Array).to(equal([1, 2, 3])) + expect(m1.customPayload["keyNull"]).to(beNil()) + + guard let nestedMap = res[0].customPayload["keyMap"] as? Dictionary else { + XCTFail("Should never be executed: nestedMap in customPayload must be parsed: \(m1.customPayload)") + return + } + expect(nestedMap["prop1"] as? String).to(equal("hoge")) + expect(nestedMap["prop2"] as? Int).to(equal(0)) + + let m2 = res[1] + expect(m2.customPayload.count).to(equal(0)) + } + + func test_fetchMessagesShouldReturnNilWith400Errors() async throws { + let badResponse400 = StubBuilder(test: self, resource: .failure_invalid_request).build(status: 400) + let badResponse401 = StubBuilder(test: self, resource: .failure_invalid_request).build(status: 401) + let badResponse403 = StubBuilder(test: self, resource: .failure_invalid_request).build(status: 403) + let badResponse404 = StubBuilder(test: self, resource: .failure_invalid_request).build(status: 404) + + stub(http(.post, uri: "/v2native/inbox/fetchMessages"), badResponse400) + let res1 = await Inbox.fetchMessages() + expect(res1).to(beNil()) + + stub(http(.post, uri: "/v2native/inbox/fetchMessages"), badResponse401) + let res2 = await Inbox.fetchMessages() + expect(res2).to(beNil()) + + stub(http(.post, uri: "/v2native/inbox/fetchMessages"), badResponse403) + let res3 = await Inbox.fetchMessages() + expect(res3).to(beNil()) + + stub(http(.post, uri: "/v2native/inbox/fetchMessages"), badResponse404) + let res4 = await Inbox.fetchMessages() + expect(res4).to(beNil()) + } + + func test_fetchMessagesShouldReturnNilwith500Error() async throws { + let badResponse500 = StubBuilder(test: self, resource: .failure_server_error).build() + stub(http(.post, uri: "/v2native/inbox/fetchMessages"), badResponse500) + let res = await Inbox.fetchMessages() + expect(res).to(beNil()) + } + + func test_fetchMessagesShouldReturnNilWithInvalidData() async { + let badResponse = """ + { + "messages": [ + { "wrong_key": "invalid value" } + ] + } + """.data(using: .utf8)! + stub(http(.post, uri: "/v2native/inbox/fetchMessages"), jsonData(badResponse)) + let res = await Inbox.fetchMessages() + expect(res).to(beNil()) + } + + func test_openMessagesShouldReturnTrueIfResponseIsSuccess() async throws { + let successResponse = StubBuilder(test: self, resource: .inbox_success_empty).build() + stub(http(.post, uri: "/v2native/inbox/openMessages"), successResponse) + let res = await Inbox.openMessages(messageIds: []) + expect(res).to(beTrue()) + } + + func test_openMessagesShouldReturnFalseIfResponseIsError() async throws { + let badResponse = StubBuilder(test: self, resource: .failure_server_error).build() + stub(http(.post, uri: "/v2native/inbox/openMessages"), badResponse) + let res = await Inbox.openMessages(messageIds: []) + expect(res).to(beFalse()) + } +} diff --git a/KarteTests/KarteInboxTests/TestUtil.swift b/KarteTests/KarteInboxTests/TestUtil.swift new file mode 100644 index 00000000..9b609093 --- /dev/null +++ b/KarteTests/KarteInboxTests/TestUtil.swift @@ -0,0 +1,24 @@ +// +// Copyright 2023 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +@testable import KarteInbox + +struct DummyConfig: InboxConfig { + var baseUrl: URL { + URL(string: "Dummy URL")! + } +} diff --git a/KarteTests/KarteInboxTests/UnitTests/CallerSpec.swift b/KarteTests/KarteInboxTests/UnitTests/CallerSpec.swift new file mode 100644 index 00000000..4b37e6cc --- /dev/null +++ b/KarteTests/KarteInboxTests/UnitTests/CallerSpec.swift @@ -0,0 +1,67 @@ +// +// Copyright 2023 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Quick +import Nimble +import KarteUtilities +@testable import KarteCore +@testable import KarteInbox + +final class CallerSpec: QuickSpec { + @available(iOS 15.0, *) + func testNativeAsyncCaller_shouldReturnNil_withInvalidUserId() async { + let caller = NativeAsyncCaller() + let req = FetchMessagesRequest(visitorId: "Dummy visitorId", config: EvaluationConfig()) + let res = await caller(callee: req) + expect(res).to(beNil()) + } + + @available(iOS 15.0, *) + func testNativeAsyncCaller_shouldReturnNil_withInvalidURL() async { + let caller = NativeAsyncCaller() + let res = await caller(callee: DummyRequest()) + expect(res).to(beNil()) + } + + func testFallbackAsyncCaller_shouldReturnNil_withInvalidUserId() async { + let caller = FallbackAsyncCaller() + let req = FetchMessagesRequest(visitorId: "Dummy visitorId", config: EvaluationConfig()) + let res = await caller(callee: req) + expect(res).to(beNil()) + } + + func testFallbackAsyncCaller_shouldReturnNil_withInvalidURL() async { + let caller = FallbackAsyncCaller() + let res = await caller(callee: DummyRequest()) + expect(res).to(beNil()) + } +} + +private struct DummyRequest: BaseAPIRequest { + typealias Response = String + + var method: HTTPMethod { + .get + } + + var path: String { + "dummy-url" + } + + var config: InboxConfig { + EvaluationConfig() + } +} diff --git a/KarteTests/KarteInboxTests/UnitTests/FetchMessagesRequestSpec.swift b/KarteTests/KarteInboxTests/UnitTests/FetchMessagesRequestSpec.swift new file mode 100644 index 00000000..5b2780c8 --- /dev/null +++ b/KarteTests/KarteInboxTests/UnitTests/FetchMessagesRequestSpec.swift @@ -0,0 +1,68 @@ +// +// Copyright 2023 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Quick +import Nimble +@testable import KarteInbox + +final class FetchMessagesRequestSpec: QuickSpec { + private let visitorId = "Dummy" + private let config = DummyConfig() + + override func spec() { + describe("a request") { + describe("its init") { + context("when initialized with parameters") { + it("has proper URL with ProductionConfig") { + let req = FetchMessagesRequest(visitorId: self.visitorId, config: ProductionConfig()) + expect(req.asURLRequest().url?.absoluteString).to(equal("https://api.karte.io/v2native/inbox/fetchMessages")) + } + + it("has proper URL with EvaluationConfig") { + let req = FetchMessagesRequest(visitorId: self.visitorId, config: EvaluationConfig()) + expect(req.asURLRequest().url?.absoluteString).to(equal("https://api-evaluation.dev-karte.com/v2native/inbox/fetchMessages")) + } + + it("has correspond visitorId in body") { + let req = FetchMessagesRequest(visitorId: self.visitorId, config: self.config) + expect(req.bodyParams?["visitorId"] as? String).to(equal(self.visitorId)) + } + + it("has correspond limit in body") { + let req = FetchMessagesRequest(visitorId: self.visitorId, limit: 1, config: self.config) + expect(req.bodyParams?["limit"] as? UInt).to(equal(1)) + } + + it("has correspond latestMessageId in body") { + let dummy = "Dummy messageId" + let req = FetchMessagesRequest(visitorId: self.visitorId, latestMessageId: dummy, config: self.config) + expect(req.bodyParams?["latestMessageId"] as? String).to(equal(dummy)) + } + } + + context("when initialized without optional parameters") { + it("has nil for optional body parameters") { + let req = FetchMessagesRequest(visitorId: self.visitorId, config: self.config) + let limit = req.bodyParams?["limit"] + let latestMessageId = req.bodyParams?["latestMessageId"] + expect(limit).to(beNil()) + expect(latestMessageId).to(beNil()) + } + } + } + } + } +} diff --git a/KarteTests/KarteInboxTests/UnitTests/OpenMessagesRequestSpec.swift b/KarteTests/KarteInboxTests/UnitTests/OpenMessagesRequestSpec.swift new file mode 100644 index 00000000..24fe4335 --- /dev/null +++ b/KarteTests/KarteInboxTests/UnitTests/OpenMessagesRequestSpec.swift @@ -0,0 +1,53 @@ +// +// Copyright 2023 PLAID, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Quick +import Nimble +@testable import KarteInbox + +final class OpenMessagesRequestSpec: QuickSpec { + private let visitorId = "Dummy" + private let config = DummyConfig() + + override func spec() { + describe("a request") { + describe("its init") { + context("when initialized with parameters") { + it("has proper URL with ProductionConfig") { + let req = OpenMessagesRequest(visitorId: self.visitorId, messageIds: [], config: ProductionConfig()) + expect(req.asURLRequest().url?.absoluteString).to(equal("https://api.karte.io/v2native/inbox/openMessages")) + } + + it("has proper URL with EvaluationConfig") { + let req = OpenMessagesRequest(visitorId: self.visitorId, messageIds: [], config: EvaluationConfig()) + expect(req.asURLRequest().url?.absoluteString).to(equal("https://api-evaluation.dev-karte.com/v2native/inbox/openMessages")) + } + + it("has correspond visitorId in body") { + let req = OpenMessagesRequest(visitorId: self.visitorId, messageIds: [], config: self.config) + expect(req.bodyParams?["visitorId"] as? String).to(equal(self.visitorId)) + } + + it("has correspond messageIds in body") { + let targets = ["aaa", "bbb", "ccc"] + let req = OpenMessagesRequest(visitorId: self.visitorId, messageIds: targets, config: self.config) + expect(req.bodyParams?["messageIds"] as? [String]).to(equal(targets)) + } + } + } + } + } +} diff --git a/KarteTests/Stub/StubResource.swift b/KarteTests/Stub/StubResource.swift index 8a5a2460..89783a81 100644 --- a/KarteTests/Stub/StubResource.swift +++ b/KarteTests/Stub/StubResource.swift @@ -48,4 +48,6 @@ extension StubResource { static var vt2 = StubResource("success_vt_2.json") static var vt_definitions = StubResource("success_vt_definitions.json") static var vt_definitions_with_dynamic_fields = StubResource("success_vt_definitions_with_dynamic_fields.json") + static var inbox_success = StubResource("success_inbox.json") + static var inbox_success_empty = StubResource("success_inbox_empty.json") } diff --git a/KarteTests/Stub/success_inbox.json b/KarteTests/Stub/success_inbox.json new file mode 100644 index 00000000..d6fa1989 --- /dev/null +++ b/KarteTests/Stub/success_inbox.json @@ -0,0 +1,36 @@ +{ + "messages": [ + { + "attachmentUrl": "", + "body": "body1", + "campaignId": "dummy_campaignId_1", + "linkUrl": "", + "messageId": "dummy_messageId_1", + "timestamp": 1674015317, + "title": "title1", + "isRead": true, + "customPayload": { + "keyStr": "Dummy", + "keyInt": 10, + "keyDouble": 1.11, + "keyArray": [1, 2, 3], + "keyMap": { + "prop1": "hoge", + "prop2": 0 + }, + "keyNull": null + } + }, + { + "attachmentUrl": "", + "body": "body2", + "campaignId": "dummy_campaignId_2", + "linkUrl": "", + "messageId": "dummy_messageId_2", + "timestamp": 1672919717, + "title": "title2", + "isRead": false, + "customPayload": {} + } + ] +} diff --git a/KarteTests/Stub/success_inbox_empty.json b/KarteTests/Stub/success_inbox_empty.json new file mode 100644 index 00000000..33c0c847 --- /dev/null +++ b/KarteTests/Stub/success_inbox_empty.json @@ -0,0 +1,3 @@ +{ + "success": true +} diff --git a/Package.swift b/Package.swift index 90fbbda6..acfb070d 100644 --- a/Package.swift +++ b/Package.swift @@ -25,6 +25,10 @@ let package = Package( name: "KarteVisualTracking", targets: ["KarteVisualTracking", "KarteCore", "KarteUtilities"] ), + .library( + name: "KarteInbox", + targets: ["KarteInbox", "KarteCore", "KarteUtilities"] + ), .library( name: "KarteRemoteNotification", targets: ["KarteRemoteNotification", "KarteCore", "KarteUtilities"] @@ -61,6 +65,9 @@ let package = Package( .binaryTarget( name: "KarteVisualTracking", url: "https://sdk.karte.io/ios/swiftpm/VisualTracking-2.12.0/KarteVisualTracking.xcframework.zip", checksum: "03364a75282667223acd96c4132afd173e12cf6da6f87a98855842d5e8d2c605" ), + .binaryTarget( + name: "KarteInbox", url: "https://sdk.karte.io/ios/swiftpm/Inbox-0.1.0/KarteInbox.xcframework.zip", checksum: "09850b4f66bca44e95e6cd3f15cd42a56137d6b4143108a8ac33b6b49aff3920" + ), .binaryTarget( name: "KarteRemoteNotification", url: "https://sdk.karte.io/ios/swiftpm/RemoteNotification-2.11.0/KarteRemoteNotification.xcframework.zip", checksum: "58bde3ca6ff813de18787b9dbe3b3b4e3ff9ddbe1713fb941b6be6d34a196ef6" ), diff --git a/scripts/bump_version.sh b/scripts/bump_version.sh index fb5bff8a..f80d065f 100644 --- a/scripts/bump_version.sh +++ b/scripts/bump_version.sh @@ -11,6 +11,7 @@ MODULES=( "KarteCrashReporting" "KarteVariables" "KarteVisualTracking" + "KarteInbox" "KarteUtilities" "KarteNotificationServiceExtension" ) diff --git a/scripts/publish.sh b/scripts/publish.sh index 79caf8e8..9c0c90c6 100644 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -PODSPECS=("KarteUtilities.podspec" "KarteCore.podspec" "KarteInAppMessaging.podspec" "KarteRemoteNotification.podspec" "KarteVariables.podspec" "KarteVisualTracking.podspec" "KarteCrashReporting.podspec" "KarteNotificationServiceExtension.podspec") +PODSPECS=("KarteUtilities.podspec" "KarteCore.podspec" "KarteInAppMessaging.podspec" "KarteRemoteNotification.podspec" "KarteVariables.podspec" "KarteVisualTracking.podspec" "KarteInbox.podspec" "KarteCrashReporting.podspec" "KarteNotificationServiceExtension.podspec") ################################################## # Functions (Sub command functions) From ec2baacf9288097f117a4696791f16ce61ef5162 Mon Sep 17 00:00:00 2001 From: github actions Date: Thu, 5 Dec 2024 06:22:57 +0000 Subject: [PATCH 5/6] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c55d550..c6905598 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ | KarteUtilities | KarteCore モジュール等が利用するUtility機能を提供します。通常直接参照する必要はありません。 | 3.12.0 | | KarteNotificationServiceExtension | リッチプッシュ通知機能を提供します。 | 1.2.0 | -# Releases - xxxx.xx.xx +# Releases - 2024.12.05 +## Version 2.18.0 ### Core 2.30.0 ** 🎉 FEATURE** From 5b5d33bcfb25f51970f895ef0a4b0d9c11970a58 Mon Sep 17 00:00:00 2001 From: github actions Date: Thu, 5 Dec 2024 06:28:15 +0000 Subject: [PATCH 6/6] Update spm manifest file --- Package.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index acfb070d..acd29a8b 100644 --- a/Package.swift +++ b/Package.swift @@ -54,10 +54,10 @@ let package = Package( name: "KarteUtilities", url: "https://sdk.karte.io/ios/swiftpm/Utilities-3.12.0/KarteUtilities.xcframework.zip", checksum: "850abc71a8bc28e415f4b11e3072ff741a1d908c13b951a4676bc2e675eaf634" ), .binaryTarget( - name: "KarteCore", url: "https://sdk.karte.io/ios/swiftpm/Core-2.29.0/KarteCore.xcframework.zip", checksum: "5b4c1f3e7157a95e9fa6ff2227854a1c5cec76fb4b1571db787b1345e7efde61" + name: "KarteCore", url: "https://sdk.karte.io/ios/swiftpm/Core-2.30.0/KarteCore.xcframework.zip", checksum: "b4814553acd31092d29a50b75b34680484d55eece5c7152dca694590c9263c60" ), .binaryTarget( - name: "KarteInAppMessaging", url: "https://sdk.karte.io/ios/swiftpm/InAppMessaging-2.18.0/KarteInAppMessaging.xcframework.zip", checksum: "d1625e74bac54bd63744c6297b742bb781ea1ab0bf4a4f652fd765245094ffcf" + name: "KarteInAppMessaging", url: "https://sdk.karte.io/ios/swiftpm/InAppMessaging-2.19.0/KarteInAppMessaging.xcframework.zip", checksum: "b87a10043ac75d9c7ced8f7493bd8c8e8d4f590facc7dd51f843675157ecfad9" ), .binaryTarget( name: "KarteVariables", url: "https://sdk.karte.io/ios/swiftpm/Variables-2.10.0/KarteVariables.xcframework.zip", checksum: "19665bf1c9eb5e04719b660839de4ca1145589a62669de6f12efb38fc39a4aad"