diff --git a/Projects/App/Resources/Pokit-info.plist b/Projects/App/Resources/Pokit-info.plist index ab1b69d0..716b5cdb 100644 --- a/Projects/App/Resources/Pokit-info.plist +++ b/Projects/App/Resources/Pokit-info.plist @@ -21,7 +21,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0.5 + 1.0.6 CFBundleURLTypes diff --git a/Projects/App/Sources/MainTab/MainTabPath.swift b/Projects/App/Sources/MainTab/MainTabPath.swift index 09714197..695295d1 100644 --- a/Projects/App/Sources/MainTab/MainTabPath.swift +++ b/Projects/App/Sources/MainTab/MainTabPath.swift @@ -216,7 +216,7 @@ public extension MainTabFeature { ), title: content.title, data: content.data, - memo: content.memo, + memo: content.memo ?? "", createdAt: content.createdAt, favorites: nil, alertYn: .no diff --git a/Projects/CoreKit/Sources/Data/DTO/Base/ContentBaseResponse.swift b/Projects/CoreKit/Sources/Data/DTO/Base/ContentBaseResponse.swift index df8e5fc8..2568b90a 100644 --- a/Projects/CoreKit/Sources/Data/DTO/Base/ContentBaseResponse.swift +++ b/Projects/CoreKit/Sources/Data/DTO/Base/ContentBaseResponse.swift @@ -13,9 +13,11 @@ public struct ContentBaseResponse: Decodable { public let data: String public let domain: String public let title: String + public let memo: String? public let thumbNail: String public let createdAt: String public let isRead: Bool? + public let isFavorite: Bool? } extension ContentBaseResponse { @@ -29,9 +31,11 @@ extension ContentBaseResponse { data: "https://www.youtube.com/watch?v=wtSwdGJzQCQ", domain: "youtube", title: "신서유기", + memo: nil, thumbNail: "https://i.ytimg.com/vi/NnOC4_kH0ok/hqdefault.jpg?sqp=-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE=&rs=AOn4CLDN6u6mTjbaVmRZ4biJS_aDq4uvAQ", createdAt: "2024.08.08", - isRead: false + isRead: false, + isFavorite: true ) } } diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_allcheck.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_allcheck.imageset/Contents.json new file mode 100644 index 00000000..810a7d79 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_allcheck.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_allcheck.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_allcheck.imageset/icon_allcheck.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_allcheck.imageset/icon_allcheck.svg new file mode 100644 index 00000000..375a1345 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_allcheck.imageset/icon_allcheck.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_alluncheck.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_alluncheck.imageset/Contents.json new file mode 100644 index 00000000..170c3b31 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_alluncheck.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_alluncheck.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_alluncheck.imageset/icon_alluncheck.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_alluncheck.imageset/icon_alluncheck.svg new file mode 100644 index 00000000..d038a9b5 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_alluncheck.imageset/icon_alluncheck.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_arrow-down2.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_arrow-down2.imageset/Contents.json new file mode 100644 index 00000000..6a687d92 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_arrow-down2.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_arrow-down2.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_arrow-down2.imageset/icon_arrow-down2.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_arrow-down2.imageset/icon_arrow-down2.svg new file mode 100644 index 00000000..7ec97e97 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_arrow-down2.imageset/icon_arrow-down2.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_hashtag.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_hashtag.imageset/Contents.json new file mode 100644 index 00000000..20663e8f --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_hashtag.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_hashtag.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_hashtag.imageset/icon_hashtag.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_hashtag.imageset/icon_hashtag.svg new file mode 100644 index 00000000..50a28eb8 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_hashtag.imageset/icon_hashtag.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_invite.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_invite.imageset/Contents.json new file mode 100644 index 00000000..4dc49364 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_invite.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_invite.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_invite.imageset/icon_invite.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_invite.imageset/icon_invite.svg new file mode 100644 index 00000000..d7b7dc78 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_invite.imageset/icon_invite.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_lock.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_lock.imageset/Contents.json new file mode 100644 index 00000000..75bc547f --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_lock.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_lock.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_lock.imageset/icon_lock.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_lock.imageset/icon_lock.svg new file mode 100644 index 00000000..2bf0bfdd --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_lock.imageset/icon_lock.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_member.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_member.imageset/Contents.json new file mode 100644 index 00000000..ff4a10cb --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_member.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_member.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_member.imageset/icon_member.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_member.imageset/icon_member.svg new file mode 100644 index 00000000..6e8af029 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_member.imageset/icon_member.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_memo.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_memo.imageset/Contents.json new file mode 100644 index 00000000..94632333 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_memo.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_memo.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_memo.imageset/icon_memo.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_memo.imageset/icon_memo.svg new file mode 100644 index 00000000..6c891dbc --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_memo.imageset/icon_memo.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_movepokit.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_movepokit.imageset/Contents.json new file mode 100644 index 00000000..2108e930 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_movepokit.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_movepokit.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_movepokit.imageset/icon_movepokit.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_movepokit.imageset/icon_movepokit.svg new file mode 100644 index 00000000..259a08c2 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_movepokit.imageset/icon_movepokit.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_pin.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_pin.imageset/Contents.json new file mode 100644 index 00000000..2046ad44 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_pin.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_pin.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_pin.imageset/icon_pin.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_pin.imageset/icon_pin.svg new file mode 100644 index 00000000..a36bb254 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_pin.imageset/icon_pin.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_report.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_report.imageset/Contents.json new file mode 100644 index 00000000..5c65fb7f --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_report.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_report.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_report.imageset/icon_report.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_report.imageset/icon_report.svg new file mode 100644 index 00000000..8067621f --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_report.imageset/icon_report.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_savepokit.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_savepokit.imageset/Contents.json new file mode 100644 index 00000000..59b65b24 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_savepokit.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_savepokit.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_savepokit.imageset/icon_savepokit.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_savepokit.imageset/icon_savepokit.svg new file mode 100644 index 00000000..39691b8a --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_savepokit.imageset/icon_savepokit.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_xs.imageset/Contents.json b/Projects/DSKit/Resources/Assets.xcassets/icon_xs.imageset/Contents.json new file mode 100644 index 00000000..40dd0b71 --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_xs.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "icon_xs.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Projects/DSKit/Resources/Assets.xcassets/icon_xs.imageset/icon_xs.svg b/Projects/DSKit/Resources/Assets.xcassets/icon_xs.imageset/icon_xs.svg new file mode 100644 index 00000000..3b3a4d1e --- /dev/null +++ b/Projects/DSKit/Resources/Assets.xcassets/icon_xs.imageset/icon_xs.svg @@ -0,0 +1,3 @@ + + + diff --git a/Projects/DSKit/Sources/Components/PoKitIconRButton.swift b/Projects/DSKit/Sources/Components/PoKitIconRButton.swift index 0e42b772..7483ea0c 100644 --- a/Projects/DSKit/Sources/Components/PoKitIconRButton.swift +++ b/Projects/DSKit/Sources/Components/PoKitIconRButton.swift @@ -50,8 +50,8 @@ public struct PokitIconRButton: View { .frame(width: self.size.iconSize.width, height: self.size.iconSize.height) .foregroundStyle(self.state.iconColor) } - .padding(.leading, self.lPadding) - .padding(.trailing, self.tPadding) + .padding(.leading, self.size.hPadding + 4) + .padding(.trailing, self.size.hPadding) .padding(.vertical, self.size.vPadding) .background { RoundedRectangle(cornerRadius: shape.radius(size: self.size), style: .continuous) @@ -61,27 +61,6 @@ public struct PokitIconRButton: View { .stroke(self.state.backgroundStrokeColor, lineWidth: 1) } } - } - - private var tPadding: CGFloat { - switch self.size { - case .small: - return 8 - case .medium: - return 16 - case .large: - return 20 - } - } - - private var lPadding: CGFloat { - switch self.size { - case .small: - return 12 - case .medium: - return 20 - case .large: - return 24 - } + .frame(minWidth: self.size.minWidth) } } diff --git a/Projects/DSKit/Sources/Components/PokitBadge.swift b/Projects/DSKit/Sources/Components/PokitBadge.swift index 4afa8ab3..a535b046 100644 --- a/Projects/DSKit/Sources/Components/PokitBadge.swift +++ b/Projects/DSKit/Sources/Components/PokitBadge.swift @@ -8,32 +8,21 @@ import SwiftUI public struct PokitBadge: View { - private let labelText: String private let state: PokitBadge.State - public init( - _ labelText: String, - state: PokitBadge.State - ) { - self.labelText = labelText + public init(state: PokitBadge.State) { self.state = state } public var body: some View { - Text(labelText) - .pokitFont(.l4) - .foregroundStyle( - state == .unCategorized ? .pokit(.text(.secondary)) : .pokit(.text(.tertiary)) - ) - .padding(.horizontal, state == .small ? 4 : 8) - .padding(.vertical, state == .small ? 2 : 4) + label .background { RoundedRectangle(cornerRadius: 4, style: .continuous) .fill(backgroundColor) .overlay { if state == .unRead { RoundedRectangle(cornerRadius: 4, style: .continuous) - .stroke(.pokit(.border(.tertiary)), lineWidth: 1) + .stroke(.pokit(.border(.brand)), lineWidth: 1) } } } @@ -41,18 +30,79 @@ public struct PokitBadge: View { private var backgroundColor: Color { switch self.state { - case .default, .small: return .pokit(.bg(.primary)) + case .default, .small, .memo, .member: return .pokit(.bg(.primary)) case .unCategorized: return .pokit(.color(.grayScale(._50))) case .unRead: return .pokit(.bg(.base)) } } + + private var labelColor: Color { + switch self.state { + case .default, .small: return .pokit(.text(.tertiary)) + case .unCategorized: return .pokit(.text(.secondary)) + case .unRead: return .pokit(.text(.brand)) + case .memo, .member: return .pokit(.icon(.secondary)) + } + } + + private var label: some View { + Group { + switch self.state { + case let .default(labelText): + Text(labelText) + .pokitFont(.l4) + .padding(.horizontal, 8) + .padding(.vertical, 4) + case let .small(labelText): + Text(labelText) + .pokitFont(.l4) + .padding(.horizontal, 4) + .padding(.vertical, 2) + case .unCategorized: + Text("미분류") + .pokitFont(.l4) + .padding(.horizontal, 8) + .padding(.vertical, 4) + case .unRead: + Text("안읽음") + .pokitFont(.l4) + .padding(.horizontal, 8) + .padding(.vertical, 4) + case .memo: + Image(.icon(.memo)) + .resizable() + .frame(width: 16, height: 16) + .padding(2) + case .member: + Image(.icon(.member)) + .resizable() + .frame(width: 16, height: 16) + .padding(2) + } + } + .foregroundStyle(labelColor) + } } public extension PokitBadge { - enum State { - case `default` - case small + enum State: Equatable { + case `default`(String) + case small(String) case unCategorized case unRead + case memo + case member } } + +#Preview { + PokitBadge(state: .unRead) + + PokitBadge(state: .default("포킷명")) + + PokitBadge(state: .unCategorized) + + PokitBadge(state: .memo) + + PokitBadge(state: .member) +} diff --git a/Projects/DSKit/Sources/Components/PokitBookmark.swift b/Projects/DSKit/Sources/Components/PokitBookmark.swift new file mode 100644 index 00000000..609602bf --- /dev/null +++ b/Projects/DSKit/Sources/Components/PokitBookmark.swift @@ -0,0 +1,71 @@ +// +// PokitBookmark.swift +// DSKit +// +// Created by 김도형 on 11/28/24. +// + +import SwiftUI + +public struct PokitBookmark: View { + private let state: PokitBookmark.State + private let action: () -> Void + + public init( + state: PokitBookmark.State, + action: @escaping () -> Void + ) { + self.state = state + self.action = action + } + + public var body: some View { + Button(action: action) { + Image(.icon(.starFill)) + .resizable() + .frame(width: 24, height: 24) + .foregroundStyle(starColor) + .padding(4) + .background { + RoundedRectangle( + cornerRadius: 9999, + style: .continuous + ) + .fill(backgroundColor) + } + } + .disabled(state == .disable) + } + + private var starColor: Color { + switch state { + case .default, .disable: + return .pokit(.icon(.disable)) + case .active: + return .pokit(.icon(.brand)) + } + } + + private var backgroundColor: Color { + switch state { + case .default, .active: + return .pokit(.bg(.baseIcon)) + case .disable: + return .pokit(.bg(.disable)) + } + } +} + +extension PokitBookmark { + public enum State { + case `default` + case active + case disable + } +} + +#Preview { + PokitBookmark(state: .active) { + + } +} diff --git a/Projects/DSKit/Sources/Components/PokitIconLButton.swift b/Projects/DSKit/Sources/Components/PokitIconLButton.swift index 340e5a2f..0cc803f1 100644 --- a/Projects/DSKit/Sources/Components/PokitIconLButton.swift +++ b/Projects/DSKit/Sources/Components/PokitIconLButton.swift @@ -49,8 +49,8 @@ public struct PokitIconLButton: View { .pokitFont(self.size.font) .foregroundStyle(self.state.textColor) } - .padding(.leading, self.lPadding) - .padding(.trailing, self.tPadding) + .padding(.leading, self.size.hPadding) + .padding(.trailing, self.size.hPadding + 4) .padding(.vertical, self.size.vPadding) .background { RoundedRectangle(cornerRadius: shape.radius(size: self.size), style: .continuous) @@ -60,27 +60,6 @@ public struct PokitIconLButton: View { .stroke(self.state.backgroundStrokeColor, lineWidth: 1) } } - } - - private var lPadding: CGFloat { - switch self.size { - case .small: - return 8 - case .medium: - return 16 - case .large: - return 20 - } - } - - private var tPadding: CGFloat { - switch self.size { - case .small: - return 12 - case .medium: - return 20 - case .large: - return 24 - } + .frame(minWidth: self.size.minWidth) } } diff --git a/Projects/DSKit/Sources/Components/PokitLinkCard.swift b/Projects/DSKit/Sources/Components/PokitLinkCard.swift index a3d5a5be..ccfa53c3 100644 --- a/Projects/DSKit/Sources/Components/PokitLinkCard.swift +++ b/Projects/DSKit/Sources/Components/PokitLinkCard.swift @@ -12,25 +12,48 @@ import NukeUI public struct PokitLinkCard: View { private let link: Item + private let state: PokitLinkCard.State + private let type: PokitLinkCard.CardType private let action: () -> Void private let kebabAction: (() -> Void)? private let fetchMetaData: (() -> Void)? + private let favoriteAction: (() -> Void)? + private let selectAction: (() -> Void)? public init( link: Item, + state: PokitLinkCard.State, + type: PokitLinkCard.CardType = .accept, action: @escaping () -> Void, kebabAction: (() -> Void)? = nil, - fetchMetaData: (() -> Void)? = nil + fetchMetaData: (() -> Void)? = nil, + favoriteAction: (() -> Void)? = nil, + selectAction: (() -> Void)? = nil ) { self.link = link + self.state = state + self.type = type self.action = action self.kebabAction = kebabAction self.fetchMetaData = fetchMetaData + self.favoriteAction = favoriteAction + self.selectAction = selectAction } public var body: some View { - Button(action: action) { - buttonLabel + VStack(spacing: 20) { + Button(action: action) { + buttonLabel + } + .padding(.top, state == .top ? 0 : 20) + + if case .top = state { + divider + } + + if case .middle = state { + divider + } } } @@ -68,6 +91,27 @@ public struct PokitLinkCard: View { } } } + .overlay(alignment: .bottomLeading) { + if let isFavorite = link.isFavorite { + PokitBookmark( + state: isFavorite ? .active : .default, + action: { favoriteAction?() } + ) + .padding(4) + } + } + .overlay(alignment: .topLeading) { + if case .unCatgorized(let isSelected) = type { + PokitCheckBox( + baseState: .default, + selectedState: .filled, + isSelected: .constant(isSelected), + shape: .rectangle, + action: { selectAction?() } + ) + .padding(4) + } + } } private var title: some View { @@ -90,13 +134,18 @@ public struct PokitLinkCard: View { let isUnCategorized = link.categoryName == "미분류" HStack(spacing: 6) { + if let isRead = link.isRead, !isRead { + PokitBadge(state: .unRead) + } + PokitBadge( - link.categoryName, - state: isUnCategorized ? .unCategorized : .default + state: isUnCategorized + ? .unCategorized + : .default(link.categoryName) ) - if let isRead = link.isRead, !isRead { - PokitBadge("안읽음", state: .unRead) + if let memo = link.memo, !memo.isEmpty { + PokitBadge(state: .memo) } } } @@ -149,17 +198,18 @@ public struct PokitLinkCard: View { .frame(width: 124, height: 94) .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous)) } +} + +extension PokitLinkCard { + public enum State { + case top + case middle + case bottom + } - @ViewBuilder - public func divider(isFirst: Bool, isLast: Bool) -> some View { - let edge: Edge.Set = isFirst ? .bottom : isLast ? .top : .vertical - - self - .padding(edge, 20) - .background(alignment: .bottom) { - if !isLast { - divider - } - } + public enum CardType { + case linkList + case unCatgorized(isSelected: Bool) + case accept } } diff --git a/Projects/DSKit/Sources/Components/PokitLinkPopup.swift b/Projects/DSKit/Sources/Components/PokitLinkPopup.swift index 37c4167f..cf11a534 100644 --- a/Projects/DSKit/Sources/Components/PokitLinkPopup.swift +++ b/Projects/DSKit/Sources/Components/PokitLinkPopup.swift @@ -37,14 +37,7 @@ public struct PokitLinkPopup: View { ZStack { background - Group { - switch self.type { - case let .link(url): - linkPopup(url) - case .text: - textPopup - } - } + popup .padding(.vertical, 12) .padding(.horizontal, 20) } @@ -59,44 +52,38 @@ public struct PokitLinkPopup: View { } } - @ViewBuilder - private func linkPopup(_ url: String) -> some View { - HStack { + private var popup: some View { + HStack(spacing: 0) { Button { action?() } label: { VStack(alignment: .leading, spacing: 0) { Text(titleKey) - .lineLimit(1) + .lineLimit(2) .pokitFont(.b2(.b)) .multilineTextAlignment(.leading) - .foregroundStyle(.pokit(.text(.inverseWh))) + .foregroundStyle( + type == .warning + ? .pokit(.text(.primary)) + : .pokit(.text(.inverseWh)) + ) - Text(url) - .lineLimit(1) - .pokitFont(.detail2) - .foregroundStyle(.pokit(.text(.inverseWh))) + if case .link(let url) = type { + Text(url) + .lineLimit(1) + .pokitFont(.detail2) + .foregroundStyle(.pokit(.text(.inverseWh))) + } } - Spacer(minLength: 72) - } - - closeButton - } - } - - private var textPopup: some View { - HStack { - Button { - action?() - } label: { - Text(titleKey) - .lineLimit(2) - .pokitFont(.b3(.b)) - .multilineTextAlignment(.leading) - .foregroundStyle(.pokit(.text(.inverseWh))) + if case .success = type { + Image(.icon(.check)) + .resizable() + .frame(width: 24, height: 24) + .foregroundStyle(.pokit(.icon(.inverseWh))) + } - Spacer(minLength: 54) + Spacer(minLength: 72) } closeButton @@ -105,7 +92,7 @@ public struct PokitLinkPopup: View { private var background: some View { RoundedRectangle(cornerRadius: 9999, style: .continuous) - .fill(.pokit(.bg(.tertiary))) + .fill(backgroundColor) } private var closeButton: some View { @@ -113,7 +100,11 @@ public struct PokitLinkPopup: View { Image(.icon(.x)) .resizable() .frame(width: 24, height: 24) - .foregroundStyle(.pokit(.icon(.inverseWh))) + .foregroundStyle( + type == .warning + ? .pokit(.icon(.primary)) + : .pokit(.icon(.inverseWh)) + ) } } @@ -123,12 +114,28 @@ public struct PokitLinkPopup: View { isPresented = false } } + + private var backgroundColor: Color { + switch type { + case .link, .text: + return .pokit(.bg(.tertiary)) + case .success: + return .pokit(.bg(.success)) + case .error: + return .pokit(.bg(.error)) + case .warning: + return .pokit(.bg(.warning)) + } + } } public extension PokitLinkPopup { - enum PopupType { + enum PopupType: Equatable { case link(url: String) case text + case success + case error + case warning } } @@ -145,5 +152,23 @@ public extension PokitLinkPopup { isPresented: .constant(true), type: .text ) + + PokitLinkPopup( + "링크저장 완료", + isPresented: .constant(true), + type: .success + ) + + PokitLinkPopup( + "링크저장 실패", + isPresented: .constant(true), + type: .error + ) + + PokitLinkPopup( + "저장공간 부족", + isPresented: .constant(true), + type: .warning + ) } } diff --git a/Projects/DSKit/Sources/Components/PokitLinkPreview.swift b/Projects/DSKit/Sources/Components/PokitLinkPreview.swift index ea17a12c..844619af 100644 --- a/Projects/DSKit/Sources/Components/PokitLinkPreview.swift +++ b/Projects/DSKit/Sources/Components/PokitLinkPreview.swift @@ -13,14 +13,14 @@ public struct PokitLinkPreview: View { @Environment(\.openURL) private var openURL - private let title: String - private let url: String - private let imageURL: String + private let title: String? + private let url: String? + private let imageURL: String? public init( - title: String, - url: String, - imageURL: String + title: String?, + url: String?, + imageURL: String? ) { self.title = title self.url = url @@ -33,22 +33,15 @@ public struct PokitLinkPreview: View { } } - @MainActor + private var buttonLabel: some View { HStack(spacing: 16) { - LazyImage(url: URL(string: imageURL)) { phase in - Group { - if let image = phase.image { - image - .resizable() - .aspectRatio(contentMode: .fill) - } else { - PokitSpinner() - .foregroundStyle(.pokit(.icon(.brand))) - .frame(width: 48, height: 48) - } + Group { + if let url = imageURL { + thumbnail(url: url) + } else { + Color.pokit(.bg(.secondary)) } - .animation(.pokitDissolve, value: phase.image) } .frame(width: 124, height: 108) .clipped() @@ -75,27 +68,74 @@ public struct PokitLinkPreview: View { } } + @MainActor + private func thumbnail(url: String) -> some View { + LazyImage(url: URL(string: url)) { phase in + Group { + if let image = phase.image { + image + .resizable() + .aspectRatio(contentMode: .fill) + } else { + PokitSpinner() + .foregroundStyle(.pokit(.icon(.brand))) + .frame(width: 48, height: 48) + } + } + .animation(.pokitDissolve, value: phase.image) + } + } + @ViewBuilder - private func info(title: String) -> some View { + private func info(title: String?) -> some View { VStack(alignment: .leading, spacing: 8) { - Text(title) - .pokitFont(.b3(.b)) - .foregroundStyle(.pokit(.text(.secondary))) - .multilineTextAlignment(.leading) - .lineLimit(2) + if let title { + Text(title) + .pokitFont(.b3(.b)) + .foregroundStyle(.pokit(.text(.secondary))) + .multilineTextAlignment(.leading) + .lineLimit(2) + } else { + placeholder(23) + } - Text(url) - .pokitFont(.detail2) - .foregroundStyle(.pokit(.text(.tertiary))) - .multilineTextAlignment(.leading) - .lineLimit(2) + if let url { + Text(url) + .pokitFont(.detail2) + .foregroundStyle(.pokit(.text(.tertiary))) + .multilineTextAlignment(.leading) + .lineLimit(2) + } else { + placeholder(55) + } } .padding(.vertical, 16) .padding(.trailing, 20) } + @ViewBuilder + private func placeholder(_ tLength: CGFloat) -> some View { + VStack(alignment: .leading, spacing: 2) { + RoundedRectangle(cornerRadius: 2, style: .continuous) + .fill(.pokit(.bg(.secondary))) + .frame(height: 16) + + RoundedRectangle(cornerRadius: 2, style: .continuous) + .fill(.pokit(.bg(.secondary))) + .padding(.trailing, tLength) + .frame(height: 16) + } + } + private func buttonTapped() { - guard let url = URL(string: url) else { return } + guard + let urlString = url, + let url = URL(string: urlString) + else { return } openURL(url) } } + +#Preview { + PokitLinkPreview(title: nil, url: nil, imageURL: nil) +} diff --git a/Projects/DSKit/Sources/Components/PokitList.swift b/Projects/DSKit/Sources/Components/PokitList.swift index c3ca1b6d..04e39fcb 100644 --- a/Projects/DSKit/Sources/Components/PokitList.swift +++ b/Projects/DSKit/Sources/Components/PokitList.swift @@ -8,6 +8,7 @@ import SwiftUI import Util +import NukeUI public struct PokitList: View { @Namespace @@ -15,15 +16,18 @@ public struct PokitList: View { private let selectedItem: Item? private let list: [Item] + private let isDisabled: Bool private let action: (Item) -> Void public init( selectedItem: Item?, list: [Item], + isDisabled: Bool = false, action: @escaping (Item) -> Void ) { self.selectedItem = selectedItem self.list = list + self.isDisabled = isDisabled self.action = action } @@ -54,29 +58,61 @@ public struct PokitList: View { Button { action(item) } label: { - HStack { + HStack(spacing: 12) { + thumbNail(url: item.categoryImage.imageURL) + VStack(alignment: .leading, spacing: 4) { Text(item.categoryName) .pokitFont(.b1(.b)) - .foregroundStyle(.pokit(.text(.primary))) + .foregroundStyle( + isDisabled + ? .pokit(.text(.disable)) + : .pokit(.text(.primary)) + ) Text("링크 \(item.contentCount)개") .pokitFont(.detail1) - .foregroundStyle(.pokit(.text(.tertiary))) + .foregroundStyle( + isDisabled + ? .pokit(.text(.disable)) + : .pokit(.text(.tertiary)) + ) } Spacer() } - .padding(.leading, 28) - .padding(.trailing, 20) - .padding(.vertical, 13) + .padding(.vertical, 18) + .padding(.horizontal, 20) .background { if isSelected { Color.pokit(.bg(.primary)) .matchedGeometryEffect(id: "SELECT", in: heroEffect) + } else { + isDisabled + ? Color.pokit(.bg(.disable)) + : Color.pokit(.bg(.base)) } } } .animation(.pokitDissolve, value: isSelected) + .disabled(isDisabled) + } + + @MainActor + private func thumbNail(url: String) -> some View { + LazyImage(url: URL(string: url)) { state in + Group { + if let image = state.image { + image + .resizable() + } else { + PokitSpinner() + .foregroundStyle(.pokit(.icon(.brand))) + .frame(width: 48, height: 48) + } + } + .animation(.pokitDissolve, value: state.image) + } + .frame(width: 60, height: 60) } } diff --git a/Projects/DSKit/Sources/Components/PokitTextButton.swift b/Projects/DSKit/Sources/Components/PokitTextButton.swift index 5620597b..286ff6f0 100644 --- a/Projects/DSKit/Sources/Components/PokitTextButton.swift +++ b/Projects/DSKit/Sources/Components/PokitTextButton.swift @@ -39,7 +39,7 @@ public struct PokitTextButton: View { Text(self.labelText) .pokitFont(self.size.font) .foregroundStyle(self.state.textColor) - .padding(.horizontal, self.hPadding) + .padding(.horizontal, self.size.hPadding) .padding(.vertical, self.size.vPadding) .background { RoundedRectangle(cornerRadius: shape.radius(size: self.size), style: .continuous) @@ -49,16 +49,6 @@ public struct PokitTextButton: View { .stroke(self.state.backgroundStrokeColor, lineWidth: 1) } } - } - - private var hPadding: CGFloat { - switch self.size { - case .small: - return 12.5 - case .medium: - return 26 - case .large: - return 34.5 - } + .frame(minWidth: self.size.minWidth) } } diff --git a/Projects/DSKit/Sources/Extensions/Color+Extension.swift b/Projects/DSKit/Sources/Extensions/Color+Extension.swift index e63a8d42..503eb67e 100644 --- a/Projects/DSKit/Sources/Extensions/Color+Extension.swift +++ b/Projects/DSKit/Sources/Extensions/Color+Extension.swift @@ -144,7 +144,7 @@ public extension Color { case .bg(let bg): switch bg { case .base: return .pokitColor(.grayScale(.white)) - case .baseIcon: return Color(hue: 0, saturation: 0, brightness: 85, opacity: 0.6) + case .baseIcon: return Color(red: 0.85, green: 0.85, blue: 0.85).opacity(0.6) case .brand: return .pokitColor(.orange(._700)) case .disable: return .pokitColor(.grayScale(._200)) case .error: return .pokitColor(.red(._500)) diff --git a/Projects/DSKit/Sources/Foundation/PokitButtonStyle.swift b/Projects/DSKit/Sources/Foundation/PokitButtonStyle.swift index 647f504c..3c0e7225 100644 --- a/Projects/DSKit/Sources/Foundation/PokitButtonStyle.swift +++ b/Projects/DSKit/Sources/Foundation/PokitButtonStyle.swift @@ -128,6 +128,22 @@ extension PokitButtonStyle.Size { case .large: return 13 } } + + var hPadding: CGFloat { + switch self { + case .small: return 8 + case .medium: return 16 + case .large: return 20 + } + } + + var minWidth: CGFloat { + switch self { + case .small: return 50 + case .medium: return 80 + case .large: return 100 + } + } } extension PokitButtonStyle.Shape { diff --git a/Projects/DSKit/Sources/Foundation/PokitImage.swift b/Projects/DSKit/Sources/Foundation/PokitImage.swift index e83d4aec..16354ee4 100644 --- a/Projects/DSKit/Sources/Foundation/PokitImage.swift +++ b/Projects/DSKit/Sources/Foundation/PokitImage.swift @@ -79,6 +79,30 @@ public enum PokitImage { return DSKitAsset.iconGoogle.swiftUIImage case .spinner: return DSKitAsset.iconSpinner.swiftUIImage + case .invite: + return DSKitAsset.iconInvite.swiftUIImage + case .memo: + return DSKitAsset.iconMemo.swiftUIImage + case .arrowDown2: + return DSKitAsset.iconArrowDown2.swiftUIImage + case .hashtag: + return DSKitAsset.iconHashtag.swiftUIImage + case .savePokit: + return DSKitAsset.iconSavepokit.swiftUIImage + case .pin: + return DSKitAsset.iconPin.swiftUIImage + case .member: + return DSKitAsset.iconMember.swiftUIImage + case .lock: + return DSKitAsset.iconLock.swiftUIImage + case .movePokit: + return DSKitAsset.iconMovepokit.swiftUIImage + case .allCheck: + return DSKitAsset.iconAllcheck.swiftUIImage + case .allUncheck: + return DSKitAsset.iconAlluncheck.swiftUIImage + case .report: + return DSKitAsset.iconReport.swiftUIImage } case .logo(let name): switch name { @@ -138,6 +162,18 @@ public extension PokitImage { case check case google case spinner + case invite + case memo + case arrowDown2 + case hashtag + case savePokit + case pin + case member + case lock + case movePokit + case allCheck + case allUncheck + case report } enum Logo { diff --git a/Projects/Domain/Sources/Base/BaseContentItem.swift b/Projects/Domain/Sources/Base/BaseContentItem.swift index 59c93b12..93861d2d 100644 --- a/Projects/Domain/Sources/Base/BaseContentItem.swift +++ b/Projects/Domain/Sources/Base/BaseContentItem.swift @@ -14,31 +14,37 @@ public struct BaseContentItem: Identifiable, Equatable, PokitLinkCardItem, Sorta public let categoryName: String public let categoryId: Int public let title: String + public let memo: String? public var thumbNail: String public let data: String public let domain: String public let createdAt: String public let isRead: Bool? + public let isFavorite: Bool? public init( id: Int, categoryName: String, categoryId: Int, title: String, + memo: String?, thumbNail: String, data: String, domain: String, createdAt: String, - isRead: Bool? + isRead: Bool?, + isFavorite: Bool? ) { self.id = id self.categoryName = categoryName self.categoryId = categoryId self.title = title + self.memo = memo self.thumbNail = thumbNail self.data = data self.domain = domain self.createdAt = createdAt self.isRead = isRead + self.isFavorite = isFavorite } } diff --git a/Projects/Domain/Sources/CategorySharing/CategorySharing.swift b/Projects/Domain/Sources/CategorySharing/CategorySharing.swift index f60d91aa..da404c8d 100644 --- a/Projects/Domain/Sources/CategorySharing/CategorySharing.swift +++ b/Projects/Domain/Sources/CategorySharing/CategorySharing.swift @@ -63,10 +63,11 @@ extension CategorySharing { public let data: String public let domain: String public let title: String - public let memo: String + public let memo: String? public let thumbNail: String public let createdAt: String public let categoryName: String public let isRead: Bool? = false + public let isFavorite: Bool? = false } } diff --git a/Projects/Domain/Sources/DTO/Base/BaseContentResponse+Extension.swift b/Projects/Domain/Sources/DTO/Base/BaseContentResponse+Extension.swift index d195655e..e67218ed 100644 --- a/Projects/Domain/Sources/DTO/Base/BaseContentResponse+Extension.swift +++ b/Projects/Domain/Sources/DTO/Base/BaseContentResponse+Extension.swift @@ -17,11 +17,13 @@ public extension ContentBaseResponse { categoryName: self.category.categoryName, categoryId: self.category.categoryId, title: self.title, + memo: self.memo, thumbNail: self.thumbNail, data: self.data, domain: self.domain, createdAt: self.createdAt, - isRead: self.isRead + isRead: self.isRead, + isFavorite: self.isFavorite ) } } diff --git a/Projects/Feature/FeatureCategorySharing/Sources/CategorySharing/CategorySharingFeature.swift b/Projects/Feature/FeatureCategorySharing/Sources/CategorySharing/CategorySharingFeature.swift index 9f97170e..7d57eb96 100644 --- a/Projects/Feature/FeatureCategorySharing/Sources/CategorySharing/CategorySharingFeature.swift +++ b/Projects/Feature/FeatureCategorySharing/Sources/CategorySharing/CategorySharingFeature.swift @@ -152,11 +152,13 @@ private extension CategorySharingFeature { categoryName: content.categoryName, categoryId: state.category.categoryId, title: content.title, + memo: content.memo, thumbNail: content.thumbNail, data: content.data, domain: content.domain, createdAt: content.createdAt, - isRead: content.isRead + isRead: content.isRead, + isFavorite: content.isFavorite ))) } state.isLoading = false @@ -176,11 +178,13 @@ private extension CategorySharingFeature { categoryName: content.categoryName, categoryId: state.category.categoryId, title: content.title, + memo: content.memo, thumbNail: content.thumbNail, data: content.data, domain: content.domain, createdAt: content.createdAt, - isRead: content.isRead + isRead: content.isRead, + isFavorite: content.isFavorite ))) } state.isLoading = false diff --git a/Projects/Feature/FeatureContentCard/Sources/ContentCard/ContentCardView.swift b/Projects/Feature/FeatureContentCard/Sources/ContentCard/ContentCardView.swift index 086a4be0..f871f86c 100644 --- a/Projects/Feature/FeatureContentCard/Sources/ContentCard/ContentCardView.swift +++ b/Projects/Feature/FeatureContentCard/Sources/ContentCard/ContentCardView.swift @@ -14,16 +14,19 @@ import DSKit public struct ContentCardView: View { /// - Properties public var store: StoreOf + private let type: PokitLinkCard.CardType private let isFirst: Bool private let isLast: Bool /// - Initializer public init( store: StoreOf, + type: PokitLinkCard.CardType = .accept, isFirst: Bool = false, isLast: Bool = false ) { self.store = store + self.type = type self.isFirst = isFirst self.isLast = isLast } @@ -34,11 +37,14 @@ public extension ContentCardView { WithPerceptionTracking { PokitLinkCard( link: store.content, + state: isFirst + ? .top + : isLast ? .bottom : .middle, + type: type, action: { send(.컨텐츠_항목_눌렀을때) }, kebabAction: { send(.컨텐츠_항목_케밥_버튼_눌렀을때) }, fetchMetaData: { send(.메타데이터_조회) } ) - .divider(isFirst: isFirst, isLast: isLast) } } } @@ -55,11 +61,13 @@ private extension ContentCardView { categoryName: "미분류", categoryId: 992 , title: "youtube", + memo: nil, thumbNail: "https://i.ytimg.com/vi/NnOC4_kH0ok/hqdefault.jpg?sqp=-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE=&rs=AOn4CLDN6u6mTjbaVmRZ4biJS_aDq4uvAQ", data: "https://www.youtube.com/watch?v=wtSwdGJzQCQ", domain: "신서유기", createdAt: "2024.08.08", - isRead: false + isRead: false, + isFavorite: true )), reducer: { ContentCardFeature() } ) diff --git a/Projects/Feature/FeatureContentDetail/Sources/ContentDetail/ContentDetailView.swift b/Projects/Feature/FeatureContentDetail/Sources/ContentDetail/ContentDetailView.swift index c049946f..6cbca8ea 100644 --- a/Projects/Feature/FeatureContentDetail/Sources/ContentDetail/ContentDetailView.swift +++ b/Projects/Feature/FeatureContentDetail/Sources/ContentDetail/ContentDetailView.swift @@ -90,7 +90,7 @@ private extension ContentDetailView { } } - PokitBadge(content.category.categoryName, state: .default) + PokitBadge(state: .default(content.category.categoryName)) Spacer() } diff --git a/Projects/Feature/FeatureRemind/Sources/Remind/RemindView.swift b/Projects/Feature/FeatureRemind/Sources/Remind/RemindView.swift index 98cdf65e..68309559 100644 --- a/Projects/Feature/FeatureRemind/Sources/Remind/RemindView.swift +++ b/Projects/Feature/FeatureRemind/Sources/Remind/RemindView.swift @@ -156,7 +156,7 @@ extension RemindView { ) VStack(alignment: .leading, spacing: 0) { - PokitBadge(content.categoryName, state: .small) + PokitBadge(state: .small(content.categoryName)) HStack(spacing: 4) { Text(content.title) @@ -258,16 +258,18 @@ extension RemindView { } ForEach(unreadContents, id: \.id) { content in - let isFirst = content == unreadContents.elements.first - let isLast = content == unreadContents.elements.last + let isFirst = content.id == unreadContents.first?.id + let isLast = content.id == unreadContents.last?.id PokitLinkCard( link: content, + state: isFirst + ? .top + : isLast ? .bottom : .middle, action: { send(.컨텐츠_항목_눌렀을때(content: content)) }, kebabAction: { send(.컨텐츠_항목_케밥_버튼_눌렀을때(content: content)) }, fetchMetaData: { send(.읽지않음_항목_이미지_조회(contentId: content.id)) } ) - .divider(isFirst: isFirst, isLast: isLast) } } } @@ -289,16 +291,18 @@ extension RemindView { .padding(.top, 16) } else { ForEach(favoriteContents, id: \.id) { content in - let isFirst = content == favoriteContents.elements.first - let isLast = content == favoriteContents.elements.last + let isFirst = content.id == favoriteContents.first?.id + let isLast = content.id == favoriteContents.last?.id PokitLinkCard( link: content, + state: isFirst + ? .top + : isLast ? .bottom : .middle, action: { send(.컨텐츠_항목_눌렀을때(content: content)) }, kebabAction: { send(.컨텐츠_항목_케밥_버튼_눌렀을때(content: content)) }, fetchMetaData: { send(.즐겨찾기_항목_이미지_조회(contentId: content.id)) } ) - .divider(isFirst: isFirst, isLast: isLast) } } } diff --git a/Projects/Util/Sources/Protocols/PokitLinkCardItem.swift b/Projects/Util/Sources/Protocols/PokitLinkCardItem.swift index 84d08d43..4f65156e 100644 --- a/Projects/Util/Sources/Protocols/PokitLinkCardItem.swift +++ b/Projects/Util/Sources/Protocols/PokitLinkCardItem.swift @@ -9,10 +9,12 @@ import Foundation public protocol PokitLinkCardItem { var title: String { get } + var memo: String? { get } var thumbNail: String { get } var createdAt: String { get } var categoryName: String { get } var isRead: Bool? { get } var data: String { get } var domain: String { get } + var isFavorite: Bool? { get } } diff --git a/Projects/Util/Sources/Protocols/PokitSelectItem.swift b/Projects/Util/Sources/Protocols/PokitSelectItem.swift index e9767209..0fbec838 100644 --- a/Projects/Util/Sources/Protocols/PokitSelectItem.swift +++ b/Projects/Util/Sources/Protocols/PokitSelectItem.swift @@ -8,6 +8,9 @@ import Foundation public protocol PokitSelectItem: Identifiable, Equatable { + associatedtype Thumbnail: CategoryImage + var categoryName: String { get } var contentCount: Int { get } + var categoryImage: Thumbnail { get } }