|
7 | 7 |
|
8 | 8 | import SwiftUI |
9 | 9 |
|
| 10 | +public enum ArchiveFooterStyle { |
| 11 | + case detail // 사진 상세 화면 (즐겨찾기, 메모 아이콘) |
| 12 | + case selection // 사진 선택 화면 (다운로드, 복제, 이동, 삭제 + 텍스트) |
| 13 | +} |
| 14 | + |
10 | 15 | struct ArchiveImageFooter: View { |
11 | 16 |
|
12 | 17 | // MARK: - Properties |
13 | 18 |
|
14 | | - /// 버튼 활성화 여부 (선택 모드에서는 선택된 아이템 유무, 상세 모드에서는 항상 true) |
15 | | - let isEnabled: Bool |
| 19 | + let style: ArchiveFooterStyle |
16 | 20 |
|
17 | | - /// 즐겨찾기 상태 (nil이면 버튼 숨김) |
| 21 | + /// 버튼 활성화 여부 |
| 22 | + let isEnabled: Bool |
| 23 | + /// 즐겨찾기 상태 (상세 모드 전용) |
18 | 24 | let isFavorite: Bool? |
19 | 25 |
|
| 26 | + // 아이콘 액션 |
20 | 27 | let onDownload: () -> Void |
21 | 28 | let onDelete: () -> Void |
22 | 29 | let onFavorite: (() -> Void)? |
23 | 30 | let onTapMemo: (() -> Void)? |
| 31 | + let onDuplicate: (() -> Void)? |
| 32 | + let onMove: (() -> Void)? |
24 | 33 |
|
25 | 34 | // MARK: - Init |
26 | 35 |
|
27 | 36 | public init( |
| 37 | + style: ArchiveFooterStyle = .detail, |
28 | 38 | isEnabled: Bool = true, |
29 | 39 | isFavorite: Bool? = nil, |
30 | 40 | onDownload: @escaping () -> Void, |
31 | 41 | onDelete: @escaping () -> Void, |
32 | 42 | onFavorite: (() -> Void)? = nil, |
33 | | - onTapMemo: (() -> Void)? = nil |
| 43 | + onTapMemo: (() -> Void)? = nil, |
| 44 | + onDuplicate: (() -> Void)? = nil, |
| 45 | + onMove: (() -> Void)? = nil |
34 | 46 | ) { |
| 47 | + self.style = style |
35 | 48 | self.isEnabled = isEnabled |
36 | 49 | self.isFavorite = isFavorite |
37 | 50 | self.onDownload = onDownload |
38 | 51 | self.onDelete = onDelete |
39 | 52 | self.onFavorite = onFavorite |
40 | 53 | self.onTapMemo = onTapMemo |
| 54 | + self.onDuplicate = onDuplicate |
| 55 | + self.onMove = onMove |
41 | 56 | } |
42 | 57 |
|
43 | 58 | // MARK: - Body |
44 | 59 |
|
45 | 60 | var body: some View { |
| 61 | + if style == .selection { |
| 62 | + selectionModeFooter |
| 63 | + } else { |
| 64 | + detailModeFooter |
| 65 | + } |
| 66 | + } |
| 67 | +} |
| 68 | + |
| 69 | +extension ArchiveImageFooter { |
| 70 | + private var selectionModeFooter: some View { |
| 71 | + HStack(alignment: .center, spacing: 0) { |
| 72 | + selectionButton( |
| 73 | + title: "다운로드", |
| 74 | + icon: Image(isEnabled ? .iconDownloadFill : .iconDownload), |
| 75 | + action: onDownload |
| 76 | + ) |
| 77 | + |
| 78 | + if let onDuplicate = onDuplicate { |
| 79 | + selectionButton( |
| 80 | + title: "사진 복제", |
| 81 | + icon: Image(isEnabled ? .iconDuplicateFill : .iconDuplicate), |
| 82 | + action: onDuplicate |
| 83 | + ) |
| 84 | + } |
| 85 | + |
| 86 | + if let onMove = onMove { |
| 87 | + selectionButton( |
| 88 | + title: "사진 이동", |
| 89 | + icon: Image(isEnabled ? .iconMoveFill : .iconMove), |
| 90 | + action: onMove |
| 91 | + ) |
| 92 | + } |
| 93 | + |
| 94 | + selectionButton( |
| 95 | + title: "삭제", |
| 96 | + icon: Image(isEnabled ? .iconTrashFill : .iconTrash), |
| 97 | + action: onDelete |
| 98 | + ) |
| 99 | + } |
| 100 | + .padding(.top, 8) |
| 101 | + .padding(.bottom, 10) |
| 102 | + .background(.white) |
| 103 | + .overlay( |
| 104 | + Rectangle() |
| 105 | + .frame(height: 1) |
| 106 | + .foregroundColor(.gray75), |
| 107 | + alignment: .top |
| 108 | + ) |
| 109 | + } |
| 110 | + |
| 111 | + // 버튼 공통 뷰 빌더 |
| 112 | + @ViewBuilder |
| 113 | + private func selectionButton(title: String, icon: Image, action: @escaping () -> Void) -> some View { |
| 114 | + Button(action: action) { |
| 115 | + VStack(spacing: 4) { |
| 116 | + icon |
| 117 | + .resizable() |
| 118 | + .aspectRatio(contentMode: .fit) |
| 119 | + .frame(width: 28, height: 28) |
| 120 | + .foregroundStyle(isEnabled ? .gray700 : .gray200) |
| 121 | + |
| 122 | + Text(title) |
| 123 | + .nekiFont(.body14Medium) |
| 124 | + .foregroundStyle(isEnabled ? .gray700 : .gray400) |
| 125 | + |
| 126 | + } |
| 127 | + .frame(maxWidth: .infinity) |
| 128 | + .contentShape(Rectangle()) |
| 129 | + } |
| 130 | + .disabled(!isEnabled) |
| 131 | + } |
| 132 | + |
| 133 | + private var detailModeFooter: some View { |
46 | 134 | HStack(alignment: .center, spacing: 0) { |
47 | 135 | Button(action: onDownload) { |
48 | 136 | Image(isEnabled ? .iconDownloadFill : .iconDownload) |
49 | | - .renderingMode(.template) |
50 | | - .foregroundStyle(isEnabled ? .gray700 : .gray100) |
| 137 | + .foregroundStyle(isEnabled ? .gray700 : .gray200) |
51 | 138 | } |
52 | 139 | .disabled(!isEnabled) |
53 | 140 |
|
54 | 141 | if let isFavorite = isFavorite, let onFavorite = onFavorite { |
55 | 142 | Button(action: onFavorite) { |
56 | 143 | Image(isFavorite ? .iconHeart28Fill : .iconHeart28Gray) |
57 | | - .renderingMode(.template) |
58 | | - .foregroundStyle(isFavorite ? .red : .gray700) |
59 | 144 | } |
60 | 145 | .padding(.leading, 16) |
61 | 146 | } |
|
0 commit comments