Setup packages

This commit is contained in:
Rokas Ambrazevicius
2023-12-27 16:12:41 +02:00
parent 7f0256cc33
commit 0bdb6a626d
33 changed files with 436 additions and 30 deletions
+7
View File
@@ -0,0 +1,7 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm
+3 -2
View File
@@ -20,7 +20,6 @@ opt_in_rules:
- contains_over_filter_is_empty
- contains_over_first_not_nil
- contains_over_range_nil_comparison
- convenience_type
- discouraged_none_name
- discouraged_object_literal
- empty_collection_literal
@@ -56,7 +55,6 @@ opt_in_rules:
- multiline_literal_brackets
- multiline_parameters
- multiline_parameters_brackets
- no_extension_access_modifier
- operator_usage_whitespace
- overridden_super_call
- pattern_matching_keywords
@@ -126,6 +124,9 @@ line_length:
multiline_parameters:
allowsSingleLine: false
nesting:
type_level: 3
private_outlet:
allow_private_set: true
+6 -5
View File
@@ -6,20 +6,21 @@ import PackageDescription
let package = Package(
name: "Home",
platforms: [
.iOS(.v15)
.iOS(.v16)
],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "Home",
targets: ["Home"]
)
],
dependencies: [
.package(path: "../UIComponents")
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "Home"
name: "Home",
dependencies: ["UIComponents"]
),
.testTarget(
name: "HomeTests",
+20 -1
View File
@@ -1,9 +1,28 @@
import SwiftUI
import UIComponents
import Theme
public struct HomeView: View {
public init() {}
public var body: some View {
Text("NymVPN")
VStack {
CustomNavBar(
title: "NymVPN",
rightButtonConfig: settingsButtonConfig()
)
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background {
NymColor.background
.ignoresSafeArea()
}
}
}
private extension HomeView {
func settingsButtonConfig() -> CustomNavBarButtonConfig {
CustomNavBarButtonConfig(type: .settingsGear) {}
}
}
@@ -317,6 +317,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -349,6 +350,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>NymVPN.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
</dict>
</dict>
</plist>
+3
View File
@@ -7,6 +7,9 @@
<FileRef
location = "group:Home">
</FileRef>
<FileRef
location = "group:UIComponents">
</FileRef>
<FileRef
location = "group:Theme">
</FileRef>
+8 -1
View File
@@ -1,11 +1,18 @@
import SwiftUI
import Home
import Theme
@main
struct NymVPNApp: App {
init() {
ThemeConfiguration.setup()
}
var body: some Scene {
WindowGroup {
HomeView()
NavigationStack {
HomeView()
}
}
}
}
+7 -5
View File
@@ -6,20 +6,22 @@ import PackageDescription
let package = Package(
name: "Theme",
platforms: [
.iOS(.v15)
.iOS(.v16)
],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "Theme",
targets: ["Theme"]
)
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "Theme"
name: "Theme",
resources: [
.copy("Resources/Fonts/Lato-Bold.ttf"),
.copy("Resources/Fonts/Lato-Regular.ttf"),
.process("Resources/Assets.xcassets")
]
),
.testTarget(
name: "ThemeTests",
@@ -0,0 +1,11 @@
import SwiftUI
extension Color {
init(_ name: String) {
guard let namedColor = UIColor(named: name, in: Bundle.module, compatibleWith: nil)
else {
fatalError("Could not load color from Theme module")
}
self.init(namedColor)
}
}
@@ -0,0 +1,10 @@
import SwiftUI
public struct NymColor {
// MARK: - Navigation bar -
public static let navigationBarBackground = Color(.navigationBarBackground)
public static let navigationBarSettingsGear = Color(.navigationBarSettingsGear)
// MARK: - Background
public static let background = Color(.background)
}
@@ -0,0 +1,33 @@
import SwiftUI
public enum NymFont {
case lato(size: CGFloat, weight: LatoWeight)
public var font: Font {
switch self {
case let .lato(size, weight):
Font.custom("Lato-\(weight.rawValue)", size: size)
}
}
}
// MARK: - Weights -
extension NymFont {
public enum LatoWeight: String, CaseIterable {
case regular = "Regular"
case bold = "Bold"
}
}
// MARK: - Register fonts -
extension NymFont {
public static func register() {
for latoWeight in NymFont.LatoWeight.allCases {
let fontName = "Lato-\(latoWeight.rawValue)"
guard let fontURL = Bundle.module.url(forResource: fontName, withExtension: "ttf") else { continue }
CTFontManagerRegisterFontsForURL(fontURL as CFURL, .process, nil)
}
}
}
@@ -0,0 +1,6 @@
import Foundation
public enum NymFontStyle {
case titleLarge
case titleMedium
}
@@ -0,0 +1,21 @@
import SwiftUI
public struct NymTextStyle {
let nymFont: NymFont
let lineSpacing: CGFloat
init(nymFont: NymFont, lineSpacing: CGFloat = 0) {
self.nymFont = nymFont
self.lineSpacing = lineSpacing
}
}
extension NymTextStyle {
public struct Title {
public struct Large {
public static var primary: NymTextStyle {
NymTextStyle(nymFont: .lato(size: 22, weight: .regular))
}
}
}
}
@@ -0,0 +1,20 @@
import SwiftUI
public struct NymTextStyleModifier: ViewModifier {
public let textStyle: NymTextStyle
public init(textStyle: NymTextStyle) {
self.textStyle = textStyle
}
public func body(content: Content) -> some View {
content
.font(textStyle.nymFont.font)
}
}
public extension View {
func textStyle(_ textStyle: NymTextStyle) -> some View {
modifier(NymTextStyleModifier(textStyle: textStyle))
}
}
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.965",
"green" : "0.957",
"red" : "0.949"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.122",
"green" : "0.106",
"red" : "0.110"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "1.000",
"green" : "1.000",
"red" : "1.000"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.192",
"green" : "0.157",
"red" : "0.165"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.122",
"green" : "0.106",
"red" : "0.110"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0.812",
"green" : "0.769",
"red" : "0.788"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -1,2 +0,0 @@
// The Swift Programming Language
// https://docs.swift.org/swift-book
@@ -0,0 +1,7 @@
import Foundation
public struct ThemeConfiguration {
public static func setup() {
NymFont.register()
}
}
+8
View File
@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
+35
View File
@@ -0,0 +1,35 @@
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "UIComponents",
platforms: [
.iOS(.v16)
],
products: [
.library(
name: "UIComponents",
targets: ["UIComponents"]
)
],
dependencies: [
.package(path: "../Theme")
],
targets: [
.target(
name: "UIComponents",
dependencies: [
"Theme"
],
resources: [
.process("Resources/Assets.xcassets")
]
),
.testTarget(
name: "UIComponentsTests",
dependencies: ["UIComponents"]
)
]
)
@@ -0,0 +1,49 @@
import SwiftUI
import Theme
public struct CustomNavBar: View {
public let title: String
public let leftButtonConfig: CustomNavBarButtonConfig?
public let rightButtonConfig: CustomNavBarButtonConfig?
public init(
title: String,
leftButtonConfig: CustomNavBarButtonConfig? = nil,
rightButtonConfig: CustomNavBarButtonConfig? = nil
) {
self.title = title
self.leftButtonConfig = leftButtonConfig
self.rightButtonConfig = rightButtonConfig
}
public var body: some View {
HStack {
button(with: leftButtonConfig)
Spacer()
Text(title)
.textStyle(.Title.Large.primary)
Spacer()
button(with: rightButtonConfig)
}
.frame(height: 64)
.background {
NymColor.navigationBarBackground
.ignoresSafeArea()
}
}
}
private extension CustomNavBar {
@ViewBuilder
func button(with config: CustomNavBarButtonConfig?) -> some View {
Button {
config?.action?()
} label: {
if let type = config?.type {
Image(type.imageName)
.tint(NymColor.navigationBarSettingsGear)
}
}
.frame(width: 48, height: 48)
}
}
@@ -0,0 +1,17 @@
public struct CustomNavBarButtonConfig {
public enum ButtonType: String {
case settingsGear
var imageName: String {
self.rawValue
}
}
public init(type: ButtonType? = nil, action: (() -> Void)?) {
self.type = type
self.action = action
}
public let type: ButtonType?
public let action: (() -> Void)?
}
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,16 @@
{
"images" : [
{
"filename" : "settings_24px.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Icons/settings_24px">
<path id="icon" fill-rule="evenodd" clip-rule="evenodd" d="M15.3102 21.0278C15.2102 21.7078 14.5902 22.2478 13.8502 22.2478H10.1502C9.41023 22.2478 8.79023 21.7078 8.70023 20.9778L8.43023 19.0878C8.16023 18.9478 7.90023 18.7978 7.64023 18.6278L5.84023 19.3478C5.14023 19.6078 4.37023 19.3178 4.03023 18.6978L2.20023 15.5278C1.85023 14.8678 2.00023 14.0878 2.56023 13.6478L4.09023 12.4578C4.08023 12.3078 4.07023 12.1578 4.07023 11.9978C4.07023 11.8478 4.08023 11.6878 4.09023 11.5378L2.57023 10.3478C1.98023 9.89781 1.83023 9.08781 2.20023 8.46781L4.05023 5.27781C4.39023 4.65781 5.16023 4.37781 5.84023 4.64781L7.65023 5.37781C7.91023 5.20781 8.17023 5.05781 8.43023 4.91781L8.70023 3.00781C8.79023 2.30781 9.41023 1.75781 10.1402 1.75781H13.8402C14.5802 1.75781 15.2002 2.29781 15.2902 3.02781L15.5602 4.91781C15.8302 5.05781 16.0902 5.20781 16.3502 5.37781L18.1502 4.65781C18.8602 4.39781 19.6302 4.68781 19.9702 5.30781L21.8102 8.48781C22.1702 9.14781 22.0102 9.92781 21.4502 10.3678L19.9302 11.5578C19.9402 11.7078 19.9502 11.8578 19.9502 12.0178C19.9502 12.1778 19.9402 12.3278 19.9302 12.4778L21.4502 13.6678C22.0102 14.1178 22.1702 14.8978 21.8202 15.5278L19.9602 18.7478C19.6202 19.3678 18.8502 19.6478 18.1602 19.3778L16.3602 18.6578C16.1002 18.8278 15.8402 18.9778 15.5802 19.1178L15.3102 21.0278ZM10.6202 20.2478H13.3802L13.7502 17.6978L14.2802 17.4778C14.7202 17.2978 15.1602 17.0378 15.6202 16.6978L16.0702 16.3578L18.4502 17.3178L19.8302 14.9178L17.8002 13.3378L17.8702 12.7778L17.8733 12.7509C17.9023 12.5005 17.9302 12.2585 17.9302 11.9978C17.9302 11.7278 17.9002 11.4678 17.8702 11.2178L17.8002 10.6578L19.8302 9.07781L18.4402 6.67781L16.0502 7.63781L15.6002 7.28781C15.1802 6.96781 14.7302 6.70781 14.2702 6.51781L13.7502 6.29781L13.3802 3.74781H10.6202L10.2502 6.29781L9.72023 6.50781C9.28023 6.69781 8.84023 6.94781 8.38023 7.29781L7.93023 7.62781L5.55023 6.67781L4.16023 9.06781L6.19023 10.6478L6.12023 11.2078C6.09023 11.4678 6.06023 11.7378 6.06023 11.9978C6.06023 12.2578 6.08023 12.5278 6.12023 12.7778L6.19023 13.3378L4.16023 14.9178L5.54023 17.3178L7.93023 16.3578L8.38023 16.7078C8.81023 17.0378 9.24023 17.2878 9.71023 17.4778L10.2402 17.6978L10.6202 20.2478ZM15.5002 11.9978C15.5002 13.9308 13.9332 15.4978 12.0002 15.4978C10.0672 15.4978 8.50023 13.9308 8.50023 11.9978C8.50023 10.0648 10.0672 8.49781 12.0002 8.49781C13.9332 8.49781 15.5002 10.0648 15.5002 11.9978Z" fill="#CAC4D0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,4 @@
import XCTest
@testable import UIComponents
final class UIComponentsTests: XCTestCase {}