Skip to content

Commit

Permalink
Add INFO view (#489)
Browse files Browse the repository at this point in the history
  • Loading branch information
mltbnz authored Jul 29, 2023
1 parent 61ad9f4 commit 014806a
Show file tree
Hide file tree
Showing 27 changed files with 487 additions and 225 deletions.
2 changes: 1 addition & 1 deletion App/iOS App/App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
reducer: AppFeature()
)
lazy var viewStore = ViewStore(
self.store.scope(state: { _ in () }),
self.store.scope(state: { _ in () }, action: { $0 }),
removeDuplicates: ==
)

Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@

Changelog for Critical Maps iOS

# [4.3.0] - 2023-07-21

### Added

- Info view with next update countdown and riders count view

### Updated

- Send location on a timly base

### Fixed

- Store user settings failure fixed


# [4.2.1] - 2023-06-05

### Fixed
Expand Down
126 changes: 69 additions & 57 deletions CriticalMapsKit/Sources/AppFeature/AppFeatureCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import MapFeature
import MapKit
import MastodonFeedFeature
import NextRideFeature
import PathMonitorClient
import SettingsFeature
import SharedDependencies
import SharedModels
Expand All @@ -33,7 +32,6 @@ public struct AppFeature: ReducerProtocol {
@Dependency(\.locationManager) public var locationManager
@Dependency(\.uiApplicationClient) public var uiApplicationClient
@Dependency(\.setUserInterfaceStyle) public var setUserInterfaceStyle
@Dependency(\.pathMonitorClient) public var pathMonitorClient
@Dependency(\.isNetworkAvailable) public var isNetworkAvailable

// MARK: State
Expand Down Expand Up @@ -66,17 +64,34 @@ public struct AppFeature: ReducerProtocol {

public var riderLocations: TaskResult<[Rider]>?
public var didResolveInitialLocation = false
public var isRequestingRiderLocations = false

// Children states
public var mapFeatureState = MapFeature.State(
riders: [],
userTrackingMode: UserTrackingFeature.State(userTrackingMode: .follow)
)

public var timerProgress: Double {
let progress = Double(requestTimer.secondsElapsed) / 60
return progress
}
public var sendLocation: Bool {
requestTimer.secondsElapsed == 30
}
public var timerValue: String {
let progress = 60 - requestTimer.secondsElapsed
return String(progress)
}
public var ridersCount: String {
let count = mapFeatureState.visibleRidersCount ?? 0
return NumberFormatter.riderCountFormatter.string(from: .init(value: count)) ?? ""
}

public var socialState = SocialFeature.State()
public var settingsState = SettingsFeature.State(userSettings: .init())
public var nextRideState = NextRideFeature.State()
public var requestTimer = RequestTimer.State()
public var connectionObserverState = NetworkConnectionObserver.State()

// Navigation
public var route: AppRoute?
Expand Down Expand Up @@ -129,20 +144,12 @@ public struct AppFeature: ReducerProtocol {
case requestTimer(RequestTimer.Action)
case settings(SettingsFeature.Action)
case social(SocialFeature.Action)
case connectionObserver(NetworkConnectionObserver.Action)
}

// MARK: Reducer

struct ObserveConnectionIdentifier: Hashable {}

public var body: some ReducerProtocol<State, Action> {
BindingReducer()

Scope(state: \.connectionObserverState, action: /AppFeature.Action.connectionObserver) {
NetworkConnectionObserver()
}

Scope(state: \.requestTimer, action: /AppFeature.Action.requestTimer) {
RequestTimer()
}
Expand Down Expand Up @@ -190,6 +197,15 @@ public struct AppFeature: ReducerProtocol {

case .onAppear:
var effects: [EffectTask<Action>] = [
EffectTask(value: .map(.onAppear)),
EffectTask(value: .requestTimer(.startTimer)),
.task {
await .userSettingsLoaded(
TaskResult {
try await fileClient.loadUserSettings()
}
)
},
.run { send in
await withThrowingTaskGroup(of: Void.self) { group in
group.addTask {
Expand All @@ -199,16 +215,7 @@ public struct AppFeature: ReducerProtocol {
await send(.fetchLocations)
}
}
},
.task {
await .userSettingsLoaded(
TaskResult {
try await fileClient.loadUserSettings()
}
)
},
EffectTask(value: .map(.onAppear)),
EffectTask(value: .requestTimer(.startTimer))
}
]
if !userDefaultsClient.didShowObservationModePrompt {
effects.append(
Expand All @@ -222,9 +229,10 @@ public struct AppFeature: ReducerProtocol {
return .merge(effects)

case .onDisappear:
return EffectTask.cancel(id: ObserveConnectionIdentifier())
return .none

case .fetchLocations:
state.isRequestingRiderLocations = true
return .task {
await .fetchLocationsResponse(
TaskResult {
Expand Down Expand Up @@ -268,11 +276,13 @@ public struct AppFeature: ReducerProtocol {
return .none

case let .fetchLocationsResponse(.success(response)):
state.isRequestingRiderLocations = false
state.riderLocations = .success(response)
state.mapFeatureState.riderLocations = response
return .none

case let .fetchLocationsResponse(.failure(error)):
state.isRequestingRiderLocations = false
logger.info("FetchLocation failed: \(error)")
state.riderLocations = .failure(error)
return .none
Expand Down Expand Up @@ -311,29 +321,8 @@ public struct AppFeature: ReducerProtocol {
}

case .locationManager(.didUpdateLocations):
let isInitialLocation = state.nextRideState.userLocation == nil

// sync with nextRideState
state.nextRideState.userLocation = state.mapFeatureState.location?.coordinate

if
let coordinate = state.mapFeatureState.location?.coordinate,
state.settingsState.rideEventSettings.isEnabled,
isInitialLocation
{
return .run { send in
await withThrowingTaskGroup(of: Void.self) { group in
group.addTask {
await send(.postLocation)
}
group.addTask {
await send(.nextRide(.getNextRide(coordinate)))
}
}
}
} else {
return EffectTask(value: .postLocation)
}
return .none

default:
return .none
Expand All @@ -359,8 +348,17 @@ public struct AppFeature: ReducerProtocol {
let userSettings = (try? result.value) ?? UserSettings()
state.settingsState = .init(userSettings: userSettings)
state.nextRideState.rideEventSettings = userSettings.rideEventSettings

let style = state.settingsState.appearanceSettings.colorScheme.userInterfaceStyle
let coordinate = state.mapFeatureState.location?.coordinate
let isRideEventsEnabled = state.settingsState.rideEventSettings.isEnabled

return .merge(
.run { send in
if isRideEventsEnabled, let coordinate {
await send(.nextRide(.getNextRide(coordinate)))
}
},
.fireAndForget {
await setUserInterfaceStyle(style)
}
Expand All @@ -386,19 +384,27 @@ public struct AppFeature: ReducerProtocol {
case let .requestTimer(timerAction):
switch timerAction {
case .timerTicked:
return .run { [isChatPresented = state.isChatViewPresented, isPrentingSubView = state.route != nil] send in
await withThrowingTaskGroup(of: Void.self) { group in
if !isPrentingSubView {
group.addTask {
await send(.fetchLocations)
if state.requestTimer.secondsElapsed == 60 {
state.requestTimer.secondsElapsed = 0

return .run { [isChatPresented = state.isChatViewPresented, isPrentingSubView = state.route != nil] send in
await withThrowingTaskGroup(of: Void.self) { group in
if !isPrentingSubView {
group.addTask {
await send(.fetchLocations)
}
}
}
if isChatPresented {
group.addTask {
await send(.fetchChatMessages)
if isChatPresented {
group.addTask {
await send(.fetchChatMessages)
}
}
}
}
} else if state.sendLocation {
return EffectTask(value: .postLocation)
} else {
return .none
}

default:
Expand Down Expand Up @@ -447,10 +453,7 @@ public struct AppFeature: ReducerProtocol {
default:
return .none
}

case .connectionObserver:
return .none


case .binding:
return .none
}
Expand Down Expand Up @@ -501,3 +504,12 @@ public extension AlertState where Action == AppFeature.Action {
}

public typealias ReducerBuilderOf<R: ReducerProtocol> = ReducerBuilder<R.State, R.Action>

extension NumberFormatter {
static let riderCountFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.groupingSeparator = "."
return formatter
}()
}
10 changes: 4 additions & 6 deletions CriticalMapsKit/Sources/AppFeature/AppNavigationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,18 @@ import Styleguide
import SwiftUI

public struct AppNavigationView: View {
public typealias State = AppFeature.State
public typealias Action = AppFeature.Action
let store: StoreOf<AppFeature>

let store: Store<State, Action>
@ObservedObject var viewStore: ViewStore<State, Action>
@ObservedObject var viewStore: ViewStoreOf<AppFeature>
@Environment(\.colorScheme) var colorScheme
@Environment(\.accessibilityReduceTransparency) var reduceTransparency
@Environment(\.colorSchemeContrast) var colorSchemeContrast

let minHeight: CGFloat = 56

public init(store: Store<State, Action>) {
public init(store: StoreOf<AppFeature>) {
self.store = store
viewStore = ViewStore(store)
viewStore = ViewStore(store, observe: { $0 })
}

public var body: some View {
Expand Down
Loading

0 comments on commit 014806a

Please sign in to comment.