diff --git a/.github/workflows/Tests.yml b/.github/workflows/Tests.yml index 20e39ac7..e39d45d7 100644 --- a/.github/workflows/Tests.yml +++ b/.github/workflows/Tests.yml @@ -3,17 +3,18 @@ name: Tests on: push: pull_request: - types: [opened] + types: [opened, synchronize, reopened] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: Tests: - runs-on: macos-13 + runs-on: macos-14-xlarge steps: - - name: Cancel previous jobs - uses: styfle/cancel-workflow-action@0.11.0 - - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Load Latest Xcode uses: maxim-lobanov/setup-xcode@v1 @@ -21,8 +22,8 @@ jobs: xcode-version: latest-stable - name: Build project - run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild build-for-testing -destination 'name=iPhone 14 Pro' -scheme 'PovioKit-Package' | xcpretty + run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild build-for-testing -destination 'name=iPhone 14 Pro' -scheme 'PovioKit-Package' | xcbeautify --renderer github-actions - name: Run tests - run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild test-without-building -destination 'name=iPhone 14 Pro' -scheme 'PovioKit-Package' | xcpretty + run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild test-without-building -destination 'name=iPhone 14 Pro' -scheme 'PovioKit-Package' | xcbeautify --renderer github-actions diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/PovioKit-Package.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/PovioKit-Package.xcscheme index 00992b39..8976f8f0 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/PovioKit-Package.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/PovioKit-Package.xcscheme @@ -146,6 +146,20 @@ ReferencedContainer = "container:"> + + + + + + + + + + + + +Copyright (c) 2024 Povio Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MIGRATING.md b/MIGRATING.md index 46c1d231..6e19cd65 100644 --- a/MIGRATING.md +++ b/MIGRATING.md @@ -1,5 +1,9 @@ ## Migration Guides +### Migration from versions < 4.0.0 +* [Core] If you have used any utilities referencing to PovioKitCore package, you'll need to replace it. They've been moved to PovioKitUtilities. +* [UI] PovioKitUI package has been replaced by PovioKitUIKit and/or PovioKitSwiftUI. Replace depending on the type of UI code you were depending on. + ### Migration from versions < 3.0.0 * [Auth] All Auth products are removed from the PovioKit package and effectivelly moved to a standalone repo https://github.com/poviolabs/PovioKitAuth. In order to continue using Auth products, install the new package `PovioKitAuth` package from the given repo url. diff --git a/Package.resolved b/Package.resolved index 4eaee067..dffa1041 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/Alamofire/Alamofire", "state" : { - "revision" : "3dc6a42c7727c49bf26508e29b0a0b35f9c7e1ad", - "version" : "5.8.1" + "revision" : "f455c2975872ccd2d9c81594c658af65716e9b9a", + "version" : "5.9.1" } } ], diff --git a/Package.swift b/Package.swift index bf5c3182..21b13cf5 100644 --- a/Package.swift +++ b/Package.swift @@ -4,17 +4,43 @@ import PackageDescription let package = Package( name: "PovioKit", platforms: [ - .iOS(.v13) + .iOS(.v13), .macOS(.v13) ], products: [ - .library(name: "PovioKitCore", targets: ["PovioKitCore"]), - .library(name: "PovioKitNetworking", targets: ["PovioKitNetworking"]), - .library(name: "PovioKitPromise", targets: ["PovioKitPromise"]), - .library(name: "PovioKitUI", targets: ["PovioKitUI"]), - .library(name: "PovioKitAsync", targets: ["PovioKitAsync"]), + .library( + name: "PovioKitCore", + targets: ["PovioKitCore"] + ), + .library( + name: "PovioKitUtilities", + targets: ["PovioKitUtilities"] + ), + .library( + name: "PovioKitNetworking", + targets: ["PovioKitNetworking"] + ), + .library( + name: "PovioKitPromise", + targets: ["PovioKitPromise"] + ), + .library( + name: "PovioKitUIKit", + targets: ["PovioKitUIKit"] + ), + .library( + name: "PovioKitSwiftUI", + targets: ["PovioKitSwiftUI"] + ), + .library( + name: "PovioKitAsync", + targets: ["PovioKitAsync"] + ), ], dependencies: [ - .package(url: "https://github.com/Alamofire/Alamofire", .upToNextMajor(from: "5.0.0")) + .package( + url: "https://github.com/Alamofire/Alamofire", + .upToNextMajor(from: "5.0.0") + ) ], targets: [ .target( @@ -25,7 +51,6 @@ let package = Package( .target( name: "PovioKitNetworking", dependencies: [ - "PovioKitCore", "Alamofire", "PovioKitPromise", ], @@ -39,19 +64,35 @@ let package = Package( resources: [.copy("../../Resources/PrivacyInfo.xcprivacy")] ), .target( - name: "PovioKitUI", + name: "PovioKitUIKit", + dependencies: [ + "PovioKitCore", + "PovioKitUtilities", + ], + path: "Sources/UI/UIKit", + resources: [.copy("../../../Resources/PrivacyInfo.xcprivacy")] + ), + .target( + name: "PovioKitSwiftUI", dependencies: [ - "PovioKitCore" + "PovioKitCore", ], - path: "Sources/UI", + path: "Sources/UI/SwiftUI", resources: [.copy("../../../Resources/PrivacyInfo.xcprivacy")] ), .target( - name: "PovioKitAsync", - dependencies: [ - ], - path: "Sources/Async", - resources: [.copy("../../../Resources/PrivacyInfo.xcprivacy")] + name: "PovioKitUtilities", + dependencies: [ + "PovioKitCore", + ], + path: "Sources/Utilities", + resources: [.copy("../../Resources/PrivacyInfo.xcprivacy")] + ), + .target( + name: "PovioKitAsync", + dependencies: [], + path: "Sources/Async", + resources: [.copy("../../Resources/PrivacyInfo.xcprivacy")] ), .testTarget( name: "Tests", @@ -59,7 +100,9 @@ let package = Package( "PovioKitCore", "PovioKitPromise", "PovioKitNetworking", - "PovioKitUI", + "PovioKitUIKit", + "PovioKitSwiftUI", + "PovioKitUtilities", "PovioKitAsync", ] ), diff --git a/README.md b/README.md index 32cc23cc..2dd31156 100644 --- a/README.md +++ b/README.md @@ -23,20 +23,23 @@ ## Packages -| [Core](Resources/Core) | [UI](Resources/UI) | [Networking](Resources/Networking) | [PromiseKit](Resources/PromiseKit) | -| :-: | :-: | :-: | :-: | +| [Core](Resources/Core) | [Networking](Resources/Networking) | [PromiseKit](Resources/PromiseKit) | [Utilities](Resources/Utilities) | [Async](Resources/Async) | [UIKit](Resources/UI/UIKit) | [SwiftUI](Resources/UI/SwiftUI) | +| :-: | :-: | :-: | :-: | :-: | :-: | :-: | ## Installation ### Swift Package Manager - In Xcode, click `File` -> `Add Package Dependencies...` - Insert `https://github.com/poviolabs/PovioKit` in the Search field. -- Select a desired `Dependency Rule`. Usually "Up to Next Major Version" with "3.0.0". +- Select a desired `Dependency Rule`. Usually "Up to Next Major Version" with "4.0.0". - Select "Add Package" button and check one or all given products from the list: - *PovioKitCore* (core library) - - *PovioKitNetworking* (networking library, depends on `core` and `promise` package) + - *PovioKitNetworking* (networking library built on top of Alamofire, has dependency on `PovioKitPromise` package) - *PovioKitPromise* (lightweight promises library) - - *PovioKitUI* (UI components) + - *PovioKitUtilities* (utility components, has dependency on `PovioKitCore` package) + - *PovioKitAsync* (async/await components) + - *PovioKitUIKit* (UIKit components, has dependency on `PovioKitCore` and `PovioKitUtilities` package) + - *PovioKitSwiftUI* (SwiftUI components, has dependency on `PovioKitCore` package) - Select "Add Package" again and you are done. ### Migration diff --git a/Resources/Async/README.md b/Resources/Async/README.md new file mode 100644 index 00000000..b188d1cf --- /dev/null +++ b/Resources/Async/README.md @@ -0,0 +1,8 @@ +# PovioKit: Async + +A package that includes async components and tools. + +### Components +| Component | Description | +| :--- | :--- | +| [AsyncThrottleSequence](/Sources/Async/AsyncThrottleSequence.swift) | A wrapper around an `AsyncSequence` that introduces a delay between tasks to control the rate at which elements are emitted. | diff --git a/Resources/Core/Utilities/Logger/README.md b/Resources/Core/Logger/README.md similarity index 71% rename from Resources/Core/Utilities/Logger/README.md rename to Resources/Core/Logger/README.md index b3d017d7..6739df5e 100644 --- a/Resources/Core/Utilities/Logger/README.md +++ b/Resources/Core/Logger/README.md @@ -1,10 +1,10 @@ # Logger -Simple console logger. +Simple, yet performant console logger built on top of [OSLog](https://developer.apple.com/documentation/os/logging) framework. ## Log Levels -There is 6 levels defined to choose from +There are 6 levels defined to choose from * info * warn * debug @@ -30,4 +30,4 @@ Logger.debug("Something went wrong", params: ["objectId": 1]) ``` ## Source code -You can find source code [here](/Sources/Core/Utilities/Logger/Logger.swift). +You can find source code [here](/Sources/Core/Logger/Logger.swift). diff --git a/Resources/Core/README.md b/Resources/Core/README.md index c33f251a..655542d0 100644 --- a/Resources/Core/README.md +++ b/Resources/Core/README.md @@ -1,25 +1,12 @@ # PovioKit: Core -Core package including essentials needed for development and other packages. +Core package includes essentials needed for the development and for other packages. -### Utilities - -| Utilities | +### Essentials +| Components | | :--- | -| [AppVersionValidator](/Sources/Core/Utilities/AppVersionValidator/AppVersionValidator.swift) | -| [AttributedStringBuilder](Utilities/AttributedStringBuilder) | -| [Broadcast](Utilities/Broadcast) | -| [BundleReader](/Sources/Core/Utilities/BundleReader/BundleReader.swift) | -| [ColorInterpolator](Utilities/ColorInterpolator) | -| [Delegated](Utilities/Delegated) | -| [DispatchTimer](Utilities/DispatchTimer) | -| [ImageSource](/Sources/Core/Utilities/ImageSource/ImageSource.swift) | -| [Logger](Utilities/Logger) | -| [Money](Utilities/Money) | -| [StartupService](Utilities/StartupService) | -| [Throttler](Utilities/Throttler) | -| [UserDefaults](Utilities/PropertyWrapper/UserDefaults) | -| [XCConfigValue](Utilities/PropertyWrapper/XCConfigValue) | +| [Logger](Logger) | + ### Extensions @@ -39,7 +26,3 @@ Core package including essentials needed for development and other packages. | [UITableViewHeaderFooterView](/Sources/Core/Extensions/UIKit/UITableViewHeaderFooterView+PovioKit.swift) | | | | [UIView](/Sources/Core/Extensions/UIKit/UIView+PovioKit.swift) | | | | [UIViewController](/Sources/Core/Extensions/UIKit/UIViewController+PovioKit.swift) | | | - - - - diff --git a/Resources/Networking/README.md b/Resources/Networking/README.md index 8184dddb..7fed05f1 100644 --- a/Resources/Networking/README.md +++ b/Resources/Networking/README.md @@ -2,7 +2,6 @@ High-level network client abstraction based on [Alamofire](https://github.com/Alamofire/Alamofire). - ## Usage #### Retreiving JSON object from an endpoint diff --git a/Resources/UI/README.md b/Resources/UI/README.md deleted file mode 100644 index a77c9930..00000000 --- a/Resources/UI/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# PovioKit: UI - -UI package including components to simplify building layouts. - -### Components - -| Components | -| :--- | -| [ActionButton](ActionButton) | -| [Camera](Camera) | -| [DynamicCollectionCell](DynamicCollectionCell) | -| [GradientView](GradientView) | -| [PaddingLabel](PaddingLabel) | -| [ProfileImageView](ProfileImageView) | -| [TextField](TextField) | diff --git a/Resources/UI/ActionButton/README.md b/Resources/UI/SwiftUI/ActionButton/README.md similarity index 95% rename from Resources/UI/ActionButton/README.md rename to Resources/UI/SwiftUI/ActionButton/README.md index fd362a25..ece59325 100644 --- a/Resources/UI/ActionButton/README.md +++ b/Resources/UI/SwiftUI/ActionButton/README.md @@ -53,4 +53,4 @@ actionButton.titleRightImage = .init(image: Image(systemName: "arrow.right"), si ``` ## Source code -You can find source code [here](/Sources/UI/ActionButton/ActionButton.swift). +You can find source code [here](/Sources/UI/SwiftUI/Views/ActionButton/ActionButton.swift). diff --git a/Resources/UI/ProfileImageView/README.md b/Resources/UI/SwiftUI/ProfileImageView/README.md similarity index 96% rename from Resources/UI/ProfileImageView/README.md rename to Resources/UI/SwiftUI/ProfileImageView/README.md index 659bcd4a..55ec8a4e 100644 --- a/Resources/UI/ProfileImageView/README.md +++ b/Resources/UI/SwiftUI/ProfileImageView/README.md @@ -73,4 +73,4 @@ profileImageView.set(, placeholder: ) ``` ## Source code -You can find source code [here](/Sources/UI/ProfileImageView). +You can find source code [here](/Sources/UI/SwiftUI/Views/ProfileImageView). diff --git a/Resources/UI/SwiftUI/README.md b/Resources/UI/SwiftUI/README.md new file mode 100644 index 00000000..552c310d --- /dev/null +++ b/Resources/UI/SwiftUI/README.md @@ -0,0 +1,31 @@ +# PovioKit: SwiftUI + +A package including components to help you out developing for SwiftUI framework. + +### Components + +| Views | | +| :--- | :--- | +| [ActionButton](ActionButton) | Generic and customizable CTA button | +| [PhotoPickerView](/Sources/UI/SwiftUI/Views/PhotoPickerView/PhotoPickerView.swift) | Photo and Camera picker view used in combination with `PhotoPickerModifier` | +| [ProfileImageView](ProfileImageView) | Generic and customizable profile image view component | +| [ProgressStyle](/Sources/UI/SwiftUI/Views/ProgressStyle/ProgressStyle.swift) | Customizable ProgressViewStyle | +| [RemoteImage](/Sources/UI/SwiftUI/Views/RemoteImage/RemoteImage.swift) | Fetching remote images using Kingfisher | +| [ScrollViewWithOffset](/Sources/UI/SwiftUI/Views/ScrollViewWithOffset/ScrollViewWithOffset.swift) | ScrollView that expose offset as we scroll | + +| View Modifiers | | +| :--- | :--- | +| [MeasureSizeModifier](/Sources/UI/SwiftUI/View%20Modifiers/MeasureSizeModifier.swift) | A modifier to return size of the underlying view | +| [OnFirstAppearModifier](/Sources/UI/SwiftUI/View%20Modifiers/OnFirstAppearModifier.swift) | Similar to the `OnAppear` modifier, but only runs once per view lifecycle | +| [PhotoPickerModifier](/Sources/UI/SwiftUI/View%20Modifiers/PhotoPickerModifier.swift) | Easily add photo or camera picker to the view | +| [PinchToZoomModifier](/Sources/UI/SwiftUI/View%20Modifiers/PinchToZoomModifier.swift) | Pinching and zooming in/out with ease | +| [SquaredModifier](/Sources/UI/SwiftUI/View%20Modifiers/SquaredModifier.swift) | Make given view squared. This is mostly used with images to properly keep the aspect ratio | +| [TextFieldLimitModifer](/Sources/UI/SwiftUI/View%20Modifiers/TextFieldLimitModifer.swift) | This modifier adds an upper bound text length limitation to the TextField | + +| Extensions | +| :--- | +| [AnyTransition](/Sources/UI/SwiftUI/Extensions/AnyTransition+PovioKit.swift) | +| [Color](/Sources/UI/SwiftUI/Extensions/Color+PovioKit.swift) | +| [Image](/Sources/UI/SwiftUI/Extensions/Image+PovioKit.swift) | +| [Text](/Sources/UI/SwiftUI/Extensions/Text+PovioKit.swift) | +| [View](/Sources/UI/SwiftUI/Extensions/View+PovioKit.swift) | diff --git a/Resources/UI/DynamicCollectionCell/README.md b/Resources/UI/UIKit/DynamicCollectionCell/README.md similarity index 91% rename from Resources/UI/DynamicCollectionCell/README.md rename to Resources/UI/UIKit/DynamicCollectionCell/README.md index 45bd20b8..afe9b902 100644 --- a/Resources/UI/DynamicCollectionCell/README.md +++ b/Resources/UI/UIKit/DynamicCollectionCell/README.md @@ -38,4 +38,4 @@ class ViewController: UIViewController { ``` ## Source code -You can find source code [here](/Sources/UI/DynamicCollectionCell/DynamicCollectionCell.swift). +You can find source code [here](/Sources/UI/UIKit/DynamicCollectionCell/DynamicCollectionCell.swift). diff --git a/Resources/UI/GradientView/README.md b/Resources/UI/UIKit/GradientView/README.md similarity index 77% rename from Resources/UI/GradientView/README.md rename to Resources/UI/UIKit/GradientView/README.md index 4609d50d..4cfec044 100644 --- a/Resources/UI/GradientView/README.md +++ b/Resources/UI/UIKit/GradientView/README.md @@ -6,4 +6,4 @@ A `UIView` subclass providing interface for managing gradient. Adding gradient b TODO: usage through examples ## Source code -You can find source code [here](/Sources/UI/GradientView/GradientView.swift). +You can find source code [here](/Sources/UI/UIKit/GradientView/GradientView.swift). diff --git a/Resources/UI/PaddingLabel/README.md b/Resources/UI/UIKit/PaddingLabel/README.md similarity index 71% rename from Resources/UI/PaddingLabel/README.md rename to Resources/UI/UIKit/PaddingLabel/README.md index 22f774a9..e3ad1f1d 100644 --- a/Resources/UI/PaddingLabel/README.md +++ b/Resources/UI/UIKit/PaddingLabel/README.md @@ -10,4 +10,4 @@ label.contentInset = .init(all: 10) // added 10pt padding on all edges ``` ## Source code -You can find source code [here](/Sources/UI/PaddingLabel/PaddingLabel.swift). +You can find source code [here](/Sources/UI/UIKit/PaddingLabel/PaddingLabel.swift). diff --git a/Resources/UI/UIKit/README.md b/Resources/UI/UIKit/README.md new file mode 100644 index 00000000..e010f93b --- /dev/null +++ b/Resources/UI/UIKit/README.md @@ -0,0 +1,12 @@ +# PovioKit: UIKit + +A package including components to help you out developing for UIKit framework. + +### Components + +| Views | +| :--- | +| [DynamicCollectionCell](DynamicCollectionCell) | +| [GradientView](GradientView) | +| [PaddingLabel](PaddingLabel) | +| [TextField](TextField) | diff --git a/Resources/UI/TextField/README.md b/Resources/UI/UIKit/TextField/README.md similarity index 93% rename from Resources/UI/TextField/README.md rename to Resources/UI/UIKit/TextField/README.md index bd979c12..34bd2572 100644 --- a/Resources/UI/TextField/README.md +++ b/Resources/UI/UIKit/TextField/README.md @@ -48,4 +48,4 @@ guard validatableTextField.isValid else { return } Validation will be triggered when `validatableTextField.isValid` is called. If validation doesn't pass, the error message will automatically display under the textfield. ## Source code -You can find source code [here](/Sources/UI/TextField/TextField.swift). +You can find source code [here](/Sources/UI/UIKit/TextField/TextField.swift). diff --git a/Resources/Core/Utilities/AttributedStringBuilder/README.md b/Resources/Utilities/AttributedStringBuilder/README.md similarity index 97% rename from Resources/Core/Utilities/AttributedStringBuilder/README.md rename to Resources/Utilities/AttributedStringBuilder/README.md index 4c26cbc8..c4a2fd78 100644 --- a/Resources/Core/Utilities/AttributedStringBuilder/README.md +++ b/Resources/Utilities/AttributedStringBuilder/README.md @@ -97,4 +97,4 @@ We've shown how we can configure a couple of attributed parameters, like color, The methods shown through examples above are actually just convenience methods calling generic `addAttribute(key: NSAttributedString.Key, object: Any?)` method. We can use this method instead to configure any other attributes we'd like. ## Source code -You can find source code [here](/Sources/Core/Utilities/AttributedStringBuilder). +You can find source code [here](/Sources/Utilities/AttributedStringBuilder). diff --git a/Resources/Core/Utilities/Broadcast/README.md b/Resources/Utilities/Broadcast/README.md similarity index 94% rename from Resources/Core/Utilities/Broadcast/README.md rename to Resources/Utilities/Broadcast/README.md index ba0aeb34..3e8c6ee5 100644 --- a/Resources/Core/Utilities/Broadcast/README.md +++ b/Resources/Utilities/Broadcast/README.md @@ -56,4 +56,4 @@ class ViewController: UIViewController, AppEventObserver { ``` ## Source code -You can find source code [here](/Sources/Core/Utilities/Broadcast/Broadcast.swift). +You can find source code [here](/Sources/Utilities/Broadcast/Broadcast.swift). diff --git a/Resources/UI/Camera/README.md b/Resources/Utilities/Camera/README.md similarity index 96% rename from Resources/UI/Camera/README.md rename to Resources/Utilities/Camera/README.md index 60da9688..ef54b940 100644 --- a/Resources/UI/Camera/README.md +++ b/Resources/Utilities/Camera/README.md @@ -83,4 +83,4 @@ func prepareQRCodeSCanner() { `func scanFailure()` ## Source code -You can find source code [here](/Sources/UI/Camera). +You can find source code [here](/Sources/Utilities/Camera). diff --git a/Resources/Core/Utilities/ColorInterpolator/README.md b/Resources/Utilities/ColorInterpolator/README.md similarity index 85% rename from Resources/Core/Utilities/ColorInterpolator/README.md rename to Resources/Utilities/ColorInterpolator/README.md index c6f4be04..606cdca3 100644 --- a/Resources/Core/Utilities/ColorInterpolator/README.md +++ b/Resources/Utilities/ColorInterpolator/README.md @@ -20,4 +20,4 @@ try? colorInterpolator.interpolate(colorPoints: colors, percentage: percentage) ``` ## Source code -You can find source code [here](/Sources/Core/Utilities/ColorInterpolator/ColorInterpolator.swift). +You can find source code [here](/Sources/Utilities/ColorInterpolator/ColorInterpolator.swift). diff --git a/Resources/Core/Utilities/Delegated/README.md b/Resources/Utilities/Delegated/README.md similarity index 97% rename from Resources/Core/Utilities/Delegated/README.md rename to Resources/Utilities/Delegated/README.md index 250fffc3..45a1e803 100644 --- a/Resources/Core/Utilities/Delegated/README.md +++ b/Resources/Utilities/Delegated/README.md @@ -127,4 +127,4 @@ class Controller: UIViewController, UITableViewDataSource { https://medium.com/anysuggestion/preventing-memory-leaks-with-swift-compile-time-safety-49b845df4dc6 ## Source code -You can find source code [here](/Sources/Core/Utilities/Delegated/Delegated.swift). +You can find source code [here](/Sources/Utilities/Delegated/Delegated.swift). diff --git a/Resources/Core/Utilities/DispatchTimer/README.md b/Resources/Utilities/DispatchTimer/README.md similarity index 89% rename from Resources/Core/Utilities/DispatchTimer/README.md rename to Resources/Utilities/DispatchTimer/README.md index 73b298fe..f2164ea5 100644 --- a/Resources/Core/Utilities/DispatchTimer/README.md +++ b/Resources/Utilities/DispatchTimer/README.md @@ -37,4 +37,4 @@ myTimer.stop() // you could eventually just nillify reference and the timer is t ``` ## Source code -You can find source code [here](/Sources/Core/Utilities/DispatchTimer/DispatchTimer.swift). +You can find source code [here](/Sources/Utilities/DispatchTimer/DispatchTimer.swift). diff --git a/Resources/Core/Utilities/Exif/README.md b/Resources/Utilities/Exif/README.md similarity index 94% rename from Resources/Core/Utilities/Exif/README.md rename to Resources/Utilities/Exif/README.md index 4f670a0c..4d0132b9 100644 --- a/Resources/Core/Utilities/Exif/README.md +++ b/Resources/Utilities/Exif/README.md @@ -50,4 +50,4 @@ do { ``` ## Source code -You can find source code [here](/Sources/Core/Utilities/Exif/Exif.swift). +You can find source code [here](/Sources/Utilities/Exif/Exif.swift). diff --git a/Resources/Core/Utilities/InAppPurchase/README.md b/Resources/Utilities/InAppPurchase/README.md similarity index 98% rename from Resources/Core/Utilities/InAppPurchase/README.md rename to Resources/Utilities/InAppPurchase/README.md index 98a5c533..4889d185 100644 --- a/Resources/Core/Utilities/InAppPurchase/README.md +++ b/Resources/Utilities/InAppPurchase/README.md @@ -163,4 +163,4 @@ Task { ``` ## Source code -You can find source code [here](/Sources/Core/Utilities/InAppPurchase). +You can find source code [here](/Sources/Utilities/InAppPurchase). diff --git a/Resources/Core/Utilities/Money/README.md b/Resources/Utilities/Money/README.md similarity index 98% rename from Resources/Core/Utilities/Money/README.md rename to Resources/Utilities/Money/README.md index b2d459e8..4a2a71b7 100644 --- a/Resources/Core/Utilities/Money/README.md +++ b/Resources/Utilities/Money/README.md @@ -150,4 +150,4 @@ print(money2 < money3) // true ``` ## Source code -You can find source code [here](/Sources/Core/Utilities/Money). +You can find source code [here](/Sources/Utilities/Money). diff --git a/Resources/Core/Utilities/PropertyWrapper/UserDefaults/README.md b/Resources/Utilities/PropertyWrapper/UserDefault/README.md similarity index 89% rename from Resources/Core/Utilities/PropertyWrapper/UserDefaults/README.md rename to Resources/Utilities/PropertyWrapper/UserDefault/README.md index 2205df4c..731077a1 100644 --- a/Resources/Core/Utilities/PropertyWrapper/UserDefaults/README.md +++ b/Resources/Utilities/PropertyWrapper/UserDefault/README.md @@ -38,4 +38,4 @@ extension UserDefault { ``` ## Source code -You can find source code [here](/Sources/Core/Utilities/PropertyWrapper/UserDefault.swift). +You can find source code [here](/Sources/Utilities/PropertyWrapper/UserDefault.swift). diff --git a/Resources/Core/Utilities/PropertyWrapper/XCConfigValue/README.md b/Resources/Utilities/PropertyWrapper/XCConfigValue/README.md similarity index 87% rename from Resources/Core/Utilities/PropertyWrapper/XCConfigValue/README.md rename to Resources/Utilities/PropertyWrapper/XCConfigValue/README.md index 3a624534..bb53a95c 100644 --- a/Resources/Core/Utilities/PropertyWrapper/XCConfigValue/README.md +++ b/Resources/Utilities/PropertyWrapper/XCConfigValue/README.md @@ -25,4 +25,4 @@ enum Environment { ``` ## Source code -You can find source code [here](/Sources/Core/Utilities/PropertyWrapper/XCConfigValue.swift). +You can find source code [here](/Sources/Utilities/PropertyWrapper/XCConfigValue.swift). diff --git a/Resources/Utilities/README.md b/Resources/Utilities/README.md new file mode 100644 index 00000000..64567cf2 --- /dev/null +++ b/Resources/Utilities/README.md @@ -0,0 +1,25 @@ +# PovioKit: Utilities + +Core package including utility tools. + +### Utilities + +| Available Utilities | +| :--- | +| [AppVersionValidator](/Sources/Utilities/AppVersionValidator/AppVersionValidator.swift) | +| [AttributedStringBuilder](AttributedStringBuilder) | +| [Broadcast](Broadcast) | +| [BundleReader](/Sources/Utilities/BundleReader/BundleReader.swift) | +| [Camera](Camera) | +| [ColorInterpolator](ColorInterpolator) | +| [Delegated](Delegated) | +| [DispatchTimer](DispatchTimer) | +| [Exif](Exif) | +| [ImageSource](/Sources/Utilities/ImageSource/ImageSource.swift) | +| [InAppPurchase](InAppPurchase) | +| [MediaPlayer](/Sources/Utilities/MediaPlayer) | +| [Money](Money) | +| [Property wrapper: UserDefaults](PropertyWrapper/UserDefaults) | +| [Property wrapper: XCConfigValue](PropertyWrapper/XCConfigValue) | +| [StartupService](StartupService) | +| [Throttler](Throttler) | diff --git a/Resources/Core/Utilities/StartupService/README.md b/Resources/Utilities/StartupService/README.md similarity index 97% rename from Resources/Core/Utilities/StartupService/README.md rename to Resources/Utilities/StartupService/README.md index 7bfab409..02af38d4 100644 --- a/Resources/Core/Utilities/StartupService/README.md +++ b/Resources/Utilities/StartupService/README.md @@ -76,4 +76,4 @@ public final class FacebookSetupProcess: StartupProcess { ``` ## Source code -You can find source code [here](/Sources/Core/Utilities/StartupService). +You can find source code [here](/Sources/Utilities/StartupService). diff --git a/Resources/Core/Utilities/Throttler/README.md b/Resources/Utilities/Throttler/README.md similarity index 90% rename from Resources/Core/Utilities/Throttler/README.md rename to Resources/Utilities/Throttler/README.md index b620365b..68e47b67 100644 --- a/Resources/Core/Utilities/Throttler/README.md +++ b/Resources/Utilities/Throttler/README.md @@ -21,4 +21,4 @@ class SearchWorker { ``` ## Source code -You can find source code [here](/Sources/Core/Utilities/Throttler/Throttler.swift). +You can find source code [here](/Sources/Utilities/Throttler/Throttler.swift). diff --git a/Sources/Async/AsyncThrottleSequence.swift b/Sources/Async/AsyncThrottleSequence.swift index 5c80fb5d..dd03b730 100644 --- a/Sources/Async/AsyncThrottleSequence.swift +++ b/Sources/Async/AsyncThrottleSequence.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni K. Turk on 22/08/2023. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation @@ -116,35 +116,30 @@ extension AsyncThrottleSequence: AsyncSequence where C.Duration == Duration { /// - Throws: An error if the underlying `AsyncSequence` throws an error. /// - Returns: The next element in the sequence, or `nil` if there are no more elements. public func next() async throws -> Element? { - var task: Task? - - lock.withLock { + let task = lock.withLock { taskInExecution?.cancel() taskInExecution = nil - let taskA = Task { - try await Task.sleep(until: clock.now.advanced(by: delayBetweenTasks), clock: clock) + let task = Task { + try await Task.sleep( + until: clock.now.advanced(by: delayBetweenTasks), + clock: clock + ) let result = try await baseIterator.next() - do { - // If task was cancelled while a request was being awaited, - // return `nil`! - try Task.checkCancellation() - return result - } catch { - if error is CancellationError { - return nil - } - throw error - } + try Task.checkCancellation() + return result } - task = taskA - taskInExecution = taskA + taskInExecution = task + return task } do { - return try await task?.value + return try await task.value } catch { - return nil + if error is CancellationError { + return nil + } + throw error } - } + } } /// Creates a new iterator for the `AsyncThrottleSequence`. diff --git a/Sources/Core/Extensions/Foundation/Collection+PovioKit.swift b/Sources/Core/Extensions/Foundation/Collection+PovioKit.swift index e165823b..2ad09f29 100644 --- a/Sources/Core/Extensions/Foundation/Collection+PovioKit.swift +++ b/Sources/Core/Extensions/Foundation/Collection+PovioKit.swift @@ -3,26 +3,33 @@ // PovioKit // // Created by Povio Team on 26/04/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation -public extension Collection where Indices.Iterator.Element == Index { +public extension Collection { /// Returns the element at the specified `index` if it is within bounds, otherwise `nil`. - subscript (safe index: Index) -> Iterator.Element? { - (startIndex <= index && index < endIndex) ? self[index] : nil + subscript (safe index: Index) -> Element? { + if startIndex <= index && index < endIndex { self[index] } else { nil } } } public extension Collection { - /// Conditional element count - https://github.com/apple/swift-evolution/blob/master/proposals/0220-count-where.md - func count(where clause: (Element) -> Bool) -> Int { - lazy.filter(clause).count + /// Conditional element count - https://forums.swift.org/t/refresh-review-se-0220-count-where/66235/4 + @inlinable + func count( + where predicate: (Element) throws -> Bool + ) rethrows -> Int { + try reduce(0) { n, element in + if try predicate(element) { + n + 1 + } else { + n + } + } } -} - -public extension Collection { + /// Groups collection elements based on dateComponents returning a dictionary func grouped( extractDate: (Element) -> Date, @@ -39,3 +46,13 @@ public extension Collection { ) } } + +public extension MutableCollection { + mutating func mutateEach(_ mutator: (inout Element) throws -> Void) rethrows { + var idx = startIndex + while idx != endIndex { + try mutator(&self[idx]) + formIndex(after: &idx) + } + } +} diff --git a/Sources/Core/Extensions/Foundation/Data+PovioKit.swift b/Sources/Core/Extensions/Foundation/Data+PovioKit.swift index 11310361..50ac944c 100644 --- a/Sources/Core/Extensions/Foundation/Data+PovioKit.swift +++ b/Sources/Core/Extensions/Foundation/Data+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Povio Team on 21/08/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation @@ -15,27 +15,21 @@ public extension Data { map { String(format: "%02x", $0) }.joined() } + /// Returns a UTF-8 encoded string. + var utf8: String? { + String(data: self, encoding: .utf8) + } + + /// Returns a UTF-16 encoded string. + var utf16: String? { + String(data: self, encoding: .utf16) + } + /// Decodes data to given `type` using given `decoder`. /// ``` /// let decodedUser = responseData.decode(UserResponse.self, with: JSONDecoder()) /// ``` func decode(_ type: D.Type, with decoder: JSONDecoder) throws -> D { - do { - return try decoder.decode(type, from: self) - } catch let decodingError as DecodingError { - switch decodingError { - case .typeMismatch(_, let context), - .valueNotFound(_, let context), - .keyNotFound(_, let context), - .dataCorrupted(let context): - Logger.debug("Decoding (failure): \(type.self)", params: ["error": context.debugDescription]) - @unknown default: - Logger.debug("Decoding (failure): \(type.self)", params: ["error": "Unknown decoding error."]) - } - throw decodingError - } catch { - Logger.debug("Decoding (failure): \(type.self)", params: ["error": error.localizedDescription]) - throw error - } + try decoder.decode(type, from: self) } } diff --git a/Sources/Core/Extensions/Foundation/Date+PovioKit.swift b/Sources/Core/Extensions/Foundation/Date+PovioKit.swift new file mode 100644 index 00000000..c8f7fdd5 --- /dev/null +++ b/Sources/Core/Extensions/Foundation/Date+PovioKit.swift @@ -0,0 +1,34 @@ +// +// Date+PovioKit.swift +// PovioKit +// +// Created by Borut Tomazin on 14/05/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import Foundation + +public extension Date { + var isToday: Bool { calendar.isDateInToday(self) } + var isYesterday: Bool { calendar.isDateInYesterday(self) } + var isInFuture: Bool { self > Date() } + + /// Returns first day of the week + var startOfWeek: Date? { + let components: Set = [.yearForWeekOfYear, .weekOfYear, .hour, .minute, .second, .nanosecond] + return calendar.date(from: calendar.dateComponents(components, from: self)) + } + + /// Returns last day of the week + var endOfWeek: Date? { + guard let startOfWeek = Date().startOfWeek else { return nil } + return calendar.date(byAdding: .day, value: 6, to: startOfWeek) + } +} + +// MARK: - Private Methods +private extension Date { + var calendar: Calendar { + Calendar.autoupdatingCurrent + } +} diff --git a/Sources/Core/Extensions/Foundation/DecodableDictionary+PovioKit.swift b/Sources/Core/Extensions/Foundation/DecodableDictionary+PovioKit.swift index cecaf35f..ea68058c 100644 --- a/Sources/Core/Extensions/Foundation/DecodableDictionary+PovioKit.swift +++ b/Sources/Core/Extensions/Foundation/DecodableDictionary+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 11/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Extensions/Foundation/DispatchTimeInterval+PovioKit.swift b/Sources/Core/Extensions/Foundation/DispatchTimeInterval+PovioKit.swift index 029a0b89..fad8c37a 100644 --- a/Sources/Core/Extensions/Foundation/DispatchTimeInterval+PovioKit.swift +++ b/Sources/Core/Extensions/Foundation/DispatchTimeInterval+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 11/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Extensions/Foundation/Double+PovioKit.swift b/Sources/Core/Extensions/Foundation/Double+PovioKit.swift index f48b4c55..bf423725 100644 --- a/Sources/Core/Extensions/Foundation/Double+PovioKit.swift +++ b/Sources/Core/Extensions/Foundation/Double+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 02/09/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Extensions/Foundation/Encodable+PovioKit.swift b/Sources/Core/Extensions/Foundation/Encodable+PovioKit.swift index 03985ff1..a27cc034 100644 --- a/Sources/Core/Extensions/Foundation/Encodable+PovioKit.swift +++ b/Sources/Core/Extensions/Foundation/Encodable+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 11/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation @@ -15,33 +15,14 @@ public extension Encodable { /// /// do { /// let encoder = JSONEncoder() - /// let requestParameters = try request.encode(with: encoder) + /// let requestParameters = try request.toJSON(with: encoder) /// } catch { /// // error /// } /// ``` - func encode(with encoder: JSONEncoder) throws -> [String: Any] { - do { - let data = try encoder.encode(self) - guard let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { - throw JSONError.serialization - } - return jsonObject - } catch let encodingError as EncodingError { - switch encodingError { - case .invalidValue(_, let context): - Logger.debug("Encoding (failure): \(type(of: self))", params: ["error": context.debugDescription]) - @unknown default: - Logger.debug("Encoding (failure): \(type(of: self))", params: ["error": "Unknown encoding error."]) - } - throw encodingError - } catch { - Logger.debug("Encoding (failure): \(type(of: self))", params: ["error": error.self]) - throw error - } + func toJSON(with encoder: JSONEncoder) throws -> [String: Any] { + let data = try encoder.encode(self) + let json = try JSONSerialization.jsonObject(with: data, options: []) + return (json as? [String: Any]) ?? [:] } } - -private enum JSONError: Error { - case serialization -} diff --git a/Sources/Core/Extensions/Foundation/Optional+PovioKit.swift b/Sources/Core/Extensions/Foundation/Optional+PovioKit.swift index 8b77e18e..8450dcb9 100644 --- a/Sources/Core/Extensions/Foundation/Optional+PovioKit.swift +++ b/Sources/Core/Extensions/Foundation/Optional+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Povio Team on 26/04/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Extensions/Foundation/Result+PovioKit.swift b/Sources/Core/Extensions/Foundation/Result+PovioKit.swift index 4fe40472..befc665c 100644 --- a/Sources/Core/Extensions/Foundation/Result+PovioKit.swift +++ b/Sources/Core/Extensions/Foundation/Result+PovioKit.swift @@ -3,7 +3,7 @@ // Alamofire // // Created by Borut Tomažin on 24/02/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Extensions/Foundation/String+PovioKit.swift b/Sources/Core/Extensions/Foundation/String+PovioKit.swift index 2157bbb3..68087c06 100644 --- a/Sources/Core/Extensions/Foundation/String+PovioKit.swift +++ b/Sources/Core/Extensions/Foundation/String+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Povio Team on 26/04/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation @@ -38,6 +38,18 @@ public extension String { return emailTest.evaluate(with: self) } + /// Returns initials from string + /// `John Doe` -> `JD` + /// `Elena Wayne Gomez` -> `EWG` + var initials: String { + let formatter = PersonNameComponentsFormatter() + if let components = formatter.personNameComponents(from: self) { + formatter.style = .abbreviated + return formatter.string(from: components) + } + return self + } + /// Returns substring containing up to `maxLength` characters from the beginning of the string. /// /// This method is just a wrapper around swift's standard library `prefix` method, but it ensures only positive values are accepted. @@ -51,4 +63,16 @@ public extension String { func safeSuffix(_ maxLength: UInt) -> Substring { suffix(Int(maxLength)) } + + /// Converts the string into a markdown formatted AttributedString. + /// + /// If the conversion fails (e.g., due to invalid markdown syntax), it returns the original string as an AttributedString. Requires iOS 15 and above. + @available(iOS 15, *) + func toMarkdown() -> AttributedString { + do { + return try AttributedString(markdown: self) + } catch { + return AttributedString(self) + } + } } diff --git a/Sources/Core/Extensions/Foundation/URL+PovioKit.swift b/Sources/Core/Extensions/Foundation/URL+PovioKit.swift index 37551542..b32825b5 100644 --- a/Sources/Core/Extensions/Foundation/URL+PovioKit.swift +++ b/Sources/Core/Extensions/Foundation/URL+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Povio Team on 26/04/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Extensions/MapKit/MKAnnotationView+PovioKit.swift b/Sources/Core/Extensions/MapKit/MKAnnotationView+PovioKit.swift index 119c9ab9..92ae24d1 100644 --- a/Sources/Core/Extensions/MapKit/MKAnnotationView+PovioKit.swift +++ b/Sources/Core/Extensions/MapKit/MKAnnotationView+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 11/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import MapKit.MKAnnotationView diff --git a/Sources/Core/Extensions/MapKit/MKCircle+PovioKit.swift b/Sources/Core/Extensions/MapKit/MKCircle+PovioKit.swift index e8fe06f4..fb4e0527 100644 --- a/Sources/Core/Extensions/MapKit/MKCircle+PovioKit.swift +++ b/Sources/Core/Extensions/MapKit/MKCircle+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 11/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import MapKit.MKCircle diff --git a/Sources/Core/Extensions/MapKit/MKMapView+PovioKit.swift b/Sources/Core/Extensions/MapKit/MKMapView+PovioKit.swift index e8fb0126..62e80e3a 100644 --- a/Sources/Core/Extensions/MapKit/MKMapView+PovioKit.swift +++ b/Sources/Core/Extensions/MapKit/MKMapView+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 11/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import MapKit.MKMapView diff --git a/Sources/Core/Extensions/MapKit/MKPolygon+PovioKit.swift b/Sources/Core/Extensions/MapKit/MKPolygon+PovioKit.swift index 9163202e..0cfa1c8d 100644 --- a/Sources/Core/Extensions/MapKit/MKPolygon+PovioKit.swift +++ b/Sources/Core/Extensions/MapKit/MKPolygon+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 11/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import MapKit.MKPolygon diff --git a/Sources/Core/Extensions/Other/SKStoreReviewController+PovioKit.swift b/Sources/Core/Extensions/Other/SKStoreReviewController+PovioKit.swift index ccca4551..be653337 100644 --- a/Sources/Core/Extensions/Other/SKStoreReviewController+PovioKit.swift +++ b/Sources/Core/Extensions/Other/SKStoreReviewController+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Borut Tomažin on 23/06/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import StoreKit public extension SKStoreReviewController { @@ -24,3 +25,4 @@ public extension SKStoreReviewController { } } } +#endif diff --git a/Sources/Core/Extensions/UIKit/CGSize+PovioKit.swift b/Sources/Core/Extensions/UIKit/CGSize+PovioKit.swift new file mode 100644 index 00000000..e54c923d --- /dev/null +++ b/Sources/Core/Extensions/UIKit/CGSize+PovioKit.swift @@ -0,0 +1,18 @@ +// +// CGSize+PovioKit.swift +// PovioKit +// +// Created by Borut Tomazin on 14/05/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +#if os(iOS) +import UIKit + +public extension CGSize { + init(size: CGFloat) { + self.init(width: size, height: size) + } +} + +#endif diff --git a/Sources/Core/Extensions/UIKit/UIApplication+PovioKit.swift b/Sources/Core/Extensions/UIKit/UIApplication+PovioKit.swift index 1d74ddd4..09f81837 100644 --- a/Sources/Core/Extensions/UIKit/UIApplication+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UIApplication+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Borut Tomažin on 13/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UIApplication { @@ -33,6 +34,11 @@ public extension UIApplication { } public extension UIApplication { + /// Returns bundle id + var bundleId: String { + Bundle.main.object(forInfoDictionaryKey: "CFBundleIdentifier") as? String ?? "/" + } + /// Returns app name var name: String { Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String ?? "/" @@ -48,3 +54,4 @@ public extension UIApplication { Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "/" } } +#endif diff --git a/Sources/Core/Extensions/UIKit/UICollectionReusableView+PovioKit.swift b/Sources/Core/Extensions/UIKit/UICollectionReusableView+PovioKit.swift index 4816ce0d..c4975444 100755 --- a/Sources/Core/Extensions/UIKit/UICollectionReusableView+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UICollectionReusableView+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Povio Team on 26/4/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UICollectionReusableView { @@ -14,3 +15,5 @@ public extension UICollectionReusableView { String(describing: self) } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UICollectionView+PovioKit.swift b/Sources/Core/Extensions/UIKit/UICollectionView+PovioKit.swift index 87f09d20..2fbece0c 100644 --- a/Sources/Core/Extensions/UIKit/UICollectionView+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UICollectionView+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Povio Team on 26/4/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UICollectionView { @@ -68,3 +69,5 @@ public extension UICollectionView { height: bounds.height - (contentInset.top + contentInset.bottom)) } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UIColor+PovioKit.swift b/Sources/Core/Extensions/UIKit/UIColor+PovioKit.swift index 033df47b..af60d93c 100644 --- a/Sources/Core/Extensions/UIKit/UIColor+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UIColor+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Povio Team on 26/4/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UIColor { @@ -13,3 +14,5 @@ public extension UIColor { self.init(red: CGFloat(red) / 255, green: CGFloat(green) / 255, blue: CGFloat(blue) / 255, alpha: alpha) } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UIDevice+PovioKit.swift b/Sources/Core/Extensions/UIKit/UIDevice+PovioKit.swift index 116fa1a8..762183e5 100644 --- a/Sources/Core/Extensions/UIKit/UIDevice+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UIDevice+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Povio Team on 26/4/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UIDevice { @@ -29,4 +30,18 @@ public extension UIDevice { return identifier + String(UnicodeScalar(UInt8(value))) } } + + /// Returns `UIEdgeInsets` for the possible (top/bottom) safe areas + var safeAreaInsets: UIEdgeInsets { + let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene + let window = windowScene?.windows.first + return window?.safeAreaInsets ?? .init() + } + + /// Returns `true` on devices with notch + var hasNotch: Bool { + safeAreaInsets.bottom > 0 + } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UIEdgeInsets+PovioKit.swift b/Sources/Core/Extensions/UIKit/UIEdgeInsets+PovioKit.swift index 2355d052..45125263 100644 --- a/Sources/Core/Extensions/UIKit/UIEdgeInsets+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UIEdgeInsets+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Povio Team on 26/4/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UIEdgeInsets { @@ -53,3 +54,5 @@ public extension UIEdgeInsets { } } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UIImage+PovioKit.swift b/Sources/Core/Extensions/UIKit/UIImage+PovioKit.swift index 32e2256c..6cbeeb90 100644 --- a/Sources/Core/Extensions/UIKit/UIImage+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UIImage+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Povio Team on 26/4/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UIImage { @@ -41,4 +42,23 @@ public extension UIImage { UIGraphicsEndImageContext() return image ?? UIImage() } + + /// Returns existing image clipped to a circle + var clipToCircle: UIImage { + let layer = CALayer() + layer.frame = .init(origin: .zero, size: size) + layer.contents = cgImage + layer.masksToBounds = true + + layer.cornerRadius = size.width / 2 + + UIGraphicsBeginImageContext(size) + guard let context = UIGraphicsGetCurrentContext() else { return self } + layer.render(in: context) + let roundedImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + return roundedImage ?? self + } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UIProgressView+PovioKit.swift b/Sources/Core/Extensions/UIKit/UIProgressView+PovioKit.swift index 4fcb3203..1fedc197 100644 --- a/Sources/Core/Extensions/UIKit/UIProgressView+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UIProgressView+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Borut Tomažin on 13/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UIProgressView { @@ -24,3 +25,5 @@ public extension UIProgressView { }) } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UIResponder+PovioKit.swift b/Sources/Core/Extensions/UIKit/UIResponder+PovioKit.swift index f2b7528d..219ee01a 100644 --- a/Sources/Core/Extensions/UIKit/UIResponder+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UIResponder+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Borut Tomažin on 13/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UIResponder { @@ -31,3 +32,5 @@ public extension UIResponder { return nil } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UITableView+PovioKit.swift b/Sources/Core/Extensions/UIKit/UITableView+PovioKit.swift index ec0c46e4..822e0466 100644 --- a/Sources/Core/Extensions/UIKit/UITableView+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UITableView+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Povio Team on 26/4/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UITableView { @@ -66,3 +67,5 @@ public extension UITableView { scrollToRow(at: IndexPath(row: lastRow, section: lastSection), at: .bottom, animated: animated) } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UITableViewCell+PovioKit.swift b/Sources/Core/Extensions/UIKit/UITableViewCell+PovioKit.swift index 767bdef5..471cf50b 100755 --- a/Sources/Core/Extensions/UIKit/UITableViewCell+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UITableViewCell+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Povio Team on 26/4/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UITableViewCell { @@ -14,3 +15,5 @@ public extension UITableViewCell { String(describing: self) } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UITableViewHeaderFooterView+PovioKit.swift b/Sources/Core/Extensions/UIKit/UITableViewHeaderFooterView+PovioKit.swift index a120113e..824323d8 100755 --- a/Sources/Core/Extensions/UIKit/UITableViewHeaderFooterView+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UITableViewHeaderFooterView+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Povio Team on 26/4/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UITableViewHeaderFooterView { @@ -14,3 +15,5 @@ public extension UITableViewHeaderFooterView { String(describing: self) } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UIView+PovioKit.swift b/Sources/Core/Extensions/UIKit/UIView+PovioKit.swift index b42bfbd3..2b66a3e7 100644 --- a/Sources/Core/Extensions/UIKit/UIView+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UIView+PovioKit.swift @@ -3,13 +3,14 @@ // PovioKit // // Created by Povio Team on 26/4/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit -// MARK: - Shadow and border public extension UIView { + // Add shadow and border func dropShadow(path: UIBezierPath?, shadowColor: UIColor, radius: CGFloat, opacity: Float, offset: CGSize) { layer.shadowPath = path?.cgPath layer.shadowColor = shadowColor.cgColor @@ -71,3 +72,5 @@ public extension UIView { } } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UIViewController+PovioKit.swift b/Sources/Core/Extensions/UIKit/UIViewController+PovioKit.swift index e2a7529f..aa440187 100644 --- a/Sources/Core/Extensions/UIKit/UIViewController+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UIViewController+PovioKit.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Toni Kocjan on 26/07/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UIViewController { @@ -100,3 +101,5 @@ private extension UIViewController { } } } + +#endif diff --git a/Sources/Core/Extensions/UIKit/UIWindow+PovioKit.swift b/Sources/Core/Extensions/UIKit/UIWindow+PovioKit.swift index 400a4a84..4919aae5 100644 --- a/Sources/Core/Extensions/UIKit/UIWindow+PovioKit.swift +++ b/Sources/Core/Extensions/UIKit/UIWindow+PovioKit.swift @@ -3,16 +3,29 @@ // PovioKit // // Created by Borut Tomazin on 5/1/2023. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public extension UIWindow { - /// Returns `UIEdgeInsets` for the possible (top/bottom) safe areas - static var safeAreaInsets: UIEdgeInsets { - UIApplication.shared.windows - .first { $0.isKeyWindow } - .map { $0.rootViewController?.view?.safeAreaInsets ?? .zero } ?? .zero + /// Returns `viewController` that currently sits on top + var topViewController: UIViewController? { + func topViewController(with rootViewController: UIViewController?) -> UIViewController? { + guard rootViewController != nil else { return nil } + + if let tabBarController = rootViewController as? UITabBarController { + return topViewController(with: tabBarController.selectedViewController) + } else if let navigationController = rootViewController as? UINavigationController { + return topViewController(with: navigationController.visibleViewController) + } else if rootViewController?.presentedViewController != nil { + return topViewController(with: rootViewController?.presentedViewController) + } + return rootViewController + } + return topViewController(with: rootViewController) } } + +#endif diff --git a/Sources/Core/Utilities/Logger/Logger.swift b/Sources/Core/Logger/Logger.swift similarity index 98% rename from Sources/Core/Utilities/Logger/Logger.swift rename to Sources/Core/Logger/Logger.swift index 1c96d9b1..4a52e17a 100644 --- a/Sources/Core/Utilities/Logger/Logger.swift +++ b/Sources/Core/Logger/Logger.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 04/29/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import OSLog diff --git a/Sources/Networking/AlamofireNetworkClient/AlamofireConsoleLogger.swift b/Sources/Networking/AlamofireNetworkClient/AlamofireConsoleLogger.swift index 9d792490..b3769110 100644 --- a/Sources/Networking/AlamofireNetworkClient/AlamofireConsoleLogger.swift +++ b/Sources/Networking/AlamofireNetworkClient/AlamofireConsoleLogger.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 05/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Alamofire diff --git a/Sources/Networking/AlamofireNetworkClient/AlamofireNetworkClient.swift b/Sources/Networking/AlamofireNetworkClient/AlamofireNetworkClient.swift index 20d40310..9f2404a3 100644 --- a/Sources/Networking/AlamofireNetworkClient/AlamofireNetworkClient.swift +++ b/Sources/Networking/AlamofireNetworkClient/AlamofireNetworkClient.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 28/10/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Networking/AlamofireNetworkClient/Extensions/ParameterEncoder+PovioKit.swift b/Sources/Networking/AlamofireNetworkClient/Extensions/ParameterEncoder+PovioKit.swift index f9c4986c..ca9e09ce 100644 --- a/Sources/Networking/AlamofireNetworkClient/Extensions/ParameterEncoder+PovioKit.swift +++ b/Sources/Networking/AlamofireNetworkClient/Extensions/ParameterEncoder+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Egzon Arifi on 20/05/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Alamofire diff --git a/Sources/Networking/AlamofireNetworkClient/Extensions/URLEncodedFormParameterEncoder+PovioKit.swift b/Sources/Networking/AlamofireNetworkClient/Extensions/URLEncodedFormParameterEncoder+PovioKit.swift index fca04022..20a66d31 100644 --- a/Sources/Networking/AlamofireNetworkClient/Extensions/URLEncodedFormParameterEncoder+PovioKit.swift +++ b/Sources/Networking/AlamofireNetworkClient/Extensions/URLEncodedFormParameterEncoder+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 04/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Alamofire @@ -11,9 +11,11 @@ import Foundation import PovioKitCore public extension URLEncodedFormParameterEncoder { - convenience init(encoder: JSONEncoder, - arrayEncoding: URLEncodedFormEncoder.ArrayEncoding = .brackets, - boolEncoding: URLEncodedFormEncoder.BoolEncoding = .numeric) { + convenience init( + encoder: JSONEncoder, + arrayEncoding: URLEncodedFormEncoder.ArrayEncoding = .brackets, + boolEncoding: URLEncodedFormEncoder.BoolEncoding = .numeric + ) { let formEncoder = URLEncodedFormEncoder( alphabetizeKeyValuePairs: true, arrayEncoding: arrayEncoding, @@ -22,7 +24,8 @@ public extension URLEncodedFormParameterEncoder { dateEncoding: Self.dateEncoding(from: encoder.dateEncodingStrategy), keyEncoding: Self.keyEncoding(from: encoder.keyEncodingStrategy), spaceEncoding: .percentEscaped, - allowedCharacters: .afURLQueryAllowed) + allowedCharacters: .afURLQueryAllowed + ) self.init(encoder: formEncoder, destination: .methodDependent) } } @@ -41,7 +44,6 @@ private extension URLEncodedFormParameterEncoder { case .formatted(let formatter): return .formatted(formatter) case .custom: - Logger.warning("Custom date encoding is not handled.") return .deferredToDate @unknown default: return .deferredToDate @@ -55,7 +57,6 @@ private extension URLEncodedFormParameterEncoder { case .convertToSnakeCase: return .convertToSnakeCase case .custom: - Logger.warning("Custom key encoding is not handled.") return .useDefaultKeys @unknown default: return .useDefaultKeys @@ -69,7 +70,6 @@ private extension URLEncodedFormParameterEncoder { case .base64: return .base64 case .custom: - Logger.warning("Custom data encoding is not handled.") return .base64 @unknown default: return .base64 diff --git a/Sources/Networking/AlamofireNetworkClient/OAuth/OAuthCredentials.swift b/Sources/Networking/AlamofireNetworkClient/OAuth/OAuthCredentials.swift index d6ed6450..cf87fe01 100644 --- a/Sources/Networking/AlamofireNetworkClient/OAuth/OAuthCredentials.swift +++ b/Sources/Networking/AlamofireNetworkClient/OAuth/OAuthCredentials.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomazin on 20/04/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/PromiseKit/After.swift b/Sources/PromiseKit/After.swift index bc7d0f64..8ea27978 100644 --- a/Sources/PromiseKit/After.swift +++ b/Sources/PromiseKit/After.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 03/02/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/PromiseKit/All.swift b/Sources/PromiseKit/All.swift index 349fd8e3..3007a9d2 100644 --- a/Sources/PromiseKit/All.swift +++ b/Sources/PromiseKit/All.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 02/02/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/PromiseKit/Any.swift b/Sources/PromiseKit/Any.swift index 47f29c3d..bd9fde8f 100644 --- a/Sources/PromiseKit/Any.swift +++ b/Sources/PromiseKit/Any.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 26/08/2021. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/PromiseKit/ConcurrentDispatch.swift b/Sources/PromiseKit/ConcurrentDispatch.swift index 3c44a5c0..299d573b 100644 --- a/Sources/PromiseKit/ConcurrentDispatch.swift +++ b/Sources/PromiseKit/ConcurrentDispatch.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 23/09/2021. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/PromiseKit/Either.swift b/Sources/PromiseKit/Either.swift index a6f56b7b..aa769f68 100644 --- a/Sources/PromiseKit/Either.swift +++ b/Sources/PromiseKit/Either.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 26/08/2021. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/PromiseKit/Future.swift b/Sources/PromiseKit/Future.swift index c08f1e16..671a09d5 100644 --- a/Sources/PromiseKit/Future.swift +++ b/Sources/PromiseKit/Future.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 04/03/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/PromiseKit/Poll.swift b/Sources/PromiseKit/Poll.swift index 9718db22..ee892619 100644 --- a/Sources/PromiseKit/Poll.swift +++ b/Sources/PromiseKit/Poll.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 23/09/2021. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/PromiseKit/Promise.swift b/Sources/PromiseKit/Promise.swift index f1982fc7..92b23ccd 100644 --- a/Sources/PromiseKit/Promise.swift +++ b/Sources/PromiseKit/Promise.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 28/02/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/PromiseKit/Race.swift b/Sources/PromiseKit/Race.swift index 6295a92d..4977f363 100644 --- a/Sources/PromiseKit/Race.swift +++ b/Sources/PromiseKit/Race.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 26/08/2021. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/PromiseKit/Sequence.swift b/Sources/PromiseKit/Sequence.swift index 64378ce3..67d46b05 100644 --- a/Sources/PromiseKit/Sequence.swift +++ b/Sources/PromiseKit/Sequence.swift @@ -3,7 +3,7 @@ // // // Created by Toni K. Turk on 08/08/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/PromiseKit/Wrap.swift b/Sources/PromiseKit/Wrap.swift index f917fdd1..5a3192da 100644 --- a/Sources/PromiseKit/Wrap.swift +++ b/Sources/PromiseKit/Wrap.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 21/07/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/UI/SwiftUI/Extensions/AnyTransition+PovioKit.swift b/Sources/UI/SwiftUI/Extensions/AnyTransition+PovioKit.swift new file mode 100644 index 00000000..34b76d14 --- /dev/null +++ b/Sources/UI/SwiftUI/Extensions/AnyTransition+PovioKit.swift @@ -0,0 +1,19 @@ +// +// AnyTransition+PovioKit.swift +// PovioKit +// +// Created by Borut Tomazin on 14/05/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +public extension AnyTransition { + /// `slideLeft` is a inverse transition of system `slide` + static var slideLeft: AnyTransition { + .asymmetric( + insertion: .move(edge: .trailing), + removal: .move(edge: .leading) + ) + } +} diff --git a/Sources/UI/SwiftUI/Extensions/Color+PovioKit.swift b/Sources/UI/SwiftUI/Extensions/Color+PovioKit.swift new file mode 100644 index 00000000..8dd84d05 --- /dev/null +++ b/Sources/UI/SwiftUI/Extensions/Color+PovioKit.swift @@ -0,0 +1,46 @@ +// +// Color+PovioKit.swift +// PovioKit +// +// Created by Borut Tomazin on 14/05/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +public extension Color { + /// Initialize Color with `red`, `green` and `blue` components. + /// + /// Example: `Color(red: 0, green: 0, blue: 0)` + init(red: Int, green: Int, blue: Int) { + self.init(red: Double(red) / 255.0, green: Double(green) / 255.0, blue: Double(blue) / 255.0) + } + + /// Initialize Color with given `hex` value. + /// + /// Example: `Color(hex: "000000")` + init(hex: String) { + let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) + var int: UInt64 = 0 + Scanner(string: hex).scanHexInt64(&int) + let alpha, red, green, blue: UInt64 + switch hex.count { + case 3: // RGB (12-bit) + (alpha, red, green, blue) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) + case 6: // RGB (24-bit) + (alpha, red, green, blue) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) + case 8: // ARGB (32-bit) + (alpha, red, green, blue) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) + default: + (alpha, red, green, blue) = (1, 1, 1, 0) + } + + self.init( + .sRGB, + red: Double(red) / 255, + green: Double(green) / 255, + blue: Double(blue) / 255, + opacity: Double(alpha) / 255 + ) + } +} diff --git a/Sources/UI/Extensions/Image+PovioKit.swift b/Sources/UI/SwiftUI/Extensions/Image+PovioKit.swift similarity index 93% rename from Sources/UI/Extensions/Image+PovioKit.swift rename to Sources/UI/SwiftUI/Extensions/Image+PovioKit.swift index 69d673a7..674a1087 100644 --- a/Sources/UI/Extensions/Image+PovioKit.swift +++ b/Sources/UI/SwiftUI/Extensions/Image+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Arlind Dushi on 3/22/22. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import SwiftUI diff --git a/Sources/UI/SwiftUI/Extensions/Text+PovioKit.swift b/Sources/UI/SwiftUI/Extensions/Text+PovioKit.swift new file mode 100644 index 00000000..5e86b482 --- /dev/null +++ b/Sources/UI/SwiftUI/Extensions/Text+PovioKit.swift @@ -0,0 +1,21 @@ +// +// Text+PovioKit.swift +// PovioKit +// +// Created by Yll Fejziu on 27/10/2023. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +public extension Text { + /// Creates an instance of hyperlinked Text using markdown formatting syntac + /// For dynamic strings, the link string has to be converted into an AttributedString + /// https://developer.apple.com/videos/play/wwdc2021/10018/?time=1638 + @available(iOS 15.0, *) + init(_ text: String, link: String) { + let markdownString = "[\(text)](\(link))".toMarkdown() + + self = Text(markdownString) + } +} diff --git a/Sources/UI/SwiftUI/Extensions/View+PovioKit.swift b/Sources/UI/SwiftUI/Extensions/View+PovioKit.swift new file mode 100644 index 00000000..8a6ec67b --- /dev/null +++ b/Sources/UI/SwiftUI/Extensions/View+PovioKit.swift @@ -0,0 +1,26 @@ +// +// View+PovioKit.swift +// PovioKit +// +// Created by Borut Tomazin on 02/03/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +public extension View { + /// Returns square frame for given `size`. + func frame(size: CGFloat? = nil, alignment: Alignment = .center) -> some View { + frame(width: size, height: size, alignment: alignment) + } + + /// Hides view using opacity. + func hidden(_ hidden: Bool) -> some View { + opacity(hidden ? 0 : 1) + } + + /// Disables animation on view. + func noAnimation() -> some View { + animation(nil, value: UUID()) + } +} diff --git a/Sources/UI/SwiftUI/View Modifiers/MeasureSizeModifier.swift b/Sources/UI/SwiftUI/View Modifiers/MeasureSizeModifier.swift new file mode 100644 index 00000000..625dc3d8 --- /dev/null +++ b/Sources/UI/SwiftUI/View Modifiers/MeasureSizeModifier.swift @@ -0,0 +1,49 @@ +// +// MeasureSizeModifier.swift +// PovioKit +// +// Created by Borut Tomazin on 10/02/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +@available(iOS 15.0, *) +public struct MeasureSizeModifier: ViewModifier { + public typealias SizeHandler = (CGSize) -> Void + let onSize: SizeHandler + let isInitialOnly: Bool + + public func body(content: Content) -> some View { + content + .background(GeometryReader { geo in + if isInitialOnly { + Color.clear + .onFirstAppear { + onSize(geo.size) + } + } else { + Color.clear + .onAppear { + onSize(geo.size) + } + .onChange(of: geo.size) { size in + onSize(size) + } + } + }) + } +} + +@available(iOS 15, *) +public extension View { + /// Measure view size everytime it changes + func measureSize(_ handler: @escaping MeasureSizeModifier.SizeHandler) -> some View { + modifier(MeasureSizeModifier(onSize: handler, isInitialOnly: false)) + } + + /// Measure view size only for the first time + func measureInitialSize(_ handler: @escaping MeasureSizeModifier.SizeHandler) -> some View { + modifier(MeasureSizeModifier(onSize: handler, isInitialOnly: true)) + } +} diff --git a/Sources/UI/SwiftUI/View Modifiers/OnFirstAppearModifier.swift b/Sources/UI/SwiftUI/View Modifiers/OnFirstAppearModifier.swift new file mode 100644 index 00000000..165e9d38 --- /dev/null +++ b/Sources/UI/SwiftUI/View Modifiers/OnFirstAppearModifier.swift @@ -0,0 +1,31 @@ +// +// OnFirstAppearModifier.swift +// PovioKit +// +// Created by Borut Tomazin on 10/02/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +public struct OnFirstAppearModifier: ViewModifier { + public typealias VoidHandler = () -> Swift.Void + @State private var didLoad = false + let action: VoidHandler? + + public func body(content: Content) -> some View { + content.onAppear { + guard !didLoad else { return } + didLoad = true + action?() + } + } +} + +public extension View { + /// Modifier action is executed only once per view lifecycle. + /// It differs from `onAppear` modifier which is executed everytime wiew appears on the screen. + func onFirstAppear(perform action: OnFirstAppearModifier.VoidHandler? = nil) -> some View { + modifier(OnFirstAppearModifier(action: action)) + } +} diff --git a/Sources/UI/SwiftUI/View Modifiers/PhotoPickerModifier.swift b/Sources/UI/SwiftUI/View Modifiers/PhotoPickerModifier.swift new file mode 100644 index 00000000..b53ded7a --- /dev/null +++ b/Sources/UI/SwiftUI/View Modifiers/PhotoPickerModifier.swift @@ -0,0 +1,76 @@ +// +// PhotoPickerModifier.swift +// PovioKit +// +// Created by Borut Tomazin on 10/02/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +@available(iOS 15.0, *) +public struct PhotoPickerModifier: ViewModifier { + public typealias VoidHandler = () -> Swift.Void + public typealias ImageHandler = (UIImage) -> Swift.Void + + @Binding var present: Bool + var canRemove: Bool = true + var configuration: Configuration = .init() + var removeHandler: VoidHandler? + let imageHandler: ImageHandler + + @State private var showImageCapture: Bool = false + @State private var showPhotoLibrary: Bool = false + + public func body(content: Content) -> some View { + content + .confirmationDialog("", isPresented: $present) { + Button(configuration.takePhoto) { + showImageCapture.toggle() + } + Button(configuration.chooseFromLibrary) { + showPhotoLibrary.toggle() + } + if canRemove { + Button(configuration.removePhoto, role: .destructive) { + removeHandler?() + } + } + } + .sheet(isPresented: $showPhotoLibrary) { + PhotoPickerView(sourceType: .photoLibrary) { image in + imageHandler(image) + } + .ignoresSafeArea() + } + .fullScreenCover(isPresented: $showImageCapture) { + PhotoPickerView(sourceType: .camera) { image in + imageHandler(image) + } + .ignoresSafeArea() + } + } + + struct Configuration { + var takePhoto: String = "Take a Photo" + var chooseFromLibrary: String = "Choose from Library" + var removePhoto: String = "Remove Photo" + } +} + +@available(iOS 15.0, *) +public extension View { + func photoPicker( + present: Binding, + canRemove: Bool = true, + removeHandler: PhotoPickerModifier.VoidHandler?, + imageHandler: @escaping PhotoPickerModifier.ImageHandler + ) -> some View { + modifier(PhotoPickerModifier( + present: present, + canRemove: canRemove, + removeHandler: removeHandler, + imageHandler: imageHandler + )) + } +} diff --git a/Sources/UI/SwiftUI/View Modifiers/PinchToZoomModifier.swift b/Sources/UI/SwiftUI/View Modifiers/PinchToZoomModifier.swift new file mode 100644 index 00000000..ce730ff8 --- /dev/null +++ b/Sources/UI/SwiftUI/View Modifiers/PinchToZoomModifier.swift @@ -0,0 +1,109 @@ +// +// PinchToZoomModifier.swift +// PovioKit +// +// Created by Yll Fejziu on 13/05/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +/// https://stackoverflow.com/a/59878898 +@available(iOS 15.0, *) +public struct PinchToZoomModifier: ViewModifier { + @StateObject private var viewModel = PinchZoomViewModel() + + public func body(content: Content) -> some View { + content + .scaleEffect(viewModel.scale, anchor: viewModel.anchor) + .offset(viewModel.offset) + .animation(viewModel.isPinching ? .none : .spring(), value: viewModel.scale) + .overlay( + PinchZoom(viewModel: viewModel) + ) + } +} + +@available(iOS 15.0, *) +public extension View { + func pinchToZoom() -> some View { + self.modifier(PinchToZoomModifier()) + } +} + +// MARK: - Private +private class PinchZoomViewModel: ObservableObject { + @Published var scale: CGFloat = 1.0 + @Published var anchor: UnitPoint = .center + @Published var offset: CGSize = .zero + @Published var isPinching: Bool = false + var startLocation: CGPoint = .zero + var location: CGPoint = .zero + var numberOfTouches: Int = 0 +} + +private class PinchZoomView: UIView { + var viewModel: PinchZoomViewModel + + init(viewModel: PinchZoomViewModel) { + self.viewModel = viewModel + super.init(frame: .zero) + + let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(pinch(gesture:))) + pinchGesture.cancelsTouchesInView = false + addGestureRecognizer(pinchGesture) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func pinch(gesture: UIPinchGestureRecognizer) { + switch gesture.state { + case .began: + viewModel.isPinching = true + viewModel.startLocation = gesture.location(in: self) + viewModel.anchor = UnitPoint(x: viewModel.startLocation.x / bounds.width, + y: viewModel.startLocation.y / bounds.height) + viewModel.numberOfTouches = gesture.numberOfTouches + case .changed: + if gesture.numberOfTouches != viewModel.numberOfTouches { + // If the number of fingers being used changes, the start location needs to be adjusted to avoid jumping. + let newLocation = gesture.location(in: self) + let jumpDifference = CGSize(width: newLocation.x - viewModel.location.x, + height: newLocation.y - viewModel.location.y) + viewModel.startLocation = CGPoint( + x: viewModel.startLocation.x + jumpDifference.width, + y: viewModel.startLocation.y + jumpDifference.height + ) + viewModel.numberOfTouches = gesture.numberOfTouches + } + viewModel.scale = gesture.scale + viewModel.location = gesture.location(in: self) + viewModel.offset = CGSize( + width: viewModel.location.x - viewModel.startLocation.x, + height: viewModel.location.y - viewModel.startLocation.y + ) + case .ended, .cancelled, .failed: + viewModel.isPinching = false + viewModel.scale = 1.0 + viewModel.anchor = .center + viewModel.offset = .zero + default: + break + } + } +} + +private struct PinchZoom: UIViewRepresentable { + @ObservedObject var viewModel: PinchZoomViewModel + + func makeUIView(context: Context) -> PinchZoomView { + .init(viewModel: viewModel) + } + + func updateUIView(_ uiView: PinchZoomView, context: Context) { + // state is automatically updated via ViewModel binding + } +} diff --git a/Sources/UI/SwiftUI/View Modifiers/SquaredModifier.swift b/Sources/UI/SwiftUI/View Modifiers/SquaredModifier.swift new file mode 100644 index 00000000..c1401da3 --- /dev/null +++ b/Sources/UI/SwiftUI/View Modifiers/SquaredModifier.swift @@ -0,0 +1,33 @@ +// +// SquaredModifier.swift +// PovioKit +// +// Created by Borut Tomazin on 10/02/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +public struct SquaredModifier: ViewModifier { + var cornerRadius: CGFloat = 0 + var aspectRatio: CGFloat = 1 + + public func body(content: Content) -> some View { + content + .frame( + minWidth: 0, + maxWidth: .infinity, + minHeight: 0, + maxHeight: .infinity + ) + .aspectRatio(aspectRatio, contentMode: .fit) + .clipShape(RoundedRectangle(cornerRadius: cornerRadius)) + } +} + +public extension View { + /// Makes view squared + func squared(cornerRadius: CGFloat = 0, aspectRatio: CGFloat = 1) -> some View { + modifier(SquaredModifier(cornerRadius: cornerRadius, aspectRatio: aspectRatio)) + } +} diff --git a/Sources/UI/SwiftUI/View Modifiers/TextFieldLimitModifer.swift b/Sources/UI/SwiftUI/View Modifiers/TextFieldLimitModifer.swift new file mode 100644 index 00000000..ca026b04 --- /dev/null +++ b/Sources/UI/SwiftUI/View Modifiers/TextFieldLimitModifer.swift @@ -0,0 +1,31 @@ +// +// TextFieldLimitModifer.swift +// PovioKit +// +// Created by Dejan Skledar on 29/12/2023. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +@available(iOS 15.0, *) +public struct TextFieldLimitModifer: ViewModifier { + @Binding var text: String + let limit: Int + + public func body(content: Content) -> some View { + content + .onChange(of: text) { newValue in + guard newValue.count > limit else { return } + text = String(newValue.prefix(limit)) + } + } +} + +@available(iOS 15.0, *) +public extension View { + /// Limit input length + func limitInput(text: Binding, limit: Int) -> some View { + modifier(TextFieldLimitModifer(text: text, limit: limit)) + } +} diff --git a/Sources/UI/ActionButton/ActionButton.swift b/Sources/UI/SwiftUI/Views/ActionButton/ActionButton.swift similarity index 99% rename from Sources/UI/ActionButton/ActionButton.swift rename to Sources/UI/SwiftUI/Views/ActionButton/ActionButton.swift index 3cee0373..479f7639 100644 --- a/Sources/UI/ActionButton/ActionButton.swift +++ b/Sources/UI/SwiftUI/Views/ActionButton/ActionButton.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Arlind Dushi on 3/17/22. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import SwiftUI diff --git a/Sources/UI/SwiftUI/Views/PhotoPickerView/PhotoPickerView.swift b/Sources/UI/SwiftUI/Views/PhotoPickerView/PhotoPickerView.swift new file mode 100644 index 00000000..455e013c --- /dev/null +++ b/Sources/UI/SwiftUI/Views/PhotoPickerView/PhotoPickerView.swift @@ -0,0 +1,54 @@ +// +// PhotoPickerView.swift +// PovioKit +// +// Created by Borut Tomazin on 10/02/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI +import UIKit + +/// This view should be used in conjuction with `PhotoPicker` view modifier. +public struct PhotoPickerView: UIViewControllerRepresentable { + let sourceType: UIImagePickerController.SourceType + let onComplete: (UIImage) -> Void + + public func makeUIViewController(context: Context) -> UIImagePickerController { + let imagePicker = UIImagePickerController() + imagePicker.sourceType = sourceType + imagePicker.delegate = context.coordinator + return imagePicker + } + + public func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) { /* --- */ } + + public func makeCoordinator() -> Coordinator { + Coordinator(onComplete: onComplete) + } +} + +// MARK: - Coordinator +public extension PhotoPickerView { + final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate { + let onComplete: (UIImage) -> Void + + public init(onComplete: @escaping (UIImage) -> Void) { + self.onComplete = onComplete + } + + public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { + guard let image = info[.originalImage] as? UIImage else { + picker.dismiss(animated: true) + return + } + picker.dismiss(animated: true) { + self.onComplete(image) + } + } + + public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { + picker.dismiss(animated: true) + } + } +} diff --git a/Sources/UI/ProfileImageView/ProfileImageView.swift b/Sources/UI/SwiftUI/Views/ProfileImageView/ProfileImageView.swift similarity index 92% rename from Sources/UI/ProfileImageView/ProfileImageView.swift rename to Sources/UI/SwiftUI/Views/ProfileImageView/ProfileImageView.swift index 6ade3ce2..4fa9fb8e 100644 --- a/Sources/UI/ProfileImageView/ProfileImageView.swift +++ b/Sources/UI/SwiftUI/Views/ProfileImageView/ProfileImageView.swift @@ -3,10 +3,11 @@ // PovioKit // // Created by Arlind Dushi on 3/9/22. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import SwiftUI +import PovioKitCore public struct ProfileImageView: View { @ObservedObject private var properties = Properties() @@ -20,9 +21,11 @@ public struct ProfileImageView: View { GeometryReader { geo in ZStack(alignment: properties.badging.alignment) { ImageView(properties: properties, profileTapped: triggerImageTapClosure) - BadgeView(style: properties.badging, - size: .init(width: geo.size.width / 5, height: geo.size.height / 5), - badgeTapped: tiggerBadgeTapClosure) + BadgeView( + style: properties.badging, + size: .init(width: geo.size.width / 5, height: geo.size.height / 5), + badgeTapped: tiggerBadgeTapClosure + ) } } } @@ -109,11 +112,17 @@ private extension ProfileImageView { GeometryReader { geo in switch (geo.size.height == geo.size.width) { case true: - Circle().stroke(properties.borderColor, - lineWidth: properties.borderWidth) + Circle() + .stroke( + properties.borderColor, + lineWidth: properties.borderWidth + ) case false: RoundedRectangle(cornerRadius: getCornerRadius(for: properties.cornerRadius)) - .stroke(properties.borderColor, lineWidth: properties.borderWidth) + .stroke( + properties.borderColor, + lineWidth: properties.borderWidth + ) } } } @@ -123,7 +132,11 @@ private extension ProfileImageView { return unwrappedPlaceholder } - return Image(uiImage: UIImage()) +#if os(iOS) + return Image(uiImage: UIImage()) +#elseif os(macOS) + return Image(nsImage: NSImage()) +#endif } func getCornerRadius(for cornerType: ProfileImageView.CornerRadiusType) -> CGFloat { @@ -142,8 +155,8 @@ private extension ProfileImageView { var badgeTapped: (() -> Void) - init?(style: BadgingMode, - size: CGSize, + init?(style: BadgingMode, + size: CGSize, badgeTapped: @escaping () -> ()) { self.badgeTapped = badgeTapped @@ -190,7 +203,8 @@ public extension ProfileImageView { backgroundColor: Color, alignment: Alignment, borderColor: Color? = nil, - borderWidth: CGFloat? = nil) { + borderWidth: CGFloat? = nil + ) { self.image = image self.contentMode = contentMode self.tintColor = tintColor diff --git a/Sources/UI/ProfileImageView/URLImageModel.swift b/Sources/UI/SwiftUI/Views/ProfileImageView/URLImageModel.swift similarity index 73% rename from Sources/UI/ProfileImageView/URLImageModel.swift rename to Sources/UI/SwiftUI/Views/ProfileImageView/URLImageModel.swift index 97525bb8..ad6cff74 100644 --- a/Sources/UI/ProfileImageView/URLImageModel.swift +++ b/Sources/UI/SwiftUI/Views/ProfileImageView/URLImageModel.swift @@ -3,14 +3,19 @@ // PovioKit // // Created by Arlind Dushi on 3/22/22. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit +public typealias ImageContainer = UIImage +#elseif os(macOS) +public typealias ImageContainer = NSImage +#endif import SwiftUI class URLImageModel: ObservableObject { - @Published var image: UIImage? + @Published var image: ImageContainer? var url: URL? init(url: URL?) { @@ -33,11 +38,10 @@ class URLImageModel: ObservableObject { guard let data = data, error == nil else { return } DispatchQueue.main.async { - guard let loadedImage = UIImage(data: data) else { + guard let loadedImage = ImageContainer(data: data) else { return } self.image = loadedImage } } } - diff --git a/Sources/UI/ProfileImageView/URLImageView.swift b/Sources/UI/SwiftUI/Views/ProfileImageView/URLImageView.swift similarity index 65% rename from Sources/UI/ProfileImageView/URLImageView.swift rename to Sources/UI/SwiftUI/Views/ProfileImageView/URLImageView.swift index a180e828..079755aa 100644 --- a/Sources/UI/ProfileImageView/URLImageView.swift +++ b/Sources/UI/SwiftUI/Views/ProfileImageView/URLImageView.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Arlind Dushi on 3/23/22. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import SwiftUI @@ -22,15 +22,23 @@ struct URLImageView: View { .resizable() } - func createImage(_ image: UIImage?, placeholder: Image?) -> Image { + func createImage(_ image: ImageContainer?, placeholder: Image?) -> Image { if let fetchedImage = image { +#if os(iOS) return Image(uiImage: fetchedImage) +#elseif os(macOS) + return Image(nsImage: fetchedImage) +#endif } if let placeholder = placeholder { return placeholder } - return Image(uiImage: UIImage()) +#if os(iOS) + return Image(uiImage: ImageContainer()) +#elseif os(macOS) + return Image(nsImage: ImageContainer()) +#endif } } diff --git a/Sources/UI/SwiftUI/Views/ProgressStyle/ProgressStyle.swift b/Sources/UI/SwiftUI/Views/ProgressStyle/ProgressStyle.swift new file mode 100644 index 00000000..e126ae30 --- /dev/null +++ b/Sources/UI/SwiftUI/Views/ProgressStyle/ProgressStyle.swift @@ -0,0 +1,38 @@ +// +// ProgressStyle.swift +// PovioKit +// +// Created by Borut Tomazin on 02/03/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + + +import SwiftUI + +@available(iOS 15.0, *) +public struct ProgressStyle: ProgressViewStyle { + var trackColor: Color = .gray + var progressColor: Color = .black + var cornerRadius: CGFloat = 8 + + public func makeBody(configuration: Configuration) -> some View { + let completed = configuration.fractionCompleted ?? 0 + return GeometryReader { geo in + ZStack(alignment: .leading) { + RoundedRectangle(cornerRadius: cornerRadius) + .fill(trackColor) + RoundedRectangle(cornerRadius: cornerRadius) + .fill(progressColor) + .frame(width: completed * geo.size.width) + } + } + } +} + +@available(iOS 15.0, *) +#Preview { + ProgressView(value: 0.5) + .progressViewStyle(ProgressStyle()) + .frame(height: 5) + .padding(.horizontal, 20) +} diff --git a/Sources/UI/SwiftUI/Views/RemoteImage/RemoteImage.swift b/Sources/UI/SwiftUI/Views/RemoteImage/RemoteImage.swift new file mode 100644 index 00000000..0c35171a --- /dev/null +++ b/Sources/UI/SwiftUI/Views/RemoteImage/RemoteImage.swift @@ -0,0 +1,41 @@ +// +// RemoteImage.swift +// PovioKit +// +// Created by Borut Tomazin on 02/03/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +#if canImport(Kingfisher) +import Kingfisher +import SwiftUI + +@available(iOS 15.0, *) +public struct RemoteImage: View { + private let url: URL? + private let placeholder: Placeholder? + + public init(url: URL?, @ViewBuilder _ placeholder: @escaping () -> Placeholder) { + self.url = url + self.placeholder = placeholder() + } + + public init(url: URL?) { + self.url = url + self.placeholder = nil + } + + public var body: some View { + if let url { + KFImage(url) + .placeholder { + placeholder + } + .resizable() + .scaledToFill() + } else { + placeholder + } + } +} +#endif diff --git a/Sources/UI/SwiftUI/Views/ScrollViewWithOffset/ScrollViewWithOffset.swift b/Sources/UI/SwiftUI/Views/ScrollViewWithOffset/ScrollViewWithOffset.swift new file mode 100644 index 00000000..fbbe6c9a --- /dev/null +++ b/Sources/UI/SwiftUI/Views/ScrollViewWithOffset/ScrollViewWithOffset.swift @@ -0,0 +1,87 @@ +// +// ScrollViewWithOffset.swift +// PovioKit +// +// Created by Borut Tomazin on 10/02/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +import SwiftUI + +/// This scroll view wraps a native `ScrollView` and tracks its +/// scroll offset as it scrolls. +/// +/// You can use the `onScroll` initializer parameter to provide +/// a function that will be called whenever the view scrolls. +/// +/// Source: https://github.com/danielsaidi/ScrollKit/blob/main/Sources/ScrollKit/ScrollViewWithOffset.swift +@available(iOS 15.0, *) +public struct ScrollViewWithOffset: View { + /** + Create a scroll view with offset tracking. + + - Parameters: + - axes: The scroll axes to use, by default `.vertical`. + - showsIndicators: Whether or not to show scroll indicators, by default `true`. + - onScroll: An action that will be called whenever the scroll offset changes, by default `nil`. + - content: The scroll view content. + */ + public init( + _ axes: Axis.Set = .vertical, + showsIndicators: Bool = true, + onScroll: ScrollAction? = nil, + @ViewBuilder content: @escaping () -> Content + ) { + self.axes = axes + self.showsIndicators = showsIndicators + self.onScroll = onScroll ?? { _ in } + self.content = content + } + + private let axes: Axis.Set + private let showsIndicators: Bool + private let onScroll: ScrollAction + private let content: () -> Content + + public typealias ScrollAction = (_ offset: CGPoint) -> Void + + public var body: some View { + ScrollView(axes, showsIndicators: showsIndicators) { + ZStack(alignment: .top) { + ScrollViewOffsetTracker() + content() + } + }.withOffsetTracking(action: onScroll) + } +} + +private struct ScrollViewOffsetTracker: View { + var body: some View { + GeometryReader { geo in + Color.clear + .preference( + key: ScrollOffsetPreferenceKey.self, + value: geo.frame(in: .named(ScrollOffsetNamespace.namespace)).origin + ) + } + .frame(height: 0) + } +} + +private extension ScrollView { + func withOffsetTracking( + action: @escaping (_ offset: CGPoint) -> Void + ) -> some View { + self.coordinateSpace(name: ScrollOffsetNamespace.namespace) + .onPreferenceChange(ScrollOffsetPreferenceKey.self, perform: action) + } +} + +private enum ScrollOffsetNamespace { + static let namespace = "scrollView" +} + +private struct ScrollOffsetPreferenceKey: PreferenceKey { + static var defaultValue: CGPoint = .zero + static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) { /* no impl */ } +} diff --git a/Sources/UI/DynamicCollectionCell/DynamicCollectionCell.swift b/Sources/UI/UIKit/DynamicCollectionCell/DynamicCollectionCell.swift similarity index 94% rename from Sources/UI/DynamicCollectionCell/DynamicCollectionCell.swift rename to Sources/UI/UIKit/DynamicCollectionCell/DynamicCollectionCell.swift index 08974609..447fe928 100644 --- a/Sources/UI/DynamicCollectionCell/DynamicCollectionCell.swift +++ b/Sources/UI/UIKit/DynamicCollectionCell/DynamicCollectionCell.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Borut Tomazin on 20/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit open class DynamicCollectionCell: UICollectionViewCell { @@ -33,3 +34,5 @@ public extension DynamicCollectionCell { case horizontal } } + +#endif diff --git a/Sources/UI/GradientView/GradientView.swift b/Sources/UI/UIKit/GradientView/GradientView.swift similarity index 97% rename from Sources/UI/GradientView/GradientView.swift rename to Sources/UI/UIKit/GradientView/GradientView.swift index 31f7dae7..1f29af81 100644 --- a/Sources/UI/GradientView/GradientView.swift +++ b/Sources/UI/UIKit/GradientView/GradientView.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Domagoj Kulundzic on 01/05/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public class GradientView: UIView { @@ -92,3 +93,5 @@ private extension GradientView { layer.insertSublayer(gradientLayer, at: 0) } } + +#endif diff --git a/Sources/UI/PaddingLabel/PaddingLabel.swift b/Sources/UI/UIKit/PaddingLabel/PaddingLabel.swift similarity index 92% rename from Sources/UI/PaddingLabel/PaddingLabel.swift rename to Sources/UI/UIKit/PaddingLabel/PaddingLabel.swift index 4eb57794..e118faf6 100644 --- a/Sources/UI/PaddingLabel/PaddingLabel.swift +++ b/Sources/UI/UIKit/PaddingLabel/PaddingLabel.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Borut Tomažin on 13/05/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit /// A UILabel subclass with configurable `contentInset`. @@ -29,3 +30,5 @@ open class PaddingLabel: UILabel { return contentSize } } + +#endif diff --git a/Sources/UI/TextField/TextField.swift b/Sources/UI/UIKit/TextField/TextField.swift similarity index 98% rename from Sources/UI/TextField/TextField.swift rename to Sources/UI/UIKit/TextField/TextField.swift index 9857563d..2404de35 100644 --- a/Sources/UI/TextField/TextField.swift +++ b/Sources/UI/UIKit/TextField/TextField.swift @@ -3,11 +3,13 @@ // PovioKit // // Created by Arlind Dushi on 01/20/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit import PovioKitCore +import PovioKitUtilities public protocol RuleValidatable { var error: String { get } @@ -275,3 +277,5 @@ private extension TextField { .create() } } + +#endif diff --git a/Sources/Core/Utilities/AppVersionValidator/AppVersionValidator.swift b/Sources/Utilities/AppVersionValidator/AppVersionValidator.swift similarity index 100% rename from Sources/Core/Utilities/AppVersionValidator/AppVersionValidator.swift rename to Sources/Utilities/AppVersionValidator/AppVersionValidator.swift diff --git a/Sources/Core/Utilities/AttributedStringBuilder/AttributedStringBuilder.swift b/Sources/Utilities/AttributedStringBuilder/AttributedStringBuilder.swift similarity index 98% rename from Sources/Core/Utilities/AttributedStringBuilder/AttributedStringBuilder.swift rename to Sources/Utilities/AttributedStringBuilder/AttributedStringBuilder.swift index aacbf3e0..c1320930 100644 --- a/Sources/Core/Utilities/AttributedStringBuilder/AttributedStringBuilder.swift +++ b/Sources/Utilities/AttributedStringBuilder/AttributedStringBuilder.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Toni Kocjan on 26/04/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public protocol BuilderCompatible: AnyObject { @@ -215,3 +216,4 @@ private extension Builder { return true } } +#endif diff --git a/Sources/Core/Utilities/AttributedStringBuilder/UILabel+BuilderCompatible.swift b/Sources/Utilities/AttributedStringBuilder/UILabel+BuilderCompatible.swift similarity index 66% rename from Sources/Core/Utilities/AttributedStringBuilder/UILabel+BuilderCompatible.swift rename to Sources/Utilities/AttributedStringBuilder/UILabel+BuilderCompatible.swift index 17c4ee1d..5b580b3f 100644 --- a/Sources/Core/Utilities/AttributedStringBuilder/UILabel+BuilderCompatible.swift +++ b/Sources/Utilities/AttributedStringBuilder/UILabel+BuilderCompatible.swift @@ -3,9 +3,12 @@ // PovioKit // // Created by Povio on 26/04/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit extension UILabel: BuilderCompatible {} + +#endif diff --git a/Sources/Core/Utilities/AttributedStringBuilder/UITextField+BuilderCompatible.swift b/Sources/Utilities/AttributedStringBuilder/UITextField+BuilderCompatible.swift similarity index 67% rename from Sources/Core/Utilities/AttributedStringBuilder/UITextField+BuilderCompatible.swift rename to Sources/Utilities/AttributedStringBuilder/UITextField+BuilderCompatible.swift index 292831c1..cef48237 100644 --- a/Sources/Core/Utilities/AttributedStringBuilder/UITextField+BuilderCompatible.swift +++ b/Sources/Utilities/AttributedStringBuilder/UITextField+BuilderCompatible.swift @@ -3,9 +3,12 @@ // PovioKit // // Created by Povio on 26/04/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit extension UITextField: BuilderCompatible {} + +#endif diff --git a/Sources/Core/Utilities/Broadcast/Broadcast.swift b/Sources/Utilities/Broadcast/Broadcast.swift similarity index 100% rename from Sources/Core/Utilities/Broadcast/Broadcast.swift rename to Sources/Utilities/Broadcast/Broadcast.swift diff --git a/Sources/Core/Utilities/BundleReader/BundleReader.swift b/Sources/Utilities/BundleReader/BundleReader.swift similarity index 89% rename from Sources/Core/Utilities/BundleReader/BundleReader.swift rename to Sources/Utilities/BundleReader/BundleReader.swift index a7057a96..6672e287 100644 --- a/Sources/Core/Utilities/BundleReader/BundleReader.swift +++ b/Sources/Utilities/BundleReader/BundleReader.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Egzon Arifi on 31/03/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/UI/Camera/Camera+PovioKit.swift b/Sources/Utilities/Camera/Camera+PovioKit.swift similarity index 94% rename from Sources/UI/Camera/Camera+PovioKit.swift rename to Sources/Utilities/Camera/Camera+PovioKit.swift index e5ded7c2..ba2bfe06 100644 --- a/Sources/UI/Camera/Camera+PovioKit.swift +++ b/Sources/Utilities/Camera/Camera+PovioKit.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Ndriqim Nagavci on 21/10/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import AVFoundation diff --git a/Sources/UI/Camera/Camera.swift b/Sources/Utilities/Camera/Camera.swift similarity index 97% rename from Sources/UI/Camera/Camera.swift rename to Sources/Utilities/Camera/Camera.swift index d48169a9..145cb001 100644 --- a/Sources/UI/Camera/Camera.swift +++ b/Sources/Utilities/Camera/Camera.swift @@ -3,11 +3,10 @@ // PovioKit // // Created by Ndriqim Nagavci on 13/10/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import AVFoundation -import PovioKitCore public class Camera: NSObject { var device: AVCaptureDevice? { diff --git a/Sources/UI/Camera/CameraService.swift b/Sources/Utilities/Camera/CameraService.swift similarity index 96% rename from Sources/UI/Camera/CameraService.swift rename to Sources/Utilities/Camera/CameraService.swift index fe8e9dbc..0342ab26 100644 --- a/Sources/UI/Camera/CameraService.swift +++ b/Sources/Utilities/Camera/CameraService.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Ndriqim Nagavci on 13/10/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import AVFoundation.AVMediaFormat diff --git a/Sources/UI/Camera/PhotoCamera.swift b/Sources/Utilities/Camera/PhotoCamera.swift similarity index 98% rename from Sources/UI/Camera/PhotoCamera.swift rename to Sources/Utilities/Camera/PhotoCamera.swift index b35d6168..aaf27410 100644 --- a/Sources/UI/Camera/PhotoCamera.swift +++ b/Sources/Utilities/Camera/PhotoCamera.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Ndriqim Nagavci on 13/10/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import AVFoundation import UIKit @@ -128,3 +129,5 @@ private extension PhotoCamera { session.commitConfiguration() } } + +#endif diff --git a/Sources/UI/Camera/QRCodeScanner.swift b/Sources/Utilities/Camera/QRCodeScanner.swift similarity index 97% rename from Sources/UI/Camera/QRCodeScanner.swift rename to Sources/Utilities/Camera/QRCodeScanner.swift index 2f5a0a44..e034cec1 100644 --- a/Sources/UI/Camera/QRCodeScanner.swift +++ b/Sources/Utilities/Camera/QRCodeScanner.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Ndriqim Nagavci on 13/10/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import AVFoundation diff --git a/Sources/Core/Utilities/ColorInterpolator/ColorInterpolator.swift b/Sources/Utilities/ColorInterpolator/ColorInterpolator.swift similarity index 96% rename from Sources/Core/Utilities/ColorInterpolator/ColorInterpolator.swift rename to Sources/Utilities/ColorInterpolator/ColorInterpolator.swift index 71fec22f..499e9658 100644 --- a/Sources/Core/Utilities/ColorInterpolator/ColorInterpolator.swift +++ b/Sources/Utilities/ColorInterpolator/ColorInterpolator.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Toni Kocjan on 11/02/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public protocol ColorInterpolator { @@ -60,3 +61,5 @@ public extension LinearColorInterpolator { case indexOutOfBounds } } + +#endif diff --git a/Sources/Core/Utilities/Delegated/Delegated.swift b/Sources/Utilities/Delegated/Delegated.swift similarity index 96% rename from Sources/Core/Utilities/Delegated/Delegated.swift rename to Sources/Utilities/Delegated/Delegated.swift index 1e38fcee..63784d69 100644 --- a/Sources/Core/Utilities/Delegated/Delegated.swift +++ b/Sources/Utilities/Delegated/Delegated.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 20/07/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/DispatchTimer/DispatchTimer.swift b/Sources/Utilities/DispatchTimer/DispatchTimer.swift similarity index 96% rename from Sources/Core/Utilities/DispatchTimer/DispatchTimer.swift rename to Sources/Utilities/DispatchTimer/DispatchTimer.swift index 843fcbf7..cc11c5b4 100644 --- a/Sources/Core/Utilities/DispatchTimer/DispatchTimer.swift +++ b/Sources/Utilities/DispatchTimer/DispatchTimer.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Borut Tomažin on 11/12/2018. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/Exif/Exif.swift b/Sources/Utilities/Exif/Exif.swift similarity index 98% rename from Sources/Core/Utilities/Exif/Exif.swift rename to Sources/Utilities/Exif/Exif.swift index 75369e67..10af20e9 100644 --- a/Sources/Core/Utilities/Exif/Exif.swift +++ b/Sources/Utilities/Exif/Exif.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Marko Mijatovic on 16/02/2023. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/Exif/ExifError.swift b/Sources/Utilities/Exif/ExifError.swift similarity index 83% rename from Sources/Core/Utilities/Exif/ExifError.swift rename to Sources/Utilities/Exif/ExifError.swift index 542b5850..3f890f20 100644 --- a/Sources/Core/Utilities/Exif/ExifError.swift +++ b/Sources/Utilities/Exif/ExifError.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Marko Mijatovic on 17/02/2023. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/Exif/ExifImageSource.swift b/Sources/Utilities/Exif/ExifImageSource.swift similarity index 92% rename from Sources/Core/Utilities/Exif/ExifImageSource.swift rename to Sources/Utilities/Exif/ExifImageSource.swift index 626062ab..e310696d 100644 --- a/Sources/Core/Utilities/Exif/ExifImageSource.swift +++ b/Sources/Utilities/Exif/ExifImageSource.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Marko Mijatovic on 17/02/2023. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/ImageSource/ImageSource.swift b/Sources/Utilities/ImageSource/ImageSource.swift similarity index 96% rename from Sources/Core/Utilities/ImageSource/ImageSource.swift rename to Sources/Utilities/ImageSource/ImageSource.swift index 70fa0e58..a2f93700 100644 --- a/Sources/Core/Utilities/ImageSource/ImageSource.swift +++ b/Sources/Utilities/ImageSource/ImageSource.swift @@ -3,9 +3,10 @@ // PovioKit // // Created by Toni Kocjan on 26/07/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import UIKit public enum ImageSource { @@ -73,3 +74,5 @@ public extension UIButton { } } #endif + +#endif diff --git a/Sources/Core/Utilities/InAppPurchase/InAppPurchaseError.swift b/Sources/Utilities/InAppPurchase/InAppPurchaseError.swift similarity index 87% rename from Sources/Core/Utilities/InAppPurchase/InAppPurchaseError.swift rename to Sources/Utilities/InAppPurchase/InAppPurchaseError.swift index 5fb2ece4..47838bd1 100644 --- a/Sources/Core/Utilities/InAppPurchase/InAppPurchaseError.swift +++ b/Sources/Utilities/InAppPurchase/InAppPurchaseError.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Marko Mijatovic on 19/01/2023. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/InAppPurchase/InAppPurchaseService.swift b/Sources/Utilities/InAppPurchase/InAppPurchaseService.swift similarity index 98% rename from Sources/Core/Utilities/InAppPurchase/InAppPurchaseService.swift rename to Sources/Utilities/InAppPurchase/InAppPurchaseService.swift index 04856c58..7f978ef2 100644 --- a/Sources/Core/Utilities/InAppPurchase/InAppPurchaseService.swift +++ b/Sources/Utilities/InAppPurchase/InAppPurchaseService.swift @@ -3,13 +3,13 @@ // PovioKit // // Created by Marko Mijatovic on 20/01/2023. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation +import PovioKitCore import StoreKit - @available(iOS 15.0, *) public final class InAppPurchaseService: NSObject { public typealias IAPProduct = String @@ -117,7 +117,7 @@ extension InAppPurchaseService { public func restorePurchases() async -> Result { do { try await AppStore.sync() - return .success() + return .success(()) } catch { return .failure(InAppPurchaseError.restoreFailed(error)) } diff --git a/Sources/Core/Utilities/MediaPlayer/AudioPlayer.swift b/Sources/Utilities/MediaPlayer/AudioPlayer.swift similarity index 100% rename from Sources/Core/Utilities/MediaPlayer/AudioPlayer.swift rename to Sources/Utilities/MediaPlayer/AudioPlayer.swift diff --git a/Sources/Core/Utilities/MediaPlayer/MediaPlayer+Models.swift b/Sources/Utilities/MediaPlayer/MediaPlayer+Models.swift similarity index 100% rename from Sources/Core/Utilities/MediaPlayer/MediaPlayer+Models.swift rename to Sources/Utilities/MediaPlayer/MediaPlayer+Models.swift diff --git a/Sources/Core/Utilities/MediaPlayer/MediaPlayer.swift b/Sources/Utilities/MediaPlayer/MediaPlayer.swift similarity index 99% rename from Sources/Core/Utilities/MediaPlayer/MediaPlayer.swift rename to Sources/Utilities/MediaPlayer/MediaPlayer.swift index 9289f08b..0015e819 100644 --- a/Sources/Core/Utilities/MediaPlayer/MediaPlayer.swift +++ b/Sources/Utilities/MediaPlayer/MediaPlayer.swift @@ -7,6 +7,7 @@ // import AVKit +import PovioKitCore public protocol MediaPlayerDelegate: AnyObject { func mediaPlayer(didBeginPlayback player: MediaPlayer) diff --git a/Sources/Core/Utilities/MediaPlayer/MediaStream.swift b/Sources/Utilities/MediaPlayer/MediaStream.swift similarity index 100% rename from Sources/Core/Utilities/MediaPlayer/MediaStream.swift rename to Sources/Utilities/MediaPlayer/MediaStream.swift diff --git a/Sources/Core/Utilities/Money/Money+Currency.swift b/Sources/Utilities/Money/Money+Currency.swift similarity index 94% rename from Sources/Core/Utilities/Money/Money+Currency.swift rename to Sources/Utilities/Money/Money+Currency.swift index 5ae3b998..bfaf3d1c 100644 --- a/Sources/Core/Utilities/Money/Money+Currency.swift +++ b/Sources/Utilities/Money/Money+Currency.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Marko Mijatovic on 04/06/2022. -// Copyright © 2023 Povio Labs. All rights reserved. +// Copyright © 2024 Povio Labs. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/Money/Money+Defaults.swift b/Sources/Utilities/Money/Money+Defaults.swift similarity index 87% rename from Sources/Core/Utilities/Money/Money+Defaults.swift rename to Sources/Utilities/Money/Money+Defaults.swift index 7475df96..b76dd54f 100644 --- a/Sources/Core/Utilities/Money/Money+Defaults.swift +++ b/Sources/Utilities/Money/Money+Defaults.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni K. Turk on 19/04/2022. -// Copyright © 2023 Povio Labs. All rights reserved. +// Copyright © 2024 Povio Labs. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/Money/Money+Extensions.swift b/Sources/Utilities/Money/Money+Extensions.swift similarity index 96% rename from Sources/Core/Utilities/Money/Money+Extensions.swift rename to Sources/Utilities/Money/Money+Extensions.swift index 44fff959..b94920b2 100644 --- a/Sources/Core/Utilities/Money/Money+Extensions.swift +++ b/Sources/Utilities/Money/Money+Extensions.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Marko Mijatovic on 04/07/2022. -// Copyright © 2023 Povio Labs. All rights reserved. +// Copyright © 2024 Povio Labs. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/Money/Money.swift b/Sources/Utilities/Money/Money.swift similarity index 99% rename from Sources/Core/Utilities/Money/Money.swift rename to Sources/Utilities/Money/Money.swift index 30489709..7065c2ed 100644 --- a/Sources/Core/Utilities/Money/Money.swift +++ b/Sources/Utilities/Money/Money.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Marko Mijatovic on 04/05/2022. -// Copyright © 2023 Povio Labs. All rights reserved. +// Copyright © 2024 Povio Labs. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/PropertyWrapper/UserDefault.swift b/Sources/Utilities/PropertyWrapper/UserDefault.swift similarity index 94% rename from Sources/Core/Utilities/PropertyWrapper/UserDefault.swift rename to Sources/Utilities/PropertyWrapper/UserDefault.swift index 66d3ff5a..d66b21c5 100644 --- a/Sources/Core/Utilities/PropertyWrapper/UserDefault.swift +++ b/Sources/Utilities/PropertyWrapper/UserDefault.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Egzon Arifi on 25/01/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/PropertyWrapper/XCConfigValue.swift b/Sources/Utilities/PropertyWrapper/XCConfigValue.swift similarity index 95% rename from Sources/Core/Utilities/PropertyWrapper/XCConfigValue.swift rename to Sources/Utilities/PropertyWrapper/XCConfigValue.swift index fdd4d7e5..52638ab1 100644 --- a/Sources/Core/Utilities/PropertyWrapper/XCConfigValue.swift +++ b/Sources/Utilities/PropertyWrapper/XCConfigValue.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Egzon Arifi on 30/03/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/StartupService/StartupProcess.swift b/Sources/Utilities/StartupService/StartupProcess.swift similarity index 87% rename from Sources/Core/Utilities/StartupService/StartupProcess.swift rename to Sources/Utilities/StartupService/StartupProcess.swift index 302ba6b5..abe97532 100644 --- a/Sources/Core/Utilities/StartupService/StartupProcess.swift +++ b/Sources/Utilities/StartupService/StartupProcess.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Domagoj Kulundzic on 26/04/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/StartupService/StartupProcessService.swift b/Sources/Utilities/StartupService/StartupProcessService.swift similarity index 86% rename from Sources/Core/Utilities/StartupService/StartupProcessService.swift rename to Sources/Utilities/StartupService/StartupProcessService.swift index d83855d2..ee647670 100644 --- a/Sources/Core/Utilities/StartupService/StartupProcessService.swift +++ b/Sources/Utilities/StartupService/StartupProcessService.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Domagoj Kulundzic on 26/04/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Sources/Core/Utilities/Throttler/Throttler.swift b/Sources/Utilities/Throttler/Throttler.swift similarity index 94% rename from Sources/Core/Utilities/Throttler/Throttler.swift rename to Sources/Utilities/Throttler/Throttler.swift index 900f622e..43bf5355 100644 --- a/Sources/Core/Utilities/Throttler/Throttler.swift +++ b/Sources/Utilities/Throttler/Throttler.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Domagoj Kulundzic on 1/05/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation diff --git a/Tests/Tests/Core/Extensions/Foundation/CollectionGroupedTests.swift b/Tests/Tests/Core/Extensions/Foundation/CollectionGroupedTests.swift index 4bc3b56e..ad849bb9 100644 --- a/Tests/Tests/Core/Extensions/Foundation/CollectionGroupedTests.swift +++ b/Tests/Tests/Core/Extensions/Foundation/CollectionGroupedTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Yll Fejziu on 14/11/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest diff --git a/Tests/Tests/Core/Extensions/Foundation/CollectionTests.swift b/Tests/Tests/Core/Extensions/Foundation/CollectionTests.swift index 12b295a5..2911cc79 100644 --- a/Tests/Tests/Core/Extensions/Foundation/CollectionTests.swift +++ b/Tests/Tests/Core/Extensions/Foundation/CollectionTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Borut Tomažin on 05/05/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest @@ -22,4 +22,23 @@ class CollectionTests: XCTestCase { XCTAssertEqual(array.count(where: { $0 is String}), 2) XCTAssertEqual(array.count(where: { $0 is Int}), 2) } + + func testMutateEach1() { + var array = [1, 2, 3, 4, 5] + array.mutateEach { $0 *= 2 } + XCTAssertEqual(array, [2, 4, 6, 8, 10]) + } + + func testMutateEach2() { + struct A: Equatable { + var x = true + + mutating func mutate() { + x.toggle() + } + } + var array = [A](repeating: .init(), count: 5) + array.mutateEach { $0.mutate() } + XCTAssertEqual(array, .init(repeating: .init(x: false), count: 5)) + } } diff --git a/Tests/Tests/Core/Extensions/Foundation/DataTests.swift b/Tests/Tests/Core/Extensions/Foundation/DataTests.swift index a2c11f4d..b2582ec4 100644 --- a/Tests/Tests/Core/Extensions/Foundation/DataTests.swift +++ b/Tests/Tests/Core/Extensions/Foundation/DataTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Borut Tomažin on 10/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest diff --git a/Tests/Tests/Core/Extensions/Foundation/DecodableDictionaryTests.swift b/Tests/Tests/Core/Extensions/Foundation/DecodableDictionaryTests.swift index 84ae85f8..565a0cdf 100644 --- a/Tests/Tests/Core/Extensions/Foundation/DecodableDictionaryTests.swift +++ b/Tests/Tests/Core/Extensions/Foundation/DecodableDictionaryTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Borut Tomažin on 11/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest diff --git a/Tests/Tests/Core/Extensions/Foundation/DispatchTimeIntervalTests.swift b/Tests/Tests/Core/Extensions/Foundation/DispatchTimeIntervalTests.swift index 35352b8a..a56440c5 100644 --- a/Tests/Tests/Core/Extensions/Foundation/DispatchTimeIntervalTests.swift +++ b/Tests/Tests/Core/Extensions/Foundation/DispatchTimeIntervalTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Borut Tomažin on 11/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest diff --git a/Tests/Tests/Core/Extensions/Foundation/DoubleTests.swift b/Tests/Tests/Core/Extensions/Foundation/DoubleTests.swift index 7ac5967e..274b5e48 100644 --- a/Tests/Tests/Core/Extensions/Foundation/DoubleTests.swift +++ b/Tests/Tests/Core/Extensions/Foundation/DoubleTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Borut Tomažin on 02/09/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest diff --git a/Tests/Tests/Core/Extensions/Foundation/EncodableTests.swift b/Tests/Tests/Core/Extensions/Foundation/EncodableTests.swift index 8c3a2041..ba53e607 100644 --- a/Tests/Tests/Core/Extensions/Foundation/EncodableTests.swift +++ b/Tests/Tests/Core/Extensions/Foundation/EncodableTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Borut Tomažin on 11/11/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest @@ -12,7 +12,7 @@ class EncodableTests: XCTestCase { func testEncode() { let request = TestRequest(id: 1, name: "PovioKit") do { - let json = try request.encode(with: JSONEncoder()) + let json = try request.toJSON(with: JSONEncoder()) XCTAssertEqual(json["id"] as? Int, 1) XCTAssertEqual(json["name"] as? String, "PovioKit") } catch { diff --git a/Tests/Tests/Core/Extensions/Foundation/OptionalTests.swift b/Tests/Tests/Core/Extensions/Foundation/OptionalTests.swift index 1e245653..44c1cd4c 100644 --- a/Tests/Tests/Core/Extensions/Foundation/OptionalTests.swift +++ b/Tests/Tests/Core/Extensions/Foundation/OptionalTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Klemen Zagar on 05/12/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest diff --git a/Tests/Tests/Core/Extensions/Foundation/StringTests.swift b/Tests/Tests/Core/Extensions/Foundation/StringTests.swift index 1f3be5bf..3825a96b 100644 --- a/Tests/Tests/Core/Extensions/Foundation/StringTests.swift +++ b/Tests/Tests/Core/Extensions/Foundation/StringTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Borut Tomažin on 05/05/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest @@ -59,4 +59,14 @@ class StringTests: XCTestCase { XCTAssertEqual("ThisIsATestString".safeSuffix(6), "String") XCTAssertEqual("ThisIsATestString".safeSuffix(100), "ThisIsATestString") } + + @available(iOS 15, *) + func testValidMarkdownConversion() { + let markdownString = "**[BoldURL](https://povio.com)**" + let expectedAttributedString = try! AttributedString(markdown: markdownString) + + let result = markdownString.toMarkdown() + + XCTAssertEqual(result, expectedAttributedString) + } } diff --git a/Tests/Tests/Core/Extensions/Foundation/URLTests.swift b/Tests/Tests/Core/Extensions/Foundation/URLTests.swift index 50955d87..03e1f91e 100644 --- a/Tests/Tests/Core/Extensions/Foundation/URLTests.swift +++ b/Tests/Tests/Core/Extensions/Foundation/URLTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Borut Tomažin on 05/05/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest diff --git a/Tests/Tests/Core/Extensions/MapKit/MKAnnotationViewTests.swift b/Tests/Tests/Core/Extensions/MapKit/MKAnnotationViewTests.swift index b5556a7f..81c48217 100644 --- a/Tests/Tests/Core/Extensions/MapKit/MKAnnotationViewTests.swift +++ b/Tests/Tests/Core/Extensions/MapKit/MKAnnotationViewTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Gentian Barileva on 02/06/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest diff --git a/Tests/Tests/Core/Extensions/UIKit/UIApplicationTests.swift b/Tests/Tests/Core/Extensions/UIKit/UIApplicationTests.swift index 8899ab55..d21ad179 100644 --- a/Tests/Tests/Core/Extensions/UIKit/UIApplicationTests.swift +++ b/Tests/Tests/Core/Extensions/UIKit/UIApplicationTests.swift @@ -3,9 +3,10 @@ // PovioKit_Tests // // Created by Toni Kocjan on 19/02/2021. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import XCTest class UIApplicationTests: XCTestCase { @@ -16,3 +17,4 @@ class UIApplicationTests: XCTestCase { XCTAssertFalse(app.build.isEmpty, "App build number should not be empty") } } +#endif diff --git a/Tests/Tests/Core/Extensions/UIKit/UICollectionReusableViewTests.swift b/Tests/Tests/Core/Extensions/UIKit/UICollectionReusableViewTests.swift index 9cbc764a..b4cd2a3d 100644 --- a/Tests/Tests/Core/Extensions/UIKit/UICollectionReusableViewTests.swift +++ b/Tests/Tests/Core/Extensions/UIKit/UICollectionReusableViewTests.swift @@ -3,9 +3,10 @@ // PovioKit_Tests // // Created by Ndriqim Nagavci on 25/10/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import XCTest import PovioKitCore @@ -21,3 +22,4 @@ class UICollectionReusableViewTests: XCTestCase { private class IdentifierTest: UICollectionReusableView { } private class SomeCustomCell: UICollectionReusableView { } +#endif diff --git a/Tests/Tests/Core/Extensions/UIKit/UIColorTests.swift b/Tests/Tests/Core/Extensions/UIKit/UIColorTests.swift index 20ec4240..75699ac5 100644 --- a/Tests/Tests/Core/Extensions/UIKit/UIColorTests.swift +++ b/Tests/Tests/Core/Extensions/UIKit/UIColorTests.swift @@ -3,9 +3,10 @@ // PovioKit_Tests // // Created by Klemen Zagar on 05/12/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import XCTest import PovioKitCore @@ -21,3 +22,4 @@ class UIColorTests: XCTestCase { XCTAssert(color.isEqual(UIColor.red.withAlphaComponent(alpha)), "Created color should be red with alpha: \(alpha)") } } +#endif diff --git a/Tests/Tests/Core/Extensions/UIKit/UIDeviceTests.swift b/Tests/Tests/Core/Extensions/UIKit/UIDeviceTests.swift index 6ae0b6b7..35b21256 100644 --- a/Tests/Tests/Core/Extensions/UIKit/UIDeviceTests.swift +++ b/Tests/Tests/Core/Extensions/UIKit/UIDeviceTests.swift @@ -3,9 +3,10 @@ // PovioKit_Tests // // Created by Klemen Zagar on 05/12/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import XCTest import PovioKitCore @@ -17,3 +18,4 @@ class UIDeviceTests: XCTestCase { XCTAssertFalse(sut.deviceCodeName.isEmpty, "Device code name should not be empty") } } +#endif diff --git a/Tests/Tests/Core/Extensions/UIKit/UIEdgeInsetsTests.swift b/Tests/Tests/Core/Extensions/UIKit/UIEdgeInsetsTests.swift index e7fb4c56..9671a09f 100644 --- a/Tests/Tests/Core/Extensions/UIKit/UIEdgeInsetsTests.swift +++ b/Tests/Tests/Core/Extensions/UIKit/UIEdgeInsetsTests.swift @@ -3,9 +3,10 @@ // PovioKit_Tests // // Created by Borut Tomažin on 23/12/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import XCTest import PovioKitCore @@ -50,3 +51,4 @@ class UIEdgeInsetsTests: XCTestCase { XCTAssertEqual(combinedInsets.horizontal, 20) } } +#endif diff --git a/Tests/Tests/Core/Extensions/UIKit/UIResponderTests.swift b/Tests/Tests/Core/Extensions/UIKit/UIResponderTests.swift index 86046eac..be97e54a 100644 --- a/Tests/Tests/Core/Extensions/UIKit/UIResponderTests.swift +++ b/Tests/Tests/Core/Extensions/UIKit/UIResponderTests.swift @@ -3,9 +3,10 @@ // PovioKit_Tests // // Created by Gentian Barileva on 01/06/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import XCTest import PovioKitCore @@ -50,3 +51,4 @@ private class MainViewController: UIViewController { private class ContentView: UIView { } private class ButtonsContainerView: UIView { } private class SecondaryViewController: UIViewController { } +#endif diff --git a/Tests/Tests/Core/Extensions/UIKit/UITableViewCellTests.swift b/Tests/Tests/Core/Extensions/UIKit/UITableViewCellTests.swift index c7d0f181..652d1a49 100644 --- a/Tests/Tests/Core/Extensions/UIKit/UITableViewCellTests.swift +++ b/Tests/Tests/Core/Extensions/UIKit/UITableViewCellTests.swift @@ -3,9 +3,10 @@ // PovioKit_Tests // // Created by Gentian Barileva on 01/06/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import XCTest import PovioKitCore @@ -21,3 +22,4 @@ class TableViewCellIdentifierTests: XCTestCase { private class IdentifierTest: UITableViewCell { } private class SomeCustomCell: UITableViewCell { } +#endif diff --git a/Tests/Tests/Core/Extensions/UIKit/UITableViewHeaderFooterViewTests.swift b/Tests/Tests/Core/Extensions/UIKit/UITableViewHeaderFooterViewTests.swift index d15f3d4f..3f18b965 100644 --- a/Tests/Tests/Core/Extensions/UIKit/UITableViewHeaderFooterViewTests.swift +++ b/Tests/Tests/Core/Extensions/UIKit/UITableViewHeaderFooterViewTests.swift @@ -3,9 +3,10 @@ // PovioKit_Tests // // Created by Gentian Barileva on 02/06/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import XCTest import PovioKitCore @@ -22,3 +23,4 @@ class UITableViewHeaderFooterViewTests: XCTestCase { // MARK: - Helpers private class CustomUITableViewHeaderFooterView: UITableViewHeaderFooterView { } private class OtherUITableViewHeaderFooterView: UITableViewHeaderFooterView { } +#endif diff --git a/Tests/Tests/Core/Extensions/UIKit/UIViewControllerTests.swift b/Tests/Tests/Core/Extensions/UIKit/UIViewControllerTests.swift index f48b499c..ffc93970 100644 --- a/Tests/Tests/Core/Extensions/UIKit/UIViewControllerTests.swift +++ b/Tests/Tests/Core/Extensions/UIKit/UIViewControllerTests.swift @@ -3,12 +3,13 @@ // PovioKit_Tests // // Created by Ndriqim Nagavci on 27/10/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import XCTest import PovioKitCore -import PovioKitUI +import PovioKitUIKit class UIViewControllerTests: XCTestCase { func test_setLeftBarButton_addsLeftBarButton() { @@ -53,4 +54,4 @@ class UIViewControllerTests: XCTestCase { @objc private func testTarget() { } } - +#endif diff --git a/Tests/Tests/Core/Extensions/UIKit/UIViewTests.swift b/Tests/Tests/Core/Extensions/UIKit/UIViewTests.swift index 5bcbf21e..605b8735 100644 --- a/Tests/Tests/Core/Extensions/UIKit/UIViewTests.swift +++ b/Tests/Tests/Core/Extensions/UIKit/UIViewTests.swift @@ -3,9 +3,11 @@ // PovioKit_Tests // // Created by Borut Tomazin on 19/09/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) + import XCTest import UIKit import PovioKitCore @@ -135,3 +137,5 @@ class UIViewTests: XCTestCase { XCTAssertNil(view.layer.animationKeys()) } } + +#endif diff --git a/Tests/Tests/Core/Extensions/UIKit/UIWindowTests.swift b/Tests/Tests/Core/Extensions/UIKit/UIWindowTests.swift index f1dd0ca9..33026828 100644 --- a/Tests/Tests/Core/Extensions/UIKit/UIWindowTests.swift +++ b/Tests/Tests/Core/Extensions/UIKit/UIWindowTests.swift @@ -3,9 +3,11 @@ // PovioKit_Tests // // Created by Borut Tomazin on 6/1/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) + import XCTest import UIKit import PovioKitCore @@ -21,3 +23,5 @@ class UIWindowTests: XCTestCase { XCTAssertEqual(window.safeAreaInsets.bottom, 34) } } + +#endif diff --git a/Tests/Tests/Core/Utilities/App Version Validator/AppVersionValidatorTests.swift b/Tests/Tests/Core/Utilities/App Version Validator/AppVersionValidatorTests.swift index bd02d71a..379d0c3e 100644 --- a/Tests/Tests/Core/Utilities/App Version Validator/AppVersionValidatorTests.swift +++ b/Tests/Tests/Core/Utilities/App Version Validator/AppVersionValidatorTests.swift @@ -3,11 +3,12 @@ // PovioKit_Tests // // Created by Toni Kocjan on 16/02/2021. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest import PovioKitCore +import PovioKitUtilities class AppVersionValidatorTests: XCTestCase { func testValidator() { diff --git a/Tests/Tests/Core/Utilities/AttributedStringBuilder/AttributedStringBuilderTests.swift b/Tests/Tests/Core/Utilities/AttributedStringBuilder/AttributedStringBuilderTests.swift index 1fc0fbad..353a0518 100644 --- a/Tests/Tests/Core/Utilities/AttributedStringBuilder/AttributedStringBuilderTests.swift +++ b/Tests/Tests/Core/Utilities/AttributedStringBuilder/AttributedStringBuilderTests.swift @@ -3,9 +3,10 @@ // PovioKit_Tests // // Created by Ndriqim Nagavci on 27/10/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import XCTest import PovioKitCore @@ -87,3 +88,4 @@ private extension AttributedStringBuilderTests { static let paragraphLineHeight: CGFloat = 30 } } +#endif diff --git a/Tests/Tests/Core/Utilities/Broadcast/BroadcastTests.swift b/Tests/Tests/Core/Utilities/Broadcast/BroadcastTests.swift index 833dd5d1..188ebad0 100644 --- a/Tests/Tests/Core/Utilities/Broadcast/BroadcastTests.swift +++ b/Tests/Tests/Core/Utilities/Broadcast/BroadcastTests.swift @@ -3,11 +3,12 @@ // PovioKit_Tests // // Created by Klemen Zagar on 05/12/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest import PovioKitCore +import PovioKitUtilities class BroadcastTests: XCTestCase { diff --git a/Tests/Tests/Core/Utilities/BundleReader/BundleReaderTests.swift b/Tests/Tests/Core/Utilities/BundleReader/BundleReaderTests.swift index e3e1eac5..aae4e73b 100644 --- a/Tests/Tests/Core/Utilities/BundleReader/BundleReaderTests.swift +++ b/Tests/Tests/Core/Utilities/BundleReader/BundleReaderTests.swift @@ -3,11 +3,12 @@ // PovioKit_Tests // // Created by Gentian Barileva on 01/06/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest import PovioKitCore +import PovioKitUtilities class BundleReaderTests: XCTestCase { func test_init_doesNotMessageTheReader() { diff --git a/Tests/Tests/Core/Utilities/DispatchTimer/DispatchTimerTests.swift b/Tests/Tests/Core/Utilities/DispatchTimer/DispatchTimerTests.swift index c37c04bf..1a6b9a3f 100644 --- a/Tests/Tests/Core/Utilities/DispatchTimer/DispatchTimerTests.swift +++ b/Tests/Tests/Core/Utilities/DispatchTimer/DispatchTimerTests.swift @@ -3,11 +3,12 @@ // PovioKit_Tests // // Created by Borut Tomazin on 19/09/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest import PovioKitCore +import PovioKitUtilities final class DispatchTimerTests: XCTestCase { func test_dispatchTimer_instance_noRepeating() { diff --git a/Tests/Tests/Core/Utilities/Exif/ExifTests.swift b/Tests/Tests/Core/Utilities/Exif/ExifTests.swift index 0580b637..0a65570d 100644 --- a/Tests/Tests/Core/Utilities/Exif/ExifTests.swift +++ b/Tests/Tests/Core/Utilities/Exif/ExifTests.swift @@ -3,11 +3,13 @@ // PovioKit_Tests // // Created by Borut Tomazin on 05/05/2023. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // +#if os(iOS) import XCTest import PovioKitCore +import PovioKitUtilities final class ExifTests: XCTestCase { let image = UIImage.with(color: .blue, size: .init(width: 100, height: 100)) @@ -58,3 +60,4 @@ final class ExifTests: XCTestCase { } } } +#endif diff --git a/Tests/Tests/Core/Utilities/Money/MoneyTests.swift b/Tests/Tests/Core/Utilities/Money/MoneyTests.swift index 1a37bb06..5646c6f9 100644 --- a/Tests/Tests/Core/Utilities/Money/MoneyTests.swift +++ b/Tests/Tests/Core/Utilities/Money/MoneyTests.swift @@ -3,11 +3,12 @@ // PovioKit_Tests // // Created by Marko Mijatovic on 04/07/2022. -// Copyright © 2023 Povio Labs. All rights reserved. +// Copyright © 2024 Povio Labs. All rights reserved. // import XCTest import PovioKitCore +import PovioKitUtilities class MoneyTests: XCTestCase { // MARK: - Testing Getters diff --git a/Tests/Tests/Core/Utilities/StartupService/StartupProcessServiceTests.swift b/Tests/Tests/Core/Utilities/StartupService/StartupProcessServiceTests.swift index 242c4fc4..c9523965 100644 --- a/Tests/Tests/Core/Utilities/StartupService/StartupProcessServiceTests.swift +++ b/Tests/Tests/Core/Utilities/StartupService/StartupProcessServiceTests.swift @@ -3,11 +3,12 @@ // PovioKit_Tests // // Created by Klemen Zagar on 05/12/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest import PovioKitCore +import PovioKitUtilities class StartupProcessServiceTests: XCTestCase { func testShouldCompleteProccesWhenCallExecution() { diff --git a/Tests/Tests/Core/Utilities/Throttler/ThrottlerTests.swift b/Tests/Tests/Core/Utilities/Throttler/ThrottlerTests.swift index 701ce7f3..d8e9dade 100644 --- a/Tests/Tests/Core/Utilities/Throttler/ThrottlerTests.swift +++ b/Tests/Tests/Core/Utilities/Throttler/ThrottlerTests.swift @@ -3,11 +3,12 @@ // PovioKit_Tests // // Created by Klemen Zagar on 05/12/2019. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest -@testable import PovioKitCore +import PovioKitCore +@testable import PovioKitUtilities class ThrottlerTests: XCTestCase { func testShouldExecuteWhenDelayed() { diff --git a/Tests/Tests/Core/Utilities/UserDefaults/UserDefaultTests.swift b/Tests/Tests/Core/Utilities/UserDefaults/UserDefaultTests.swift index d9f7fb4c..8c81a914 100644 --- a/Tests/Tests/Core/Utilities/UserDefaults/UserDefaultTests.swift +++ b/Tests/Tests/Core/Utilities/UserDefaults/UserDefaultTests.swift @@ -3,11 +3,12 @@ // PovioKit // // Created by Egzon Arifi on 25/01/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest import PovioKitCore +import PovioKitUtilities class UserDefaultTests: XCTestCase { let userDefaults: UserDefaults = .standard diff --git a/Tests/Tests/PromiseKit/EitherTests.swift b/Tests/Tests/PromiseKit/EitherTests.swift index d1f07a43..f449e8f6 100644 --- a/Tests/Tests/PromiseKit/EitherTests.swift +++ b/Tests/Tests/PromiseKit/EitherTests.swift @@ -3,7 +3,7 @@ // PovioKit_Tests // // Created by Toni Kocjan on 31/01/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest diff --git a/Tests/Tests/PromiseKit/PromiseTests.swift b/Tests/Tests/PromiseKit/PromiseTests.swift index ea2df3a2..5dae83e9 100644 --- a/Tests/Tests/PromiseKit/PromiseTests.swift +++ b/Tests/Tests/PromiseKit/PromiseTests.swift @@ -3,7 +3,7 @@ // PovioKit // // Created by Toni Kocjan on 31/01/2020. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest diff --git a/Tests/Tests/Utilities/XCConfigValue/MockBundleReader.swift b/Tests/Tests/Utilities/XCConfigValue/MockBundleReader.swift index 88a037cc..c4614460 100644 --- a/Tests/Tests/Utilities/XCConfigValue/MockBundleReader.swift +++ b/Tests/Tests/Utilities/XCConfigValue/MockBundleReader.swift @@ -3,11 +3,12 @@ // PovioKit // // Created by Egzon Arifi on 31/03/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import Foundation import PovioKitCore +import PovioKitUtilities class MockBundleReader: BundleReadable { private let dictionary: [String: Any] diff --git a/Tests/Tests/Utilities/XCConfigValue/XCConfigValueTests.swift b/Tests/Tests/Utilities/XCConfigValue/XCConfigValueTests.swift index a38032fe..6e13ced8 100644 --- a/Tests/Tests/Utilities/XCConfigValue/XCConfigValueTests.swift +++ b/Tests/Tests/Utilities/XCConfigValue/XCConfigValueTests.swift @@ -3,11 +3,12 @@ // PovioKit // // Created by Egzon Arifi on 31/03/2022. -// Copyright © 2023 Povio Inc. All rights reserved. +// Copyright © 2024 Povio Inc. All rights reserved. // import XCTest import PovioKitCore +import PovioKitUtilities class XCConfigValueTests: XCTestCase { enum TestConfig {