Skip to content

Instantly share code, notes, and snippets.

@saroar
Created January 26, 2024 13:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saroar/56d3caeaab5c15be14ed02d16dac738d to your computer and use it in GitHub Desktop.
Save saroar/56d3caeaab5c15be14ed02d16dac738d to your computer and use it in GitHub Desktop.
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