Skip to content

Commit

Permalink
feature: 마이페이지 오프라인 대응
Browse files Browse the repository at this point in the history
  • Loading branch information
Jihyun247 committed Aug 20, 2024
1 parent cc92ce2 commit 782935d
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 23 deletions.
Binary file modified DependencyGraph/mohanyang_dev_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified DependencyGraph/mohanyang_prod_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import DependenciesMacros
@DependencyClient
public struct NetworkTracking {
public var start: @Sendable () -> Void
public var updateNetworkConnected: @Sendable () -> AsyncThrowingStream<Bool, Error> = { .never }
public var updateNetworkConnected: @Sendable () -> AsyncStream<Bool> = { .never }
public var cancel: @Sendable () -> Void
}

Expand Down
10 changes: 7 additions & 3 deletions Projects/Domain/NetworkTracking/Sources/NetworkTracking.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,21 @@ import NetworkTrackingInterface

import Dependencies

extension NetworkTracking {
extension NetworkTracking: DependencyKey {
public static let liveValue: NetworkTracking = .live()

public static func live() -> NetworkTracking {
let networkMonitor = NWPathMonitor()
let globalQueue = DispatchQueue.global()

return NetworkTracking(
start: {
networkMonitor.start(queue: DispatchQueue.global())
networkMonitor.start(queue: globalQueue)
},
updateNetworkConnected: {
return AsyncThrowingStream<Bool, Error> { continuation in
return AsyncStream<Bool> { continuation in
let initialState = networkMonitor.currentPath.status == .satisfied ? true : false
continuation.yield(initialState)
networkMonitor.pathUpdateHandler = { path in
let isConnected = path.status == .satisfied ? true : false
continuation.yield(isConnected)
Expand Down
34 changes: 29 additions & 5 deletions Projects/Feature/MyPageFeature/Sources/MyPage/MyPageCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import APIClientInterface
import UserServiceInterface
import CatServiceInterface
import UserDefaultsClientInterface
import NetworkTrackingInterface

import ComposableArchitecture

Expand All @@ -22,22 +23,25 @@ public struct MyPageCore {
var cat: AnyCat? = nil
var isTimerAlarmOn: Bool = false
var isDisturbAlarmOn: Bool = false
var isInternetConnected: Bool = false
var isNetworkConnected: Bool = false
let feedbackURLString: String = "https://forms.gle/wEUPH9Tvxgua4hCZ9"
@Presents var myCat: MyCatCore.State?
}

public enum Action: BindableAction {
case onAppear
case onDisappear
case myCatDetailTapped
case _responseUserInfo(UserDTO.Response.GetUserInfoResponseDTO)
case _fetchNetworkConntection(Bool)
case myCat(PresentationAction<MyCatCore.Action>)
case binding(BindingAction<State>)
}

@Dependency(APIClient.self) var apiClient
@Dependency(UserService.self) var userService
@Dependency(UserDefaultsClient.self) var userDefaultsClient
@Dependency(NetworkTracking.self) var networkTracking
let isTimerAlarmOnKey = "mohanyang_userdefaults_isTimerAlarmOnKey"
let isDisturbAlarmOnKey = "mohanyang_userdefaults_isDisturmAlarmOnKey"

Expand All @@ -56,10 +60,17 @@ public struct MyPageCore {
case .onAppear:
state.isTimerAlarmOn = userDefaultsClient.boolForKey(isTimerAlarmOnKey)
state.isDisturbAlarmOn = userDefaultsClient.boolForKey(isDisturbAlarmOnKey)
return .run { send in
let data = try await userService.getUserInfo(apiClient: apiClient)
await send(._responseUserInfo(data))
}
return .merge(
.run { send in
let data = try await userService.getUserInfo(apiClient: apiClient)
await send(._responseUserInfo(data))
},
fetchNetworkConnection()
)

case .onDisappear:
networkTracking.cancel()
return .none

case .myCatDetailTapped:
guard let cat = state.cat else { return .none }
Expand All @@ -74,6 +85,10 @@ public struct MyPageCore {
)
return .none

case ._fetchNetworkConntection(let isConntected):
state.isNetworkConnected = isConntected
return .none

case .myCat:
return .none

Expand All @@ -91,4 +106,13 @@ public struct MyPageCore {
return .none
}
}

private func fetchNetworkConnection() -> Effect<Action> {
networkTracking.start()
return .run { send in
for await isConnected in networkTracking.updateNetworkConnected() {
await send(._fetchNetworkConntection(isConnected))
}
}
}
}
39 changes: 25 additions & 14 deletions Projects/Feature/MyPageFeature/Sources/MyPage/MyPageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ import ComposableArchitecture

public struct MyPageView: View {
@Bindable var store: StoreOf<MyPageCore>

public init(store: StoreOf<MyPageCore>) {
self.store = store
}

public var body: some View {
NavigationContainer(
title: Text("마이페이지"),
Expand All @@ -27,17 +27,22 @@ public struct MyPageView: View {
ScrollView {
VStack(spacing: Alias.Spacing.medium) {

MyCatSectionView(name: store.cat?.name ?? "")
.padding(.all, Alias.Spacing.xLarge)
.background(
RoundedRectangle(cornerRadius: Alias.BorderRadius.small)
.foregroundStyle(Alias.Color.Background.secondary)
)
.onTapGesture {
MyCatSectionView(
name: store.cat?.name ?? "",
isNetworkConntected: $store.isNetworkConnected
)
.padding(.all, Alias.Spacing.xLarge)
.background(
RoundedRectangle(cornerRadius: Alias.BorderRadius.small)
.foregroundStyle(Alias.Color.Background.secondary)
)
.onTapGesture {
if store.isNetworkConnected {
store.send(.myCatDetailTapped)
}
}

StatisticSectionView(isInternetConnected: $store.isInternetConnected)
StatisticSectionView(isNetworkConnected: $store.isNetworkConnected)
.padding(.all, Alias.Spacing.xLarge)
.background(
RoundedRectangle(cornerRadius: Alias.BorderRadius.medium)
Expand Down Expand Up @@ -92,6 +97,9 @@ public struct MyPageView: View {
.onAppear {
store.send(.onAppear)
}
.onDisappear {
store.send(.onDisappear)
}
}

private func openFeedbackForm(urlString: String) {
Expand All @@ -103,6 +111,7 @@ public struct MyPageView: View {

struct MyCatSectionView: View {
let name: String
@Binding var isNetworkConntected: Bool

var body: some View {
HStack {
Expand All @@ -115,19 +124,21 @@ struct MyCatSectionView: View {
.foregroundStyle(Color.black)
}
Spacer()
DesignSystemAsset.Image._24ChevronRightPrimary.swiftUIImage
if isNetworkConntected {
DesignSystemAsset.Image._24ChevronRightPrimary.swiftUIImage
}
}
}
}

struct StatisticSectionView: View {
@Binding var isInternetConnected: Bool
@Binding var isNetworkConnected: Bool

var body: some View {
ZStack {
VStack(spacing: Alias.Spacing.medium) {
Spacer()
if isInternetConnected {
if isNetworkConnected {
DesignSystemAsset.Image.imgUpdateStatistics.swiftUIImage
} else {
DesignSystemAsset.Image.imgOfflineStatistics.swiftUIImage
Expand All @@ -153,7 +164,7 @@ struct AlarmSectionView: View {
let title: String
let subTitle: String
@Binding var isOn: Bool

var body: some View {
HStack(spacing: 0) {
VStack(alignment: .leading, spacing: Alias.Spacing.xSmall) {
Expand Down

0 comments on commit 782935d

Please sign in to comment.