From 7d1e3abef732f5f44dc7ea6f3c4763d5128bf47b Mon Sep 17 00:00:00 2001 From: Martin Lasek Date: Mon, 21 Oct 2024 10:59:06 -0700 Subject: [PATCH 1/6] updated dependency --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 1d7fc58..bf6b154 100644 --- a/Package.swift +++ b/Package.swift @@ -11,7 +11,7 @@ let package = Package( .library(name: "WishKit", targets: ["WishKit"]) ], dependencies: [ - .package(url: "https://github.com/wishkit/wishkit-ios-shared.git", exact: "1.4.3") + .package(url: "https://github.com/wishkit/wishkit-ios-shared.git", exact: "1.5.0") ], targets: [ .target(name: "WishKit", dependencies: [ From 5c462dc8af2c3131e0acfc12e2025c970152fd84 Mon Sep 17 00:00:00 2001 From: Martin Lasek Date: Mon, 21 Oct 2024 13:28:18 -0700 Subject: [PATCH 2/6] new filter for feedback list supporting new states --- .../WishKit/Configuration+Localization.swift | 24 ++++++++- Sources/WishKit/Model/WishModel.swift | 49 ++++++++++++------- Sources/WishKit/SwiftUI/SegmentedView.swift | 16 ++++-- Sources/WishKit/SwiftUI/WishView.swift | 6 ++- .../iOS+Catalyst/WishlistView+iOS.swift | 48 ++++++++++++++---- 5 files changed, 107 insertions(+), 36 deletions(-) diff --git a/Sources/WishKit/Configuration+Localization.swift b/Sources/WishKit/Configuration+Localization.swift index 9214b61..92c778a 100644 --- a/Sources/WishKit/Configuration+Localization.swift +++ b/Sources/WishKit/Configuration+Localization.swift @@ -18,6 +18,14 @@ extension Configuration { public var implemented: String + public var inReview: String + + public var planned: String + + public var inProgress: String + + public var completed: String + public var wishlist: String public var save: String @@ -97,6 +105,10 @@ extension Configuration { pending: String = Localization.default().pending, approved: String = Localization.default().approved, implemented: String = Localization.default().implemented, + inReview: String = Localization.default().inReview, + planned: String = Localization.default().planned, + inProgress: String = Localization.default().inProgress, + completed: String = Localization.default().completed, wishlist: String = Localization.default().wishlist, save: String = Localization.default().save, title: String = Localization.default().title, @@ -139,6 +151,10 @@ extension Configuration { self.pending = pending self.approved = approved self.implemented = implemented + self.inReview = inReview + self.planned = planned + self.inProgress = inProgress + self.completed = completed self.wishlist = wishlist self.save = save self.title = title @@ -182,8 +198,12 @@ extension Configuration { Localization( requested: "Requested", pending: "Pending", - approved: "Approved", - implemented: "Implemented", + approved: "In Review", + implemented: "Completed", + inReview: "In Review", + planned: "Planned", + inProgress: "In Progress", + completed: "Completed", wishlist: "Feature Requests", save: "Save", title: "Title", diff --git a/Sources/WishKit/Model/WishModel.swift b/Sources/WishKit/Model/WishModel.swift index a3b9fa7..2027fde 100644 --- a/Sources/WishKit/Model/WishModel.swift +++ b/Sources/WishKit/Model/WishModel.swift @@ -14,11 +14,31 @@ import SwiftUI final class WishModel: ObservableObject { @Published + @available(*, deprecated, message: "Use `inReviewList` instead.") var approvedWishlist: [WishResponse] = [] @Published + @available(*, deprecated, message: "Use `completedList` instead.") var implementedWishlist: [WishResponse] = [] + @Published + var pendingList: [WishResponse] = [] + + @Published + var inReviewList: [WishResponse] = [] + + @Published + var plannedList: [WishResponse] = [] + + @Published + var inProgressList: [WishResponse] = [] + + @Published + var completedList: [WishResponse] = [] + + @Published + var fullList: [WishResponse] = [] + @Published var shouldShowWatermark: Bool = false @@ -38,9 +58,9 @@ final class WishModel: ObservableObject { case .success(let response): DispatchQueue.main.async { withAnimation { - self.updateApprovedWishlist(with: response.list) - self.updateImplementedWishlist(with: response.list) + self.updateAllLists(with: response.list) self.shouldShowWatermark = response.shouldShowWatermark + self.fullList = response.list } } case .failure(let error): @@ -61,24 +81,15 @@ final class WishModel: ObservableObject { fetchList(completion: nil) } - private func updateApprovedWishlist(with list: [WishResponse]) { - let userUUID = UUIDManager.getUUID() - - var filteredList = list.filter { wish in - let ownPendingWish = (wish.state == .pending && wish.userUUID == userUUID) - let approvedWish = wish.state == .approved + private func updateAllLists(with list: [WishResponse]) { + let sortedList = list.sorted { $0.votingUsers.count > $1.votingUsers.count } - return ownPendingWish || approvedWish - } - - filteredList.sort { $0.votingUsers.count > $1.votingUsers.count } - - self.approvedWishlist = filteredList - } + self.pendingList = sortedList.filter { wish in wish.state == .pending && wish.userUUID == UUIDManager.getUUID() } + self.inReviewList = sortedList.filter { wish in wish.state == .inReview || wish.state == .approved } + self.plannedList = sortedList.filter { wish in wish.state == .planned } + self.inProgressList = sortedList.filter { wish in wish.state == .inProgress } + self.completedList = sortedList.filter { wish in wish.state == .completed || wish.state == .implemented} - private func updateImplementedWishlist(with list: [WishResponse]) { - var filteredList = list.filter { wish in wish.state == .implemented } - filteredList.sort { $0.votingUsers.count > $1.votingUsers.count } - self.implementedWishlist = filteredList + self.implementedWishlist = sortedList } } diff --git a/Sources/WishKit/SwiftUI/SegmentedView.swift b/Sources/WishKit/SwiftUI/SegmentedView.swift index 90f2871..c905f52 100644 --- a/Sources/WishKit/SwiftUI/SegmentedView.swift +++ b/Sources/WishKit/SwiftUI/SegmentedView.swift @@ -31,13 +31,21 @@ extension WishState: Identifiable { public var description: String { switch self { case .approved: - return WishKit.config.localization.approved + WishKit.config.localization.approved case .implemented: - return WishKit.config.localization.implemented + WishKit.config.localization.implemented case .pending: - return WishKit.config.localization.pending + WishKit.config.localization.pending + case .inReview: + WishKit.config.localization.inReview + case .planned: + WishKit.config.localization.planned + case .inProgress: + WishKit.config.localization.inProgress + case .completed: + WishKit.config.localization.completed default: - return "" + "Not Supported" } } } diff --git a/Sources/WishKit/SwiftUI/WishView.swift b/Sources/WishKit/SwiftUI/WishView.swift index baa79cd..c14c4f6 100644 --- a/Sources/WishKit/SwiftUI/WishView.swift +++ b/Sources/WishKit/SwiftUI/WishView.swift @@ -130,7 +130,7 @@ struct WishView: View { @unknown default: return WishKit.theme.badgeColor.pending.light } - case .approved: + case .inReview, .approved: switch colorScheme { case .light: return WishKit.theme.badgeColor.approved.light @@ -139,7 +139,7 @@ struct WishView: View { @unknown default: return WishKit.theme.badgeColor.approved.light } - case .implemented: + case .completed, .implemented: switch colorScheme { case .light: return WishKit.theme.badgeColor.implemented.light @@ -157,6 +157,8 @@ struct WishView: View { @unknown default: return WishKit.theme.badgeColor.rejected.light } + default: + return WishKit.theme.badgeColor.rejected.light } } diff --git a/Sources/WishKit/SwiftUI/iOS+Catalyst/WishlistView+iOS.swift b/Sources/WishKit/SwiftUI/iOS+Catalyst/WishlistView+iOS.swift index 1c5001f..adbd6ab 100644 --- a/Sources/WishKit/SwiftUI/iOS+Catalyst/WishlistView+iOS.swift +++ b/Sources/WishKit/SwiftUI/iOS+Catalyst/WishlistView+iOS.swift @@ -28,7 +28,7 @@ struct WishlistViewIOS: View { private var colorScheme @State - private var selectedWishState: WishState = .approved + private var selectedWishState: WishState = .inReview @ObservedObject var wishModel: WishModel @@ -66,17 +66,44 @@ struct WishlistViewIOS: View { } } + private var feedbackStateSelection: [WishState] { + return [.pending, .inReview, .planned, .inProgress, .completed] + } + private func getList() -> [WishResponse] { switch selectedWishState { - case .approved: - return wishModel.approvedWishlist - case .implemented: - return wishModel.implementedWishlist - default: + case .pending: + return wishModel.pendingList + case .inReview, .approved: + return wishModel.inReviewList + case .planned: + return wishModel.plannedList + case .inProgress: + return wishModel.inProgressList + case .completed, .implemented: + return wishModel.completedList + case .rejected: return [] } } + private func getCountFor(state: WishState) -> Int { + switch state { + case .pending: + return wishModel.pendingList.count + case .inReview, .approved: + return wishModel.inReviewList.count + case .planned: + return wishModel.plannedList.count + case .inProgress: + return wishModel.inProgressList.count + case .completed, .implemented: + return wishModel.completedList.count + case .rejected: + return 0 + } + } + var body: some View { ZStack { @@ -86,7 +113,7 @@ struct WishlistViewIOS: View { } if wishModel.hasFetched && !wishModel.isLoading && getList().isEmpty { - Text(WishKit.config.localization.noFeatureRequests) + Text("\(selectedWishState.description): \(WishKit.config.localization.noFeatureRequests)") } ScrollView { @@ -95,8 +122,11 @@ struct WishlistViewIOS: View { if WishKit.config.buttons.segmentedControl.display == .show { Spacer(minLength: 15) - SegmentedView(selectedWishState: $selectedWishState) - .frame(maxWidth: 200) + Picker("", selection: $selectedWishState) { + ForEach(feedbackStateSelection) { state in + Text("\(state.description) (\(getCountFor(state: state)))") + } + } } Spacer(minLength: 15) From 8bb95160d48f80d60d8cbe3a073bacd5d5f24896 Mon Sep 17 00:00:00 2001 From: Martin Lasek Date: Sun, 27 Oct 2024 00:18:05 -0700 Subject: [PATCH 3/6] added color for planned, inReview and inProgress and complete --- Sources/WishKit/SwiftUI/WishView.swift | 56 +++++++++++++++++++++----- Sources/WishKit/Theme.swift | 39 +++++++++++++++--- 2 files changed, 81 insertions(+), 14 deletions(-) diff --git a/Sources/WishKit/SwiftUI/WishView.swift b/Sources/WishKit/SwiftUI/WishView.swift index c14c4f6..119860e 100644 --- a/Sources/WishKit/SwiftUI/WishView.swift +++ b/Sources/WishKit/SwiftUI/WishView.swift @@ -121,6 +121,25 @@ struct WishView: View { func badgeColor(for wishState: WishState) -> Color { switch wishState { + case .approved: + switch colorScheme { + case .light: + return WishKit.theme.badgeColor.approved.light + case .dark: + return WishKit.theme.badgeColor.approved.dark + @unknown default: + return WishKit.theme.badgeColor.approved.light + } + case .implemented: + switch colorScheme { + case .light: + return WishKit.theme.badgeColor.implemented.light + case .dark: + return WishKit.theme.badgeColor.implemented.dark + @unknown default: + return WishKit.theme.badgeColor.implemented.light + } + case .pending: switch colorScheme { case .light: @@ -130,23 +149,42 @@ struct WishView: View { @unknown default: return WishKit.theme.badgeColor.pending.light } - case .inReview, .approved: + case .inReview: switch colorScheme { case .light: - return WishKit.theme.badgeColor.approved.light + return WishKit.theme.badgeColor.inReview.light case .dark: - return WishKit.theme.badgeColor.approved.dark + return WishKit.theme.badgeColor.inReview.dark @unknown default: - return WishKit.theme.badgeColor.approved.light + return WishKit.theme.badgeColor.inReview.light + } + case .planned: + switch colorScheme { + case .light: + return WishKit.theme.badgeColor.planned.light + case .dark: + return WishKit.theme.badgeColor.planned.dark + @unknown default: + return WishKit.theme.badgeColor.planned.light } - case .completed, .implemented: + case .inProgress: switch colorScheme { case .light: - return WishKit.theme.badgeColor.implemented.light + return WishKit.theme.badgeColor.inProgress.light case .dark: - return WishKit.theme.badgeColor.implemented.dark + return WishKit.theme.badgeColor.inProgress.dark @unknown default: - return WishKit.theme.badgeColor.implemented.light + return WishKit.theme.badgeColor.inProgress.light + } + + case .completed: + switch colorScheme { + case .light: + return WishKit.theme.badgeColor.completed.light + case .dark: + return WishKit.theme.badgeColor.completed.dark + @unknown default: + return WishKit.theme.badgeColor.completed.light } case .rejected: switch colorScheme { @@ -158,7 +196,7 @@ struct WishView: View { return WishKit.theme.badgeColor.rejected.light } default: - return WishKit.theme.badgeColor.rejected.light + return .black } } diff --git a/Sources/WishKit/Theme.swift b/Sources/WishKit/Theme.swift index 0e79439..2159c6a 100644 --- a/Sources/WishKit/Theme.swift +++ b/Sources/WishKit/Theme.swift @@ -68,26 +68,55 @@ struct PrivateTheme { extension Theme { public struct BadgeTheme { - public var pending: Scheme - + @available(*, deprecated, renamed: "inReview") public var approved: Scheme + @available(*, deprecated, renamed: "completed") public var implemented: Scheme + public var pending: Scheme + + public var inReview: Scheme + + public var planned: Scheme + + public var inProgress: Scheme + + public var completed: Scheme + public var rejected: Scheme - init(pending: Scheme, approved: Scheme, implemented: Scheme, rejected: Scheme) { - self.pending = pending + init( + approved: Scheme, + implemented: Scheme, + pending: Scheme, + inReview: Scheme, + planned: Scheme, + inProgress: Scheme, + completed: Scheme, + rejected: Scheme + ) { self.approved = approved self.implemented = implemented + + self.pending = pending + self.inReview = inReview + self.planned = planned + self.inProgress = inProgress + self.completed = completed self.rejected = rejected } static func `default`() -> BadgeTheme { return BadgeTheme( - pending: .setBoth(to: .yellow), approved: .setBoth(to: .blue), implemented: .setBoth(to: .green), + + pending: .setBoth(to: .yellow), + inReview: .setBoth(to: Color(red: 0, green: 251, blue: 255)), + planned: .setBoth(to: .purple), + inProgress: .setBoth(to: .blue), + completed: .setBoth(to: .green), rejected: .setBoth(to: .red) ) } From 547cdf62db59a1d0454638daa5ff7776929c1674 Mon Sep 17 00:00:00 2001 From: Martin Lasek Date: Sun, 27 Oct 2024 11:14:21 -0700 Subject: [PATCH 4/6] added dropdown filter fot states for macos/visionos --- ...View.swift => WishState+Description.swift} | 16 -------- Sources/WishKit/SwiftUI/WishlistView.swift | 20 +++++++--- .../macOS/WishlistContainer+macOS.swift | 38 ++++++++++++++++--- Sources/WishKit/Theme.swift | 2 +- 4 files changed, 48 insertions(+), 28 deletions(-) rename Sources/WishKit/SwiftUI/{SegmentedView.swift => WishState+Description.swift} (67%) diff --git a/Sources/WishKit/SwiftUI/SegmentedView.swift b/Sources/WishKit/SwiftUI/WishState+Description.swift similarity index 67% rename from Sources/WishKit/SwiftUI/SegmentedView.swift rename to Sources/WishKit/SwiftUI/WishState+Description.swift index c905f52..0cbaa3b 100644 --- a/Sources/WishKit/SwiftUI/SegmentedView.swift +++ b/Sources/WishKit/SwiftUI/WishState+Description.swift @@ -9,22 +9,6 @@ import SwiftUI import WishKitShared -struct SegmentedView: View { - - @Binding - var selectedWishState: WishState - - var body: some View { - if WishKit.config.buttons.segmentedControl.display == .show { - Picker("", selection: $selectedWishState) { - ForEach([WishState.approved, WishState.implemented]) { state in - Text(state.description) - } - }.pickerStyle(.segmented) - } - } -} - extension WishState: Identifiable { public var id: Self { self } diff --git a/Sources/WishKit/SwiftUI/WishlistView.swift b/Sources/WishKit/SwiftUI/WishlistView.swift index 6509ad3..b002cf1 100644 --- a/Sources/WishKit/SwiftUI/WishlistView.swift +++ b/Sources/WishKit/SwiftUI/WishlistView.swift @@ -20,7 +20,7 @@ struct WishlistView: View { @State var showingCreateSheet = false - + @State var selectedWish: WishResponse? = nil @@ -30,11 +30,21 @@ struct WishlistView: View { func getList() -> [WishResponse] { switch listType { case .approved: - return wishModel.approvedWishlist + wishModel.approvedWishlist case .implemented: - return wishModel.implementedWishlist - default: - return [] + wishModel.implementedWishlist + case .pending: + wishModel.pendingList + case .inReview: + wishModel.inReviewList + case .planned: + wishModel.plannedList + case .inProgress: + wishModel.inProgressList + case .completed: + wishModel.completedList + case .rejected: + [] } } diff --git a/Sources/WishKit/SwiftUI/macOS/WishlistContainer+macOS.swift b/Sources/WishKit/SwiftUI/macOS/WishlistContainer+macOS.swift index 3209b2d..207130a 100644 --- a/Sources/WishKit/SwiftUI/macOS/WishlistContainer+macOS.swift +++ b/Sources/WishKit/SwiftUI/macOS/WishlistContainer+macOS.swift @@ -16,7 +16,7 @@ struct WishlistContainer: View { private var colorScheme @State - private var listType: WishState = .approved + private var listType: WishState = .inReview @State private var isRefreshing = false @@ -56,14 +56,40 @@ struct WishlistContainer: View { }.background(systemBackgroundColor) } + private var feedbackStateSelection: [WishState] { + return [.pending, .inReview, .planned, .inProgress, .completed] + } + + private func getCountFor(state: WishState) -> Int { + switch state { + case .pending: + return wishModel.pendingList.count + case .inReview, .approved: + return wishModel.inReviewList.count + case .planned: + return wishModel.plannedList.count + case .inProgress: + return wishModel.inProgressList.count + case .completed, .implemented: + return wishModel.completedList.count + case .rejected: + return 0 + } + } + var segmentedControlView: some View { HStack { - SegmentedView(selectedWishState: $listType) - .padding(.leading, 5) - .frame(maxWidth: 300) + + if WishKit.config.buttons.segmentedControl.display == .show { + Picker("", selection: $listType) { + ForEach(feedbackStateSelection) { state in + Text("\(state.description) (\(getCountFor(state: state)))") + } + }.frame(maxWidth: 150) + } Spacer() - + Button(action: refreshList) { if isRefreshing { Text(WishKit.config.localization.refreshing) @@ -86,7 +112,7 @@ struct WishlistContainer: View { .background(systemBackgroundColor) } } - }.padding(EdgeInsets(top: 15, leading: 5, bottom: 15, trailing: 15)) + }.padding(EdgeInsets(top: 15, leading: 15, bottom: 15, trailing: 20)) } var noSegmentedControlView: some View { diff --git a/Sources/WishKit/Theme.swift b/Sources/WishKit/Theme.swift index 2159c6a..d3ed7be 100644 --- a/Sources/WishKit/Theme.swift +++ b/Sources/WishKit/Theme.swift @@ -113,7 +113,7 @@ extension Theme { implemented: .setBoth(to: .green), pending: .setBoth(to: .yellow), - inReview: .setBoth(to: Color(red: 0, green: 251, blue: 255)), + inReview: .setBoth(to: Color(red: 1/255, green: 255/255, blue: 255/255)), planned: .setBoth(to: .purple), inProgress: .setBoth(to: .blue), completed: .setBoth(to: .green), From 3724cc98d58d5fb0ccf1c63011acf7c171960ef9 Mon Sep 17 00:00:00 2001 From: Martin Lasek Date: Sun, 27 Oct 2024 11:51:32 -0700 Subject: [PATCH 5/6] bumped up sdk version --- Sources/WishKit/ProjectSettings.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WishKit/ProjectSettings.swift b/Sources/WishKit/ProjectSettings.swift index 2acbb78..b9edf2c 100644 --- a/Sources/WishKit/ProjectSettings.swift +++ b/Sources/WishKit/ProjectSettings.swift @@ -13,5 +13,5 @@ struct ProjectSettings { let wishKitUrl = ProcessInfo.processInfo.environment["wishkit-url"] return wishKitUrl ?? "https://www.wishkit.io/api" } - static let sdkVersion = "4.5.0" + static let sdkVersion = "4.6.0" } From ee5baf6c3ad147f7b07145f0eb4c12c0236b0ed1 Mon Sep 17 00:00:00 2001 From: Martin Lasek Date: Sun, 27 Oct 2024 11:55:29 -0700 Subject: [PATCH 6/6] fixed code formatting --- Sources/WishKit/SwiftUI/WishView.swift | 16 ++++++++-------- Sources/WishKit/SwiftUI/WishlistView.swift | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Sources/WishKit/SwiftUI/WishView.swift b/Sources/WishKit/SwiftUI/WishView.swift index 119860e..4dc221d 100644 --- a/Sources/WishKit/SwiftUI/WishView.swift +++ b/Sources/WishKit/SwiftUI/WishView.swift @@ -131,14 +131,14 @@ struct WishView: View { return WishKit.theme.badgeColor.approved.light } case .implemented: - switch colorScheme { - case .light: - return WishKit.theme.badgeColor.implemented.light - case .dark: - return WishKit.theme.badgeColor.implemented.dark - @unknown default: - return WishKit.theme.badgeColor.implemented.light - } + switch colorScheme { + case .light: + return WishKit.theme.badgeColor.implemented.light + case .dark: + return WishKit.theme.badgeColor.implemented.dark + @unknown default: + return WishKit.theme.badgeColor.implemented.light + } case .pending: switch colorScheme { diff --git a/Sources/WishKit/SwiftUI/WishlistView.swift b/Sources/WishKit/SwiftUI/WishlistView.swift index b002cf1..cc6b4e7 100644 --- a/Sources/WishKit/SwiftUI/WishlistView.swift +++ b/Sources/WishKit/SwiftUI/WishlistView.swift @@ -20,7 +20,7 @@ struct WishlistView: View { @State var showingCreateSheet = false - + @State var selectedWish: WishResponse? = nil