Skip to content

Commit de80b53

Browse files
committed
feat: Feed Sheet 개발 완료
1 parent edf0229 commit de80b53

11 files changed

Lines changed: 149 additions & 66 deletions

File tree

Projects/Feature/Feed/Interface/Sources/Route/FeedRoute.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77

88
public enum FeedRoute: Equatable {
9-
case groupMenu
9+
case addGroup
1010
}
1111

1212
@MainActor
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//
2+
// FeedViewController+GroupMenuSheet.swift
3+
// Feed
4+
//
5+
// Created by 김동준 on 7/14/26.
6+
//
7+
8+
import SwiftUI
9+
import CommonDomain
10+
11+
extension FeedViewController {
12+
func presentGroupMenuSheet(
13+
groupList: [GroupModel],
14+
selectedGroup: GroupModel,
15+
onGroupSelect: @escaping (GroupModel) -> Void,
16+
onAddGroupTap: @escaping () -> Void
17+
) {
18+
guard presentedViewController == nil else { return }
19+
20+
let viewController = UIHostingController(
21+
rootView: FeedGroupSelectSheetView(
22+
groupList: groupList,
23+
selectedGroup: selectedGroup,
24+
onGroupSelect: { [weak self] group in
25+
self?.dismiss(animated: true) {
26+
onGroupSelect(group)
27+
}
28+
},
29+
onAddGroupTap: { [weak self] in
30+
self?.dismiss(animated: true) {
31+
onAddGroupTap()
32+
}
33+
}
34+
)
35+
)
36+
viewController.view.backgroundColor = .systemWhite
37+
viewController.modalPresentationStyle = .pageSheet
38+
39+
if let sheetPresentationController = viewController.sheetPresentationController {
40+
let identifier = UISheetPresentationController.Detent.Identifier("groupSelect")
41+
sheetPresentationController.detents = [
42+
.custom(identifier: identifier) { _ in
43+
407
44+
}
45+
]
46+
sheetPresentationController.prefersGrabberVisible = true
47+
sheetPresentationController.preferredCornerRadius = 36
48+
}
49+
50+
present(viewController, animated: true)
51+
}
52+
}

Projects/Feature/Feed/Sources/Presentation/FeedReactor.swift

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ public final class FeedReactor: Reactor {
1818
public struct State {
1919
var isFloatingActionButtonExpanded = false
2020
var groups: [GroupModel] = []
21+
var selectedGroup: GroupModel?
2122
var isFetchGroupLoading = false
2223
}
2324

2425
public enum Mutation {
2526
case setFloatingActionButtonExpanded(Bool)
2627
case setGroups([GroupModel])
28+
case setSelectedGroup(GroupModel)
2729
case setFetchGroupLoading(Bool)
2830
}
2931

@@ -33,7 +35,8 @@ public final class FeedReactor: Reactor {
3335
case didTapFloatingActionButton
3436
case didTapExerciseRecordButton
3537
case didTapMealRecordButton
36-
case didGroupButtonTapped
38+
case didTapAddGroup
39+
case didSelectGroup(GroupModel)
3740
}
3841

3942
public init(
@@ -60,16 +63,16 @@ public final class FeedReactor: Reactor {
6063
return .just(.setFloatingActionButtonExpanded(false))
6164
case .didTapMealRecordButton:
6265
return .just(.setFloatingActionButtonExpanded(false))
63-
case .didGroupButtonTapped:
64-
guard !currentState.isFetchGroupLoading,
65-
!currentState.groups.isEmpty else {
66-
return .empty()
67-
}
68-
66+
case .didTapAddGroup:
6967
Task { @MainActor [weak router] in
70-
router?.route(from: .groupMenu)
68+
router?.route(from: .addGroup)
7169
}
7270
return .empty()
71+
case let .didSelectGroup(group):
72+
guard currentState.groups.contains(where: { $0.groupId == group.groupId }) else {
73+
return .empty()
74+
}
75+
return .just(.setSelectedGroup(group))
7376
}
7477
}
7578

@@ -81,6 +84,11 @@ public final class FeedReactor: Reactor {
8184
newState.isFloatingActionButtonExpanded = isExpanded
8285
case .setGroups(let groups):
8386
newState.groups = groups
87+
if newState.selectedGroup == nil, groups.count > 0 {
88+
newState.selectedGroup = groups.first
89+
}
90+
case .setSelectedGroup(let group):
91+
newState.selectedGroup = group
8492
case .setFetchGroupLoading(let isLoading):
8593
newState.isFetchGroupLoading = isLoading
8694
}

Projects/Feature/Feed/Sources/Presentation/FeedViewController.swift

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,21 @@ public final class FeedViewController: UIViewController, View {
102102
.disposed(by: disposeBag)
103103

104104
groupButton.rx.tap
105-
.map { FeedReactor.Action.didGroupButtonTapped }
106-
.bind(to: reactor.action)
105+
.withLatestFrom(reactor.state)
106+
.compactMap { FeedGroupMenuSheetViewState(state: $0) }
107+
.observe(on: MainScheduler.instance)
108+
.bind(with: self) { owner, viewState in
109+
owner.presentGroupMenuSheet(
110+
groupList: viewState.groupList,
111+
selectedGroup: viewState.selectedGroup,
112+
onGroupSelect: { group in
113+
reactor.action.onNext(.didSelectGroup(group))
114+
},
115+
onAddGroupTap: {
116+
reactor.action.onNext(.didTapAddGroup)
117+
}
118+
)
119+
}
107120
.disposed(by: disposeBag)
108121

109122
reactor.state
@@ -119,7 +132,7 @@ public final class FeedViewController: UIViewController, View {
119132
.map { state in
120133
FeedGroupHeaderViewState(
121134
isLoading: state.isFetchGroupLoading,
122-
groupName: state.groups.first?.name
135+
groupName: state.selectedGroup?.name
123136
)
124137
}
125138
.distinctUntilChanged()

Projects/Feature/Main/Sources/MainContainer/Sheet/MainGroupSelectSheetView.swift renamed to Projects/Feature/Feed/Sources/Presentation/Sheet/FeedGroupSelectSheetView.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
//
2-
// MainGroupSelectSheetView.swift
3-
// Main
2+
// FeedGroupSelectSheetView.swift
3+
// Feed
44
//
5-
// Created by 김동준 on 7/6/26.
5+
// Created by 김동준 on 7/14/26.
66
//
77

88
import SwiftUI
99
import CommonDomain
1010
import DesignSystem
1111

12-
struct MainGroupSelectSheetView: View {
12+
struct FeedGroupSelectSheetView: View {
1313
private let groupList: [GroupModel]
1414
private let selectedGroup: GroupModel
1515
private let onGroupSelect: (GroupModel) -> Void
@@ -48,17 +48,17 @@ struct MainGroupSelectSheetView: View {
4848
}
4949
}
5050

51-
private extension MainGroupSelectSheetView {
51+
private extension FeedGroupSelectSheetView {
5252
func groupRow(_ group: GroupModel) -> some View {
5353
let isSelected = group.groupId == selectedGroup.groupId
54-
54+
5555
return Button {
5656
onGroupSelect(group)
5757
} label: {
5858
HStack(spacing: 0) {
5959
groupInfo(group)
6060
Spacer()
61-
61+
6262
if isSelected {
6363
MText(
6464
"현재 보는 중",
@@ -84,11 +84,11 @@ private extension MainGroupSelectSheetView {
8484
}
8585
}
8686
}
87-
87+
8888
func groupInfo(_ group: GroupModel) -> some View {
8989
VStack(alignment: .leading, spacing: 6) {
9090
groupTitle(group)
91-
91+
9292
MText(
9393
"그룹코드 \(group.code)",
9494
style: .c2,
@@ -97,7 +97,7 @@ private extension MainGroupSelectSheetView {
9797
)
9898
}
9999
}
100-
100+
101101
func groupTitle(_ group: GroupModel) -> some View {
102102
HStack(spacing: 4) {
103103
MText(
@@ -106,7 +106,7 @@ private extension MainGroupSelectSheetView {
106106
color: .gray10,
107107
alignment: .leading
108108
)
109-
109+
110110
MText(
111111
"그룹",
112112
style: .c2,
@@ -116,7 +116,7 @@ private extension MainGroupSelectSheetView {
116116
}
117117
}
118118

119-
private extension MainGroupSelectSheetView {
119+
private extension FeedGroupSelectSheetView {
120120
var addGroupButton: some View {
121121
MButton(
122122
"그룹 추가하기",
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// FeedGroupMenuSheetViewState.swift
3+
// Feed
4+
//
5+
// Created by 김동준 on 7/14/26.
6+
//
7+
8+
import CommonDomain
9+
10+
struct FeedGroupMenuSheetViewState {
11+
let groupList: [GroupModel]
12+
let selectedGroup: GroupModel
13+
14+
init?(state: FeedReactor.State) {
15+
guard !state.isFetchGroupLoading,
16+
let selectedGroup = state.selectedGroup else {
17+
return nil
18+
}
19+
20+
self.groupList = state.groups
21+
self.selectedGroup = selectedGroup
22+
}
23+
}

Projects/Feature/Main/Sources/Coordinator/MainCoordinator.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ public final class MainCoordinator {
7474
tabs: tabs
7575
)
7676
self.mainContainerViewController = mainContainerViewController
77-
mainContainerViewController.onSheetGroupParticipateTap = { [weak self] in
77+
mainContainerViewController.onGroupParticipateTap = { [weak self] in
7878
self?.showGroupParticipate()
7979
}
80-
mainContainerViewController.onSheetGroupCreateTap = { [weak self] in
80+
mainContainerViewController.onGroupCreateTap = { [weak self] in
8181
self?.showGroupCreate(needBackButton: true)
8282
}
8383

Projects/Feature/Main/Sources/MainContainer/Extensions/MainContainerViewController+Overlay.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,32 @@
66
//
77

88
import UIKit
9+
import SwiftUI
910
import SnapKit
1011

1112
extension MainContainerViewController {
13+
func presentAddGroupAlert() {
14+
let viewController = UIHostingController(
15+
rootView: MainAddGroupAlertView(
16+
onDismiss: { [weak self] in
17+
self?.dismissOverlay()
18+
},
19+
onParticipateTap: { [weak self] in
20+
self?.dismissOverlay {
21+
self?.onGroupParticipateTap?()
22+
}
23+
},
24+
onCreateTap: { [weak self] in
25+
self?.dismissOverlay {
26+
self?.onGroupCreateTap?()
27+
}
28+
}
29+
)
30+
)
31+
32+
showOverlay(viewController)
33+
}
34+
1235
func showOverlay(_ overlayViewController: UIViewController) {
1336
removeCurrentOverlay()
1437

Projects/Feature/Main/Sources/MainContainer/Extensions/MainContainerViewController+Sheet.swift

Lines changed: 0 additions & 36 deletions
This file was deleted.

Projects/Feature/Main/Sources/MainContainer/MainContainerViewController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import SnapKit
1111
import DesignSystem
1212

1313
final class MainContainerViewController: UIViewController {
14-
var onSheetGroupParticipateTap: (() -> Void)?
15-
var onSheetGroupCreateTap: (() -> Void)?
14+
var onGroupParticipateTap: (() -> Void)?
15+
var onGroupCreateTap: (() -> Void)?
1616
var onAlarmTap: (() -> Void)?
1717
var currentOverlayViewController: UIViewController?
1818

0 commit comments

Comments
 (0)