From c69e2cda1adabba1ed1e97e0d373a8f131e2b838 Mon Sep 17 00:00:00 2001 From: Arturo Carretero Calvo <10163049+ArtCC@users.noreply.github.com> Date: Wed, 29 Oct 2025 21:26:51 +0100 Subject: [PATCH 1/2] Update Votice SDK version to 1.0.17 and reflect changes in configuration manager and tests - Bump Votice SDK package version from 1.0.16 to 1.0.17 in README.md - Update ConfigurationManager version property to "1.0.17" - Modify ConfigurationManagerTests to expect version "1.0.17" instead of "1.0.16" in all relevant assertions no message --- README.md | 2 +- Sources/Votice/Core/Managers/ConfigurationManager.swift | 2 +- Tests/VoticeTests/Managers/ConfigurationManagerTests.swift | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f8e6351..22ed2fa 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ The Votice management app for handling suggestions or issues and apps is availab Add this line to your `Package.swift` dependencies: ```swift -.package(url: "https://github.com/artcc/votice-sdk", from: "1.0.16"), +.package(url: "https://github.com/artcc/votice-sdk", from: "1.0.17"), ``` Or via Xcode: diff --git a/Sources/Votice/Core/Managers/ConfigurationManager.swift b/Sources/Votice/Core/Managers/ConfigurationManager.swift index 3acf427..9a0c534 100644 --- a/Sources/Votice/Core/Managers/ConfigurationManager.swift +++ b/Sources/Votice/Core/Managers/ConfigurationManager.swift @@ -49,7 +49,7 @@ final class ConfigurationManager: ConfigurationManagerProtocol, @unchecked Senda private let lock = NSLock() private let _baseURL = "https://api.votice.app/api" private let _configurationId = UUID().uuidString - private let _version = "1.0.16" + private let _version = "1.0.17" private let _buildNumber = "1" // MARK: - Public properties diff --git a/Tests/VoticeTests/Managers/ConfigurationManagerTests.swift b/Tests/VoticeTests/Managers/ConfigurationManagerTests.swift index 788b424..5294625 100644 --- a/Tests/VoticeTests/Managers/ConfigurationManagerTests.swift +++ b/Tests/VoticeTests/Managers/ConfigurationManagerTests.swift @@ -32,7 +32,7 @@ struct ConfigurationManagerTests { #expect(manager.showCompletedSeparately == false) #expect(manager.user.isPremium == false) #expect(manager.optionalVisibleStatuses == [.accepted, .blocked, .rejected]) - #expect(manager.version == "1.0.16") + #expect(manager.version == "1.0.17") #expect(manager.buildNumber == "1") } @@ -138,7 +138,7 @@ struct ConfigurationManagerTests { // ConfigurationId, version, and buildNumber should remain unchanged #expect(!manager.configurationId.isEmpty) - #expect(manager.version == "1.0.16") + #expect(manager.version == "1.0.17") #expect(manager.buildNumber == "1") } @@ -325,7 +325,7 @@ struct ConfigurationManagerTests { // Test immutable properties #expect(manager.baseURL == "https://api.votice.app/api") - #expect(manager.version == "1.0.16") + #expect(manager.version == "1.0.17") #expect(manager.buildNumber == "1") // Configuration ID should be consistent for same instance From 70d462a61cf480efeea4b9bf9cba19e44caa7071 Mon Sep 17 00:00:00 2001 From: Arturo Carretero Calvo <10163049+ArtCC@users.noreply.github.com> Date: Sun, 2 Nov 2025 10:59:36 +0100 Subject: [PATCH 2/2] Refactor VoticeDemo project structure and add configurable UI dimensions - Rename Assets.xcassets and Info.plist to be under a new Resources group in the Xcode project - Update Info.plist file type to text.plist.xml in project file - Change INFOPLIST_FILE paths to point to Resources/Info.plist in project settings - Adjust macOS App window minimum width from 1200 to 1280 in AppVoticeDemo.swift - Modify View extension to remove opacity from Circle fill color - Add width and height properties with thread-safe access to ConfigurationManager - Initialize width and height to 800x600 in ConfigurationManager reset method - Add optional progress property to SuggestionEntity model and update initializers and copy method - Replace fixed frame widths in SuggestionDetailView+tvOS and SuggestionListView+tvOS with ConfigurationManager width and height - Replace fixed frame sizes in SuggestionListView macOS views with ConfigurationManager width and height - Remove tvOS support warning comments from Votice.swift - Change feedbackNavigationView and feedbackView methods to accept width and height parameters instead of minWidth and minHeight - Update internal open method to use width and height parameters, enforce minimums of 800x600, set ConfigurationManager dimensions, and apply frame size accordingly --- .../VoticeDemo.xcodeproj/project.pbxproj | 18 +++++-- .../AccentColor.colorset/Contents.json | 0 .../Assets.xcassets/Contents.json | 0 .../brand.colorset/Contents.json | 0 .../VoticeDemo/{ => Resources}/Info.plist | 0 .../VoticeDemo/Shared/App/AppVoticeDemo.swift | 2 +- Sources/Votice/Core/Extensions/View.swift | 2 +- .../Core/Managers/ConfigurationManager.swift | 22 +++++++++ .../Votice/Core/Models/SuggestionEntity.swift | 5 ++ .../SuggestionDetailView+tvOS.swift | 2 +- .../SuggestionListView+tvOS.swift | 2 +- .../SuggestionList/SuggestionListView.swift | 4 +- Sources/Votice/Votice.swift | 49 +++++++++---------- 13 files changed, 69 insertions(+), 37 deletions(-) rename Example/VoticeDemo/VoticeDemo/{ => Resources}/Assets.xcassets/AccentColor.colorset/Contents.json (100%) rename Example/VoticeDemo/VoticeDemo/{ => Resources}/Assets.xcassets/Contents.json (100%) rename Example/VoticeDemo/VoticeDemo/{ => Resources}/Assets.xcassets/brand.colorset/Contents.json (100%) rename Example/VoticeDemo/VoticeDemo/{ => Resources}/Info.plist (100%) diff --git a/Example/VoticeDemo/VoticeDemo.xcodeproj/project.pbxproj b/Example/VoticeDemo/VoticeDemo.xcodeproj/project.pbxproj index 9c4a42f..9d244b7 100644 --- a/Example/VoticeDemo/VoticeDemo.xcodeproj/project.pbxproj +++ b/Example/VoticeDemo/VoticeDemo.xcodeproj/project.pbxproj @@ -86,7 +86,7 @@ 802F7E8B2E0F1A2500F1BDF6 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; 802F7E8C2E0F1A2500F1BDF6 /* AppVoticeDemo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVoticeDemo.swift; sourceTree = ""; }; 8055AAC42EB0AB6300FF6DAE /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = ""; }; - 805C23CB2E19684E00AB56D0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 805C23CB2E19684E00AB56D0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 805C23CC2E19685B00AB56D0 /* VoticeDemo-macOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "VoticeDemo-macOS-Info.plist"; sourceTree = SOURCE_ROOT; }; 805C23CD2E19686400AB56D0 /* VoticeDemo-tvOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "VoticeDemo-tvOS-Info.plist"; sourceTree = SOURCE_ROOT; }; 805C23CF2E1968CC00AB56D0 /* Poppins-Black.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-Black.ttf"; sourceTree = ""; }; @@ -194,8 +194,7 @@ 802F7E8D2E0F1A2500F1BDF6 /* VoticeDemo */ = { isa = PBXGroup; children = ( - 802F7E8A2E0F1A2500F1BDF6 /* Assets.xcassets */, - 805C23CB2E19684E00AB56D0 /* Info.plist */, + 808BBED02EB7621800262E3E /* Resources */, 805C23CE2E1968BD00AB56D0 /* Shared */, ); path = VoticeDemo; @@ -258,6 +257,15 @@ path = App; sourceTree = ""; }; + 808BBED02EB7621800262E3E /* Resources */ = { + isa = PBXGroup; + children = ( + 802F7E8A2E0F1A2500F1BDF6 /* Assets.xcassets */, + 805C23CB2E19684E00AB56D0 /* Info.plist */, + ); + path = Resources; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -808,7 +816,7 @@ ENABLE_PREVIEWS = YES; ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = VoticeDemo/Info.plist; + INFOPLIST_FILE = VoticeDemo/Resources/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = VoticeDemo; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -842,7 +850,7 @@ ENABLE_PREVIEWS = YES; ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = VoticeDemo/Info.plist; + INFOPLIST_FILE = VoticeDemo/Resources/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = VoticeDemo; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; diff --git a/Example/VoticeDemo/VoticeDemo/Assets.xcassets/AccentColor.colorset/Contents.json b/Example/VoticeDemo/VoticeDemo/Resources/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from Example/VoticeDemo/VoticeDemo/Assets.xcassets/AccentColor.colorset/Contents.json rename to Example/VoticeDemo/VoticeDemo/Resources/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/Example/VoticeDemo/VoticeDemo/Assets.xcassets/Contents.json b/Example/VoticeDemo/VoticeDemo/Resources/Assets.xcassets/Contents.json similarity index 100% rename from Example/VoticeDemo/VoticeDemo/Assets.xcassets/Contents.json rename to Example/VoticeDemo/VoticeDemo/Resources/Assets.xcassets/Contents.json diff --git a/Example/VoticeDemo/VoticeDemo/Assets.xcassets/brand.colorset/Contents.json b/Example/VoticeDemo/VoticeDemo/Resources/Assets.xcassets/brand.colorset/Contents.json similarity index 100% rename from Example/VoticeDemo/VoticeDemo/Assets.xcassets/brand.colorset/Contents.json rename to Example/VoticeDemo/VoticeDemo/Resources/Assets.xcassets/brand.colorset/Contents.json diff --git a/Example/VoticeDemo/VoticeDemo/Info.plist b/Example/VoticeDemo/VoticeDemo/Resources/Info.plist similarity index 100% rename from Example/VoticeDemo/VoticeDemo/Info.plist rename to Example/VoticeDemo/VoticeDemo/Resources/Info.plist diff --git a/Example/VoticeDemo/VoticeDemo/Shared/App/AppVoticeDemo.swift b/Example/VoticeDemo/VoticeDemo/Shared/App/AppVoticeDemo.swift index 18a0942..0a76642 100644 --- a/Example/VoticeDemo/VoticeDemo/Shared/App/AppVoticeDemo.swift +++ b/Example/VoticeDemo/VoticeDemo/Shared/App/AppVoticeDemo.swift @@ -16,7 +16,7 @@ struct AppVoticeDemo: App { WindowGroup { HomeView() #if os(macOS) - .frame(minWidth: 1200, minHeight: 720) + .frame(minWidth: 1280, minHeight: 720) #endif } } diff --git a/Sources/Votice/Core/Extensions/View.swift b/Sources/Votice/Core/Extensions/View.swift index 74dc512..0c9dc52 100644 --- a/Sources/Votice/Core/Extensions/View.swift +++ b/Sources/Votice/Core/Extensions/View.swift @@ -153,7 +153,7 @@ extension View { #if !os(tvOS) self.background { Circle() - .fill(fillColor.opacity(0.75)) + .fill(fillColor) .glassEffect( isInteractive ? .regular.interactive() : .regular, in: .circle diff --git a/Sources/Votice/Core/Managers/ConfigurationManager.swift b/Sources/Votice/Core/Managers/ConfigurationManager.swift index 9a0c534..a99185f 100644 --- a/Sources/Votice/Core/Managers/ConfigurationManager.swift +++ b/Sources/Votice/Core/Managers/ConfigurationManager.swift @@ -45,6 +45,8 @@ final class ConfigurationManager: ConfigurationManagerProtocol, @unchecked Senda private var _useLiquidGlass = true private var _user = UserEntity(isPremium: false) private var _optionalVisibleStatuses: Set = [.accepted, .blocked, .rejected] + private var _width: CGFloat = 800 + private var _height: CGFloat = 600 private let lock = NSLock() private let _baseURL = "https://api.votice.app/api" @@ -120,6 +122,24 @@ final class ConfigurationManager: ConfigurationManagerProtocol, @unchecked Senda } } + var width: CGFloat { + get { + lock.withLock { _width } + } + set { + lock.withLock { _width = newValue } + } + } + + var height: CGFloat { + get { + lock.withLock { _height } + } + set { + lock.withLock { _height = newValue } + } + } + var version: String { _version } @@ -221,6 +241,8 @@ final class ConfigurationManager: ConfigurationManagerProtocol, @unchecked Senda _showCompletedSeparately = false _useLiquidGlass = false _optionalVisibleStatuses = [.accepted, .blocked, .rejected] + _width = 800 + _height = 600 LogManager.shared.devLog(.info, "ConfigurationManager: reset") } diff --git a/Sources/Votice/Core/Models/SuggestionEntity.swift b/Sources/Votice/Core/Models/SuggestionEntity.swift index d4269bf..e4687d1 100644 --- a/Sources/Votice/Core/Models/SuggestionEntity.swift +++ b/Sources/Votice/Core/Models/SuggestionEntity.swift @@ -25,6 +25,7 @@ public struct SuggestionEntity: Codable, Equatable, Identifiable, Sendable { public let createdBy: String? public let deviceId: String? public let status: SuggestionStatusEntity? + public let progress: Int? public let source: SuggestionSource? public let voteCount: Int? public let language: String? @@ -47,6 +48,7 @@ public struct SuggestionEntity: Codable, Equatable, Identifiable, Sendable { createdBy: String? = nil, deviceId: String? = nil, status: SuggestionStatusEntity? = nil, + progress: Int? = nil, source: SuggestionSource? = nil, commentCount: Int? = nil, voteCount: Int? = nil, @@ -67,6 +69,7 @@ public struct SuggestionEntity: Codable, Equatable, Identifiable, Sendable { self.createdBy = createdBy self.deviceId = deviceId self.status = status + self.progress = progress self.source = source self.commentCount = commentCount self.voteCount = voteCount @@ -108,6 +111,7 @@ extension SuggestionEntity { createdBy: String? = nil, deviceId: String? = nil, status: SuggestionStatusEntity? = nil, + progress: Int? = nil, source: SuggestionSource? = nil, commentCount: Int? = nil, voteCount: Int? = nil, @@ -129,6 +133,7 @@ extension SuggestionEntity { createdBy: createdBy ?? self.createdBy, deviceId: deviceId ?? self.deviceId, status: status ?? self.status, + progress: progress ?? self.progress, source: source ?? self.source, commentCount: commentCount ?? self.commentCount, voteCount: voteCount ?? self.voteCount, diff --git a/Sources/Votice/UI/Views/SuggestionDetail/SuggestionDetailView+tvOS.swift b/Sources/Votice/UI/Views/SuggestionDetail/SuggestionDetailView+tvOS.swift index d76a6f1..374a179 100644 --- a/Sources/Votice/UI/Views/SuggestionDetail/SuggestionDetailView+tvOS.swift +++ b/Sources/Votice/UI/Views/SuggestionDetail/SuggestionDetailView+tvOS.swift @@ -36,7 +36,7 @@ extension SuggestionDetailView { .padding(.horizontal, 20) Color.clear.focusable(true) } - .frame(width: 1250) + .frame(width: ConfigurationManager.shared.width, height: ConfigurationManager.shared.height) .background( LinearGradient( colors: [ diff --git a/Sources/Votice/UI/Views/SuggestionList/SuggestionListView+tvOS.swift b/Sources/Votice/UI/Views/SuggestionList/SuggestionListView+tvOS.swift index 339b68c..be463fd 100644 --- a/Sources/Votice/UI/Views/SuggestionList/SuggestionListView+tvOS.swift +++ b/Sources/Votice/UI/Views/SuggestionList/SuggestionListView+tvOS.swift @@ -31,7 +31,7 @@ extension SuggestionListView { } } } - .frame(width: 1250) + .frame(width: ConfigurationManager.shared.width, height: ConfigurationManager.shared.height) .task { await viewModel.loadSuggestions() } diff --git a/Sources/Votice/UI/Views/SuggestionList/SuggestionListView.swift b/Sources/Votice/UI/Views/SuggestionList/SuggestionListView.swift index 53cdcdd..f76b4a0 100644 --- a/Sources/Votice/UI/Views/SuggestionList/SuggestionListView.swift +++ b/Sources/Votice/UI/Views/SuggestionList/SuggestionListView.swift @@ -99,7 +99,7 @@ private extension SuggestionListView { viewModel.addSuggestion(suggestion) } #if os(macOS) - .frame(minWidth: 800, minHeight: 600) + .frame(width: ConfigurationManager.shared.width, height: ConfigurationManager.shared.height) #endif } } @@ -113,7 +113,7 @@ private extension SuggestionListView { } } #if os(macOS) - .frame(minWidth: 800, minHeight: 600) + .frame(width: ConfigurationManager.shared.width, height: ConfigurationManager.shared.height) #endif } } diff --git a/Sources/Votice/Votice.swift b/Sources/Votice/Votice.swift index fb872dd..1f6455d 100644 --- a/Sources/Votice/Votice.swift +++ b/Sources/Votice/Votice.swift @@ -9,12 +9,6 @@ import Foundation import SwiftUI -// swiftlint:disable line_length -#if os(tvOS) -#warning("Votice SDK is currently only supported on iOS, iPadOS and macOS. Support for tvOS will be available in future releases.") -#endif -// swiftlint:enable line_length - // MARK: - Configuration public struct Votice { @@ -118,35 +112,35 @@ extension Votice { /// Present the Votice feedback interface /// - Parameters: /// - theme: Custom theme for the UI (optional) - /// - minWidth: Minimum width for macOS (default 800) - /// - minHeight: Minimum height for macOS (default 600) + /// - width: width for macOS (default 800) + /// - height: height for macOS (default 600) /// - Returns: A SwiftUI View that can be presented modally or embedded public static func feedbackNavigationView( theme: VoticeTheme? = nil, - minWidth: CGFloat = 800, - minHeight: CGFloat = 600 + width: CGFloat = 800, + height: CGFloat = 600 ) -> some View { - open(isNavigation: true, theme: theme, minWidth: minWidth, minHeight: minHeight) + open(isNavigation: true, theme: theme, width: width, height: height) } /// Present the Votice feedback interface as a standalone view /// - Parameters: /// - theme: Custom theme for the UI (optional) - /// - minWidth: Minimum width for macOS (default 800) - /// - minHeight: Minimum height for macOS (default 600) + /// - width: width for macOS (default 800) + /// - height: height for macOS (default 600) /// - Returns: A SwiftUI View that can be used in any context /// - Note: This view is suitable for embedding in your app's UI or presenting as a full-screen cover public static func feedbackView( theme: VoticeTheme? = nil, - minWidth: CGFloat = 800, - minHeight: CGFloat = 600 + width: CGFloat = 800, + height: CGFloat = 600 ) -> some View { #if os(iOS) || os(macOS) NavigationStack { - open(isNavigation: false, theme: theme, minWidth: minWidth, minHeight: minHeight) + open(isNavigation: false, theme: theme, width: width, height: height) } #elseif os(tvOS) - open(isNavigation: false, theme: theme, minWidth: minWidth, minHeight: minHeight) + open(isNavigation: false, theme: theme, width: width, height: height) #endif } } @@ -165,11 +159,7 @@ extension Votice { surfaceColor: Color? = nil ) -> VoticeTheme { // Use smart defaults if no colors are provided - createAdvancedTheme( - primaryColor: primaryColor, - backgroundColor: backgroundColor, - surfaceColor: surfaceColor - ) + createAdvancedTheme(primaryColor: primaryColor, backgroundColor: backgroundColor, surfaceColor: surfaceColor) } /// Get a system theme that automatically adapts to the user's appearance preference @@ -387,13 +377,20 @@ private extension Votice { static func open( isNavigation: Bool, theme: VoticeTheme? = nil, - minWidth: CGFloat = 800, - minHeight: CGFloat = 600 + width: CGFloat = 800, + height: CGFloat = 600 ) -> some View { - SuggestionListView(isNavigation: isNavigation) + let widthValue = max(width, 800) + let heightValue = max(height, 600) + + return SuggestionListView(isNavigation: isNavigation) .voticeTheme(theme ?? .default) + .task { + ConfigurationManager.shared.width = widthValue + ConfigurationManager.shared.height = heightValue + } #if os(macOS) || os(tvOS) - .frame(minWidth: minWidth, minHeight: minHeight) + .frame(width: widthValue, height: heightValue) #endif } }