Skip to content

Commit

Permalink
Revert "Remove inbox (#474)" (#475)
Browse files Browse the repository at this point in the history
This reverts commit a1ffd9f.
  • Loading branch information
TakayukiCho authored Dec 4, 2024
1 parent a1ffd9f commit fb25c26
Show file tree
Hide file tree
Showing 30 changed files with 1,432 additions and 5 deletions.
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
- KarteVariables/**
'Module:VT':
- KarteVisualTracking/**
'Module:Inbox':
- KarteInbox/**
'Module:Detectors':
- KarteDetectors/**
'Module:Utilities':
Expand Down
1 change: 1 addition & 0 deletions .slather.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ binary_basename:
- KarteRemoteNotification
- KarteVisualTracking
- KarteVariables
- KarteInbox
- KarteCrashReporting
- KarteUtilities
- KarteNotificationServiceExtension
1 change: 1 addition & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ included:
- KarteInAppMessaging
- KarteRemoteNotification
- KarteVariables
- KarteInbox
- KarteVisualTracking
- KarteCrashReporting
- KarteNotificationServiceExtension
Expand Down
4 changes: 0 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@

# Releases - xxxx.xx.xx

### Inbox
** 🔨CHANGED**
- Inboxモジュール(β版)の公開を停止しました。

### Core 2.30.0
** 🎉 FEATURE**
- Native機能呼び出しにATT許諾ダイアログ表示を追加しました。
Expand Down
299 changes: 299 additions & 0 deletions Karte.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions KarteInbox.podspec
Original file line number Diff line number Diff line change
@@ -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' => '[email protected]' }
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
68 changes: 68 additions & 0 deletions KarteInbox/API/BaseAPIRequest.swift
Original file line number Diff line number Diff line change
@@ -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
}
}
102 changes: 102 additions & 0 deletions KarteInbox/API/Caller.swift
Original file line number Diff line number Diff line change
@@ -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<Request: BaseAPIRequest>(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<Request: BaseAPIRequest>(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<Request: BaseAPIRequest>(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()
}
}
}
61 changes: 61 additions & 0 deletions KarteInbox/API/FetchMessagesRequest.swift
Original file line number Diff line number Diff line change
@@ -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]
}
45 changes: 45 additions & 0 deletions KarteInbox/API/InboxClient.swift
Original file line number Diff line number Diff line change
@@ -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: BaseAPIRequest>(_ 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
}
}
Loading

0 comments on commit fb25c26

Please sign in to comment.