Created
January 26, 2024 13:45
-
-
Save saroar/56d3caeaab5c15be14ed02d16dac738d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public struct TabReducer: Reducer { | |
public enum Tab: Equatable { case swapToys, conversations, profile, settings } | |
public struct State: Equatable { | |
public var swaps: SwapsReducer.State | |
public var conversations: Conversations.State | |
public var profile: Profile.State | |
public var settings: Settings.State | |
public var isHidden = false | |
public var unreadMessageCount: Int = 0 | |
public var currentUser: UserOutput = .withFirstName // have to not optional | |
public var websocketState: WebSocketReducer.State | |
public var selectedTab: Tab = .swapToys | |
public init( | |
selectedTab: Tab = .swapToys, | |
swaps: SwapsReducer.State = .init(), | |
conversations: Conversations.State = .init(websocketState: .init(user: .withFirstName)), | |
profile: Profile.State = .init(settingsState: .init()), | |
settings: Settings.State = .init(), | |
isHidden: Bool = false, | |
websocketState: WebSocketReducer.State = .init(user: .withFirstName) | |
) { | |
self.selectedTab = selectedTab | |
self.swaps = swaps | |
self.conversations = conversations | |
self.profile = profile | |
self.settings = settings | |
self.isHidden = isHidden | |
self.websocketState = websocketState | |
} | |
} | |
@CasePathable | |
public enum Action: Equatable { | |
case onAppear | |
case connect | |
case disConnect | |
case didSelectTab(Tab) | |
case swaps(SwapsReducer.Action) | |
case conversations(Conversations.Action) | |
case profile(Profile.Action) | |
case settings(Settings.Action) | |
case tabViewIsHidden(Bool) | |
case webSocketReducer(WebSocketReducer.Action) | |
// case scenePhase(ScenePhase) | |
} | |
@Dependency(\.keychainClient) var keychainClient | |
@Dependency(\.build) var build | |
public init() {} | |
public var body: some Reducer<State, Action> { | |
Scope(state: \.websocketState, action: \.webSocketReducer) { | |
WebSocketReducer() | |
} | |
Scope(state: \.swaps, action: \.swaps) { | |
SwapsReducer() | |
} | |
Scope(state: \.conversations, action: \.conversations) { | |
Conversations() | |
} | |
Scope(state: \.profile, action: \.profile) { | |
Profile() | |
} | |
Scope(state: \.settings, action: \.settings) { | |
Settings() | |
} | |
Reduce(self.core) | |
} | |
func core(state: inout State, action: Action) -> Effect<Action> { | |
func handle(_ data: Data) { | |
let chatOutGoingEvent = ChatOutGoingEvent.decode(data: data) | |
switch chatOutGoingEvent { | |
case .connect: | |
break | |
case .disconnect: | |
let warning = state.websocketState.user.id | |
logger.warning("websocker disconnect for user \(warning)") | |
break | |
case .conversation(let lastMessage): | |
guard var findConversation = state.conversations.conversations[id: lastMessage.conversationId] | |
else { return } | |
guard let index = state.conversations.conversations.firstIndex(where: { $0.id == findConversation.id }) | |
else { return } | |
/// issue is when i get msg we update conversation last msg + chat list | |
findConversation.lastMessage = lastMessage | |
state.conversations.conversations[id: lastMessage.conversationId] = findConversation | |
state.conversations.conversations.swapAt(index, 0) | |
case .message(let message): | |
print(#line, message) | |
state.conversations.chatState?.messages.insert(message, at: 0) | |
case .notice(let msg): | |
print(#line, msg) | |
case .error(let error): | |
print(#line, error) | |
case .none: | |
print(#line, "decode error") | |
} | |
} | |
switch action { | |
case .onAppear: | |
do { | |
state.currentUser = try self.keychainClient.readCodable(.user, self.build.identifier(), UserOutput.self) | |
} catch { | |
//state.alert = .init(title: TextState("Missing you id! please login again!")) | |
return .none | |
} | |
state.websocketState.user = state.currentUser | |
return .none | |
case .connect: | |
return .run { send in | |
await send(.webSocketReducer(.handshake)) | |
} | |
case .disConnect: | |
return .run { send in | |
await send(.webSocketReducer(.webSocket(.didClose(code: .goingAway, reason: nil)))) | |
} | |
case .didSelectTab(let tab): | |
state.selectedTab = tab | |
return .none | |
case .tabViewIsHidden: | |
return .none | |
case .swaps: | |
state.swaps.user = state.currentUser | |
// state.swaps.swapFrom?.user = state.currentUser | |
return .none | |
case .conversations(.backToSwaps): | |
state.selectedTab = .swapToys | |
return .none | |
case .conversations: | |
state.conversations.websocketState = state.websocketState | |
return .none | |
case .profile: | |
// state.profile.user = state.currentUser | |
return .none | |
case .webSocketReducer(.receivedSocketMessage(.success(let responseString))): | |
switch responseString { | |
case .data: | |
return .none | |
case .string(let resString): | |
guard let data = resString.data(using: .utf8) else { | |
return .none | |
} | |
handle(data) | |
return .none | |
} | |
case .webSocketReducer(.receivedSocketMessage(.failure)): | |
return .none | |
case .webSocketReducer(.webSocket(.didOpen)): | |
return .none | |
case .webSocketReducer: | |
return .none | |
case .settings: | |
return .none | |
} | |
} | |
} | |
private let logger = Logger(subsystem: "com.addame.AddaMeIOS", category: "tabs.reducer") | |
public struct TabBarView: View { | |
public struct ViewState: Equatable { | |
public init(state: TabReducer.State) { | |
self.selectedTab = state.selectedTab | |
self.isHidden = state.isHidden | |
self.unreadMessageCount = state.unreadMessageCount | |
} | |
public var selectedTab: TabReducer.Tab | |
public var isHidden = false | |
public var unreadMessageCount: Int | |
} | |
public enum ViewAction: Equatable { | |
case onAppear | |
case didSelectTab(TabReducer.Tab) | |
case tabViewIsHidden(Bool) | |
} | |
let store: StoreOf<TabReducer> | |
public init(store: StoreOf<TabReducer>) { | |
self.store = store | |
} | |
public var body: some View { | |
WithViewStore( | |
self.store, | |
observe: ViewState.init | |
) { viewStore in | |
TabView { | |
NavigationStack { | |
SwapsView(store: | |
store.scope(state: \.swaps, action: \.swaps) | |
) | |
} | |
.tabItem { | |
Label("Swap", systemImage: "photo.fill") | |
} | |
.tag(TabReducer.Tab.swapToys) | |
.background(Color.offWhiteLPG) | |
NavigationStack { | |
ConversationsView( | |
store: store.scope( | |
state: \.conversations, | |
action: TabReducer.Action.conversations | |
) | |
) | |
} | |
.tag(TabReducer.Tab.conversations) | |
.tabItem { | |
Label("Conversation", systemImage: "bubble.left.and.bubble.right") | |
} | |
.background(Color.offWhiteLPG) | |
NavigationStack { | |
// MyFamily() | |
ProfileView( | |
store: store.scope(state: \.profile, action: \.profile) | |
) | |
.tag(TabReducer.Tab.profile) | |
} | |
.tabItem { | |
Label("My Family", systemImage: "moon.stars") | |
} | |
.background(Color.offWhiteLPG) | |
// .tag(TabReducer.State.Tab.profile) | |
NavigationView { | |
UI() | |
} | |
.tabItem { | |
Label("UI", systemImage: "heart") | |
} | |
.background(Color.offWhiteLPG) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment