Skip to content

Commit 833e753

Browse files
committed
[#465] 태그편집 기능 구현
1 parent 01b678b commit 833e753

File tree

4 files changed

+68
-22
lines changed

4 files changed

+68
-22
lines changed

DesignSystem/Views/DynamicCellLayout.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import SwiftUI
1111
Cell들의 폭의 반응하여 List를 만드는 구조체
1212
*/
1313
struct DynamicCellLayout<Data: RandomAccessCollection>: View where Data.Element: DynamicCell {
14+
@EnvironmentObject var tagViewModel: TagViewModel
1415
let data: Data
1516
let action: (String) -> Void
1617
let screenWidth: CGFloat
@@ -21,15 +22,14 @@ struct DynamicCellLayout<Data: RandomAccessCollection>: View where Data.Element:
2122
}
2223

2324
private func generateLayout(items: Data) -> some View {
24-
//let screenWidth = UIScreen.main.bounds.width
2525

2626
var currentWidth: CGFloat = 0
2727
var currentArrays = [Data.Element]()
2828

2929
var resultRows = [[Data.Element]]()
3030

3131
for (index, item) in items.enumerated() {
32-
let itemWidth = item.getCellWidth() + 16
32+
let itemWidth = item.itemWidth(isEditMode: tagViewModel.isEditMode)
3333
if currentWidth + itemWidth + 20 >= screenWidth {
3434
resultRows.append(currentArrays)
3535
currentArrays.removeAll()

Presentation/Home/HomeSearch/Cell/PDFTagCell.swift

+28-8
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,27 @@ struct PDFTagCell<Tag: DynamicCell>: View {
2424
action()
2525
} label: {
2626
// TODO: 태그 title
27-
Text(tag.name)
28-
.reazyFont(.h3)
29-
.foregroundStyle(isSelected ? .gray300 : .gray800)
30-
.frame(width: tag.getCellWidth(), height: 24)
31-
.padding(.horizontal, 8)
32-
.background {
33-
RoundedRectangle(cornerRadius: 4)
34-
.foregroundStyle(isSelected ? .point4 : .primary3)
27+
HStack(spacing: 8) {
28+
Text(tag.name)
29+
.reazyFont(.h3)
30+
.foregroundStyle(isSelected ? .gray300 : .gray800)
31+
.frame(width: tag.getCellWidth())
32+
if tagViewModel.isEditMode {
33+
Button {
34+
tagViewModel.deleteTag(id: tag.id)
35+
} label: {
36+
Image(systemName: "x.circle.fill")
37+
.foregroundStyle(.gray700)
38+
.font(.system(size: 12))
39+
}
3540
}
41+
}
42+
.padding(.horizontal, 8)
43+
.frame(height: 24)
44+
.background {
45+
RoundedRectangle(cornerRadius: 4)
46+
.foregroundStyle(isSelected ? .point4 : .primary3)
47+
}
3648
}
3749
}
3850
}
@@ -65,3 +77,11 @@ protocol DynamicCell: Hashable, Identifiable {
6577

6678
func getCellWidth() -> CGFloat
6779
}
80+
81+
extension DynamicCell {
82+
/// 편집 모드 여부에 따라 동적으로 셀 너비를 계산
83+
func itemWidth(isEditMode: Bool) -> CGFloat {
84+
let additionalPadding: CGFloat = isEditMode ? 40 : 16
85+
return getCellWidth() + additionalPadding
86+
}
87+
}

Presentation/Home/TagSearch/TagView.swift

+31-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import SwiftUI
1010
// MARK: - [쿠로] 태그 뷰!
1111
struct TagView: View {
1212
@EnvironmentObject private var tagViewModel: TagViewModel
13-
@State private var popover = false
1413
@Namespace private var nsPopover
1514

1615
var body: some View {
@@ -50,14 +49,28 @@ struct TagView: View {
5049
// 편집 버튼
5150
HStack(spacing: 0) {
5251
Spacer()
53-
EllipsisView(ellipsisAction: {
54-
withAnimation {
55-
popover.toggle()
52+
if tagViewModel.isEditMode {
53+
Button {
54+
withAnimation {
55+
tagViewModel.isEditMode = false
56+
}
57+
} label: {
58+
Text("완료")
59+
.reazyFont(.button1)
60+
.foregroundColor(.primary1)
61+
.padding(.trailing, 24)
62+
.padding(.bottom, 20)
5663
}
57-
})
58-
.matchedGeometryEffect(id: "popover",
59-
in: nsPopover,
60-
anchor: .topTrailing)
64+
} else {
65+
EllipsisView(ellipsisAction: {
66+
withAnimation {
67+
tagViewModel.popover.toggle()
68+
}
69+
})
70+
.matchedGeometryEffect(id: "popover",
71+
in: nsPopover,
72+
anchor: .topTrailing)
73+
}
6174
}
6275
}
6376
.frame(maxWidth: .infinity,maxHeight: geometry.size.height * 0.4)
@@ -68,7 +81,7 @@ struct TagView: View {
6881
}
6982
.padding([.top, .horizontal], 20)
7083
}
71-
if popover {
84+
if tagViewModel.popover {
7285
EllipsisButtonView(namespace: nsPopover)
7386
.transition(.opacity.combined(with: .scale))
7487
}
@@ -77,7 +90,7 @@ struct TagView: View {
7790
.ignoresSafeArea(.all)
7891
.onTapGesture {
7992
withAnimation {
80-
popover = false
93+
tagViewModel.popover = false
8194
}
8295
}
8396
}
@@ -134,11 +147,16 @@ struct TagListView: View {
134147

135148
// MARK: - 태그 전체 리스트 뷰
136149
private struct EllipsisButtonView: View {
150+
@EnvironmentObject private var tagViewModel: TagViewModel
137151
let namespace: Namespace.ID
152+
138153
var body: some View {
139154
VStack(spacing: 0) {
140155
Button {
141-
156+
withAnimation {
157+
tagViewModel.isEditMode = true
158+
tagViewModel.popover = false
159+
}
142160
} label: {
143161
HStack {
144162
Text("태그 목록 편집")
@@ -178,7 +196,8 @@ private struct EllipsisButtonView: View {
178196
.background(
179197
RoundedRectangle(cornerRadius: 10)
180198
.fill(.gray100)
181-
.shadow(color: Color(hex: "#3C3D4B").opacity(0.08), radius: 12, x: 0, y: 0)
199+
.shadow(color: Color(hex: "#3C3D4B").opacity(0.08),
200+
radius: 12, x: 0, y: 0)
182201
)
183202
.padding(.trailing, 70)
184203
.matchedGeometryEffect(id: "popover",

Presentation/Home/TagSearch/TagViewModel.swift

+7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Combine
1212
class TagViewModel: ObservableObject {
1313

1414
private let tagViewUseCase: TagViewUseCase
15+
// MARK: - [부리] tags에 사용자가 만든 태그들 다 저장
1516
@Published public var tags: [TemporaryTag] = []
1617
@Published public var selectedTags: [String] = [] {
1718
didSet {
@@ -20,6 +21,8 @@ class TagViewModel: ObservableObject {
2021
}
2122
@Published public private(set) var isTagExist: Bool = false
2223
@Published public var isTagSelected: Bool = false
24+
@Published public var isEditMode: Bool = false
25+
@Published public var popover: Bool = false
2326
private var cancellables = Set<AnyCancellable>()
2427

2528
init(
@@ -47,4 +50,8 @@ class TagViewModel: ObservableObject {
4750
selectedTags.append(tagName)
4851
}
4952
}
53+
54+
func deleteTag(id: UUID) {
55+
tags.removeAll { $0.id == id }
56+
}
5057
}

0 commit comments

Comments
 (0)