Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adopt new api architecture #475

Merged
merged 31 commits into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f5eb1ec
update models
mltbnz Jun 1, 2023
903eccb
rename to service layer to APIService
mltbnz Jun 1, 2023
d80513c
update mapCore
mltbnz Jun 1, 2023
0f99131
update request struct
mltbnz Jun 1, 2023
bbed84b
update Service layer
mltbnz Jun 1, 2023
0c28959
check connection lost errors
mltbnz Jun 1, 2023
f905b1a
remove warnings
mltbnz Jun 1, 2023
8760861
update app core
mltbnz Jun 1, 2023
230dcce
update chat core
mltbnz Jun 1, 2023
7fcd271
update chatView to reflect API changes
mltbnz Jun 1, 2023
bd92f96
remove unused model
mltbnz Jun 1, 2023
8e2bd19
update testplans and project structure
mltbnz Jun 1, 2023
2fb7c40
update MapCore tests
mltbnz Jun 1, 2023
570b435
update chat core tests
mltbnz Jun 1, 2023
aa115d1
disable AppCore tests
mltbnz Jun 1, 2023
cf1b0e9
use gw endpoint for chatMessages
mltbnz Jun 1, 2023
72c8eb0
only fetch chatMessages when view is presented
mltbnz Jun 1, 2023
77f6241
regular fetch behaviour update
mltbnz Jun 1, 2023
8c84f4b
move message fetching to feature core
mltbnz Jun 1, 2023
3f7051b
do not set loading from outside
mltbnz Jun 1, 2023
a5432ee
update timer interval
mltbnz Jun 1, 2023
b25bb48
remove old endpoint
mltbnz Jun 1, 2023
b10db10
fetch locations when modal view is dismissed
mltbnz Jun 1, 2023
9ac622e
update changeLog
mltbnz Jun 1, 2023
48aabd2
update project and dependencies
mltbnz Jun 2, 2023
d8e2362
update changelog
mltbnz Jun 2, 2023
dac3d0e
update rideEvent settings
mltbnz Jun 2, 2023
57d2706
update chat feature tests
mltbnz Jun 2, 2023
13454ce
update appcore tests
mltbnz Jun 2, 2023
1109c47
update offline banner behaviour
mltbnz Jun 2, 2023
6f76ed3
update tests
mltbnz Jun 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

Changelog for Critical Maps iOS

# [4.1.0] - 2023-06-01

### Added

- Adopt new Backend architecture
- Update BottomSheet view that will focus on available next ride
- Performance enhencements

# [4.0.0] - 2022-03-18

__Proposal for the release is to make it `4.0.0`__
Expand Down
18 changes: 15 additions & 3 deletions CriticalMaps.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
732734462771172C0007579E /* CriticalMapsKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = CriticalMapsKit; sourceTree = "<group>"; };
7327344B277118670007579E /* TwitterFeaturePreview.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TwitterFeaturePreview.app; sourceTree = BUILT_PRODUCTS_DIR; };
7327344D277118670007579E /* TwitterFeaturePreviewApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwitterFeaturePreviewApp.swift; sourceTree = "<group>"; };
7347AB262A27BE2A00BCA949 /* ChatFeature.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = ChatFeature.xctestplan; sourceTree = "<group>"; };
7347AB272A27C0A900BCA949 /* MapFeature.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = MapFeature.xctestplan; sourceTree = "<group>"; };
73654C6B26C85FCF004BE38B /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
7369207C28D0D92100EA0584 /* SnapshotTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = SnapshotTests.xctestplan; sourceTree = "<group>"; };
738214EF271F49AB009847C7 /* appIcon-5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "appIcon-5.png"; sourceTree = "<group>"; };
Expand All @@ -44,7 +46,7 @@
739C4980276733E20001466A /* Berlin:Germany.gpx */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = "Berlin:Germany.gpx"; path = "App/Berlin:Germany.gpx"; sourceTree = "<group>"; };
73BABF82277B0A2900D9790F /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
73BABF83277B0A2900D9790F /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
73CA9806268DCC0F004D81FA /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = UnitTests.xctestplan; path = App/UnitTests.xctestplan; sourceTree = "<group>"; };
73CA9806268DCC0F004D81FA /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = "<group>"; };
73CF5FC2263EAF5B001925A3 /* Critical Maps.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Critical Maps.app"; sourceTree = BUILT_PRODUCTS_DIR; };
73CF5FF1263EB0A6001925A3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
73CF5FF6263EB0A6001925A3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -121,6 +123,17 @@
path = TwitterFeaturePreview;
sourceTree = "<group>";
};
7347AB282A27C0CA00BCA949 /* Testplans */ = {
isa = PBXGroup;
children = (
7347AB272A27C0A900BCA949 /* MapFeature.xctestplan */,
7347AB262A27BE2A00BCA949 /* ChatFeature.xctestplan */,
7369207C28D0D92100EA0584 /* SnapshotTests.xctestplan */,
73CA9806268DCC0F004D81FA /* UnitTests.xctestplan */,
);
path = Testplans;
sourceTree = "<group>";
};
738214EE271F49AB009847C7 /* appicons */ = {
isa = PBXGroup;
children = (
Expand All @@ -141,8 +154,7 @@
73BABF83277B0A2900D9790F /* README.md */,
732734462771172C0007579E /* CriticalMapsKit */,
739C4980276733E20001466A /* Berlin:Germany.gpx */,
7369207C28D0D92100EA0584 /* SnapshotTests.xctestplan */,
73CA9806268DCC0F004D81FA /* UnitTests.xctestplan */,
7347AB282A27C0CA00BCA949 /* Testplans */,
73CF5FF0263EB0A6001925A3 /* iOS App */,
7327344C277118670007579E /* TwitterFeaturePreview */,
73238EBB27728043003DE01F /* ChatFeaturePreview */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<TestPlanReference
reference = "container:App/UnitTests.xctestplan">
reference = "container:Testplans/UnitTests.xctestplan">
</TestPlanReference>
</BuildActionEntry>
</BuildActionEntries>
Expand All @@ -39,11 +39,11 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:App/UnitTests.xctestplan"
reference = "container:Testplans/UnitTests.xctestplan"
default = "YES">
</TestPlanReference>
<TestPlanReference
reference = "container:SnapshotTests.xctestplan">
reference = "container:Testplans/SnapshotTests.xctestplan">
</TestPlanReference>
</TestPlans>
</TestAction>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ChatFeature"
BuildableName = "ChatFeature"
BlueprintName = "ChatFeature"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:../Testplans/ChatFeature.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ChatFeature"
BuildableName = "ChatFeature"
BlueprintName = "ChatFeature"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1330"
version = "1.3">
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
Expand All @@ -27,18 +27,12 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "MapFeatureTests"
BuildableName = "MapFeatureTests"
BlueprintName = "MapFeatureTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
<TestPlans>
<TestPlanReference
reference = "container:../MapFeature.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand Down
83 changes: 83 additions & 0 deletions CriticalMapsKit/Sources/ApiClient/APIService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import Foundation
import SharedModels

// MARK: Interface

/// A Service to send and fetch locations and chat messages from the Criticl Maps API
public struct APIService {
public var getRiders: @Sendable () async throws -> [Rider]
public var postRiderLocation: @Sendable (SendLocationPostBody) async throws -> ApiResponse
public var getChatMessages: @Sendable () async throws -> [ChatMessage]
public var postChatMessage: @Sendable (ChatMessagePost) async throws -> ApiResponse

public init(
postRiderLocation: @Sendable @escaping (SendLocationPostBody) async throws -> ApiResponse,
getRiders: @Sendable @escaping () async throws -> [Rider],
getChatMessages: @Sendable @escaping () async throws -> [ChatMessage],
postChatMessage: @Sendable @escaping (ChatMessagePost) async throws -> ApiResponse
) {
self.postRiderLocation = postRiderLocation
self.getRiders = getRiders
self.getChatMessages = getChatMessages
self.postChatMessage = postChatMessage
}
}

// MARK: Live

public extension APIService {
static func live(apiClient: APIClient = .live()) -> Self {
Self(
postRiderLocation: { body in
let request: Request = .put(.locations, body: try? body.encoded())
let (data, _) = try await apiClient.send(request)
return try data.decoded()
},
getRiders: {
let request: Request = .get(.locations)
let (data, _) = try await apiClient.send(request)
return try data.decoded()
},
getChatMessages: {
let request: Request = .get(.chatMessages)
let (data, _) = try await apiClient.send(request)
return try data.decoded()
},
postChatMessage: { body in
let request: Request = .post(.chatMessages, body: try? body.encoded())
let (data, _) = try await apiClient.send(request)
return try data.decoded()
}
)
}
}

// MARK: Mocks and failing used for previews and tests

public extension APIService {
static let noop = Self(
postRiderLocation: { _ in
ApiResponse(status: "ok")
},
getRiders: { [] },
getChatMessages: { [] },
postChatMessage: { _ in
ApiResponse(status: "ok")
}
)

static let failing = Self(
postRiderLocation: { _ in throw NSError(domain: "", code: 1) },
getRiders: { throw NSError(domain: "", code: 1) },
getChatMessages: { throw NSError(domain: "", code: 1) },
postChatMessage: { _ in throw NSError(domain: "", code: 1) }
)
}

public struct ApiResponse: Codable, Equatable {
public init(status: String?) {
self.status = status
}

public var status: String?
}
25 changes: 17 additions & 8 deletions CriticalMapsKit/Sources/ApiClient/Endpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,29 @@ import Foundation
/// A structure to define an endpoint on the Critical Maps API
public struct Endpoint {
public let baseUrl: String
public let path: String?
public let pathComponents: [String]

public init(baseUrl: String, path: String? = nil) {
public init(baseUrl: String, pathComponents: [String] = []) {
self.baseUrl = baseUrl
self.path = path
self.pathComponents = pathComponents
}

var url: String {
guard !pathComponents.isEmpty else {
return baseUrl
}
let path = pathComponents.joined(separator: "/")
return "\(baseUrl)/\(path)"
}
}

public extension Endpoint {
static let criticalmaps = Self(baseUrl: apiBaseUrl)
static let twitter = Self(baseUrl: apiBaseUrl, path: "/twitter")

static let criticalmass = Self(baseUrl: criticalmassInEndpoint, path: "/api/ride")
static let locations = Self(baseUrl: cdnBaseUrl, pathComponents: ["locations"])
static let chatMessages = Self(baseUrl: apiGWBaseUrl, pathComponents: ["messages"])
static let twitter = Self(baseUrl: apiGWBaseUrl, pathComponents: ["twitter"])
static let criticalmass = Self(baseUrl: criticalmassInEndpoint, pathComponents: ["api", "ride"])
}

let criticalmassInEndpoint = "criticalmass.in"
let apiBaseUrl = "api.criticalmaps.net"
let cdnBaseUrl = "api-cdn.criticalmaps.net"
let apiGWBaseUrl = "api-gw.criticalmaps.net"

This file was deleted.

24 changes: 22 additions & 2 deletions CriticalMapsKit/Sources/ApiClient/NetworkDispatcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ extension NetworkDispatcher {
/// Parses a HTTP StatusCode and returns a proper error
/// - Parameter statusCode: HTTP status code
/// - Returns: Mapped Error
private static func httpError(_ statusCode: Int) -> NetworkRequestError {
private static func httpError(_ statusCode: Int?) -> NetworkRequestError {
guard let statusCode else { return .unknownError }
switch statusCode {
case 400: return .badRequest
case 403: return .forbidden
Expand Down Expand Up @@ -48,7 +49,18 @@ public extension NetworkDispatcher {
static func live(urlSession: URLSession = .shared) -> Self {
Self { urlRequest in
let (data, response) = try await urlSession.data(for: urlRequest)
if let response = response as? HTTPURLResponse, !response.isSuccessful {

guard let response = response as? HTTPURLResponse else {
throw NetworkRequestError.invalidResponse
}

// check for connection failure reasons
guard !NSURLErrorConnectionFailureCodes.contains(response.statusCode) else {
throw NetworkRequestError.connectionLost
}

// check if response is successful
guard response.isSuccessful else {
throw httpError(response.statusCode)
}
return (data, response)
Expand All @@ -64,3 +76,11 @@ extension HTTPURLResponse {
(200 ... 299).contains(statusCode)
}
}

let NSURLErrorConnectionFailureCodes: [Int] = [
NSURLErrorCannotFindHost, /// Error Code: ` -1003`
NSURLErrorCannotConnectToHost, /// Error Code: ` -1004`
NSURLErrorNetworkConnectionLost, /// Error Code: ` -1005`
NSURLErrorNotConnectedToInternet, /// Error Code: ` -1009`
NSURLErrorSecureConnectionFailed /// Error Code: ` -1200`
]
Loading
Loading