Setup packages
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
/*.xcodeproj
|
||||
xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm
|
||||
@@ -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,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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
-14
@@ -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>
|
||||
@@ -7,6 +7,9 @@
|
||||
<FileRef
|
||||
location = "group:Home">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:UIComponents">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Theme">
|
||||
</FileRef>
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
+38
@@ -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
|
||||
}
|
||||
}
|
||||
+38
@@ -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
|
||||
}
|
||||
}
|
||||
+38
@@ -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
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm/configuration/registries.json
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
.netrc
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
+17
@@ -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
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
+16
@@ -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"
|
||||
}
|
||||
}
|
||||
+5
@@ -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 {}
|
||||
Reference in New Issue
Block a user