geeknative 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/bin/geeknative.js +12 -0
- package/package.json +31 -4
- package/src/cli.js +61 -0
- package/src/codegen/app.js +97 -0
- package/src/codegen/icons.js +87 -0
- package/src/codegen/index.js +44 -0
- package/src/codegen/strings.js +308 -0
- package/src/codegen/tokens.js +449 -0
- package/src/codegen/util.js +122 -0
- package/src/commands/check.js +143 -0
- package/src/commands/create.js +78 -0
- package/src/commands/doctor.js +108 -0
- package/src/commands/gen.js +44 -0
- package/src/commands/parity.js +134 -0
- package/src/commands/run.js +91 -0
- package/src/lib/exec.js +77 -0
- package/src/lib/fsutil.js +92 -0
- package/src/lib/log.js +37 -0
- package/src/lib/managed.js +80 -0
- package/src/lib/project.js +52 -0
- package/src/lib/toolchains.js +126 -0
- package/template/.claude/agents/android-engineer.md +15 -0
- package/template/.claude/agents/ios-engineer.md +15 -0
- package/template/.claude/agents/web-engineer.md +15 -0
- package/template/.claude/settings.json +65 -0
- package/template/.geeknative/framework.mk +41 -0
- package/template/.geeknative/hooks/after-edit.mjs +28 -0
- package/template/.geeknative/hooks/parity-guard.mjs +49 -0
- package/template/.geeknative/hooks/subagent-context.mjs +24 -0
- package/template/.geeknative/playbooks/bug.md +7 -0
- package/template/.geeknative/playbooks/design.md +10 -0
- package/template/.geeknative/playbooks/engineering.md +9 -0
- package/template/.geeknative/playbooks/feature.md +11 -0
- package/template/.geeknative/playbooks/platform-specific.md +8 -0
- package/template/.geeknative/playbooks/product.md +12 -0
- package/template/.geeknative/templates/feature.md +49 -0
- package/template/.gemini/settings.json +5 -0
- package/template/.github/dependabot.yml +18 -0
- package/template/AGENTS.md +97 -0
- package/template/CLAUDE.md +9 -0
- package/template/DESIGN.md +65 -0
- package/template/Makefile +6 -0
- package/template/PRODUCT.md +40 -0
- package/template/README.md +28 -0
- package/template/_gitignore +33 -0
- package/template/apps/android/AGENTS.md +66 -0
- package/template/apps/android/CLAUDE.md +1 -0
- package/template/apps/android/app/build.gradle.kts +68 -0
- package/template/apps/android/app/identity.properties +4 -0
- package/template/apps/android/app/src/main/AndroidManifest.xml +24 -0
- package/template/apps/android/app/src/main/kotlin/app/App.kt +15 -0
- package/template/apps/android/app/src/main/kotlin/app/MainActivity.kt +49 -0
- package/template/apps/android/app/src/main/kotlin/app/core/AppContainer.kt +27 -0
- package/template/apps/android/app/src/main/kotlin/app/core/designsystem/AppCard.kt +30 -0
- package/template/apps/android/app/src/main/kotlin/app/core/designsystem/AppTheme.kt +35 -0
- package/template/apps/android/app/src/main/kotlin/app/core/navigation/AppNavigation.kt +40 -0
- package/template/apps/android/app/src/main/kotlin/app/core/navigation/Route.kt +13 -0
- package/template/apps/android/app/src/main/kotlin/app/features/home/HomeScreen.kt +67 -0
- package/template/apps/android/app/src/main/kotlin/app/features/settings/Appearance.kt +22 -0
- package/template/apps/android/app/src/main/kotlin/app/features/settings/SettingsRepository.kt +40 -0
- package/template/apps/android/app/src/main/kotlin/app/features/settings/SettingsScreen.kt +113 -0
- package/template/apps/android/app/src/main/kotlin/app/features/settings/SettingsViewModel.kt +28 -0
- package/template/apps/android/app/src/main/kotlin/app/generated/AppIdentity.kt +10 -0
- package/template/apps/android/app/src/main/kotlin/app/generated/Icons.kt +15 -0
- package/template/apps/android/app/src/main/kotlin/app/generated/Tokens.kt +144 -0
- package/template/apps/android/app/src/main/res/drawable/ic_launcher_foreground.xml +17 -0
- package/template/apps/android/app/src/main/res/mipmap/ic_launcher.xml +10 -0
- package/template/apps/android/app/src/main/res/mipmap/ic_launcher_round.xml +10 -0
- package/template/apps/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +6 -0
- package/template/apps/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +6 -0
- package/template/apps/android/app/src/main/res/values/generated_colors.xml +15 -0
- package/template/apps/android/app/src/main/res/values/generated_strings.xml +16 -0
- package/template/apps/android/app/src/main/res/values/ic_launcher_background.xml +4 -0
- package/template/apps/android/app/src/main/res/values/themes.xml +7 -0
- package/template/apps/android/app/src/main/res/values-night/generated_colors.xml +15 -0
- package/template/apps/android/app/src/main/res/values-night/themes.xml +6 -0
- package/template/apps/android/app/src/test/kotlin/app/features/settings/SettingsTest.kt +90 -0
- package/template/apps/android/build.gradle.kts +5 -0
- package/template/apps/android/gradle/gradle-daemon-jvm.properties +12 -0
- package/template/apps/android/gradle/libs.versions.toml +37 -0
- package/template/apps/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/template/apps/android/gradle/wrapper/gradle-wrapper.properties +9 -0
- package/template/apps/android/gradle.properties +7 -0
- package/template/apps/android/gradlew +248 -0
- package/template/apps/android/gradlew.bat +82 -0
- package/template/apps/android/settings.gradle.kts +29 -0
- package/template/apps/ios/AGENTS.md +70 -0
- package/template/apps/ios/App/AppMain.swift +13 -0
- package/template/apps/ios/App/Core/AppContainer.swift +22 -0
- package/template/apps/ios/App/Core/DesignSystem/AppCard.swift +15 -0
- package/template/apps/ios/App/Core/Navigation/Route.swift +4 -0
- package/template/apps/ios/App/Core/RootView.swift +32 -0
- package/template/apps/ios/App/Features/Home/HomeScreen.swift +35 -0
- package/template/apps/ios/App/Features/Settings/Appearance.swift +27 -0
- package/template/apps/ios/App/Features/Settings/SettingsRepository.swift +40 -0
- package/template/apps/ios/App/Features/Settings/SettingsScreen.swift +40 -0
- package/template/apps/ios/App/Features/Settings/SettingsViewModel.swift +23 -0
- package/template/apps/ios/App/Generated/AppIdentity.swift +9 -0
- package/template/apps/ios/App/Generated/Colors.xcassets/AccentColor.colorset/Contents.json +38 -0
- package/template/apps/ios/App/Generated/Colors.xcassets/Contents.json +6 -0
- package/template/apps/ios/App/Generated/Icons.swift +8 -0
- package/template/apps/ios/App/Generated/Localizable.xcstrings +127 -0
- package/template/apps/ios/App/Generated/Strings.swift +40 -0
- package/template/apps/ios/App/Generated/Tokens.swift +65 -0
- package/template/apps/ios/App/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon.png +0 -0
- package/template/apps/ios/App/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json +14 -0
- package/template/apps/ios/App/Resources/Assets.xcassets/Contents.json +6 -0
- package/template/apps/ios/App.xcodeproj/project.pbxproj +298 -0
- package/template/apps/ios/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/template/apps/ios/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme +89 -0
- package/template/apps/ios/AppTests/SettingsTests.swift +54 -0
- package/template/apps/ios/CLAUDE.md +1 -0
- package/template/apps/ios/Config/App.xcconfig +23 -0
- package/template/apps/ios/Config/AppTests.xcconfig +10 -0
- package/template/apps/ios/Config/Base.xcconfig +25 -0
- package/template/apps/ios/Config/Debug.xcconfig +9 -0
- package/template/apps/ios/Config/Identity.xcconfig +5 -0
- package/template/apps/ios/Config/Release.xcconfig +6 -0
- package/template/apps/web/AGENTS.md +63 -0
- package/template/apps/web/CLAUDE.md +1 -0
- package/template/apps/web/package.json +38 -0
- package/template/apps/web/public/favicon.svg +6 -0
- package/template/apps/web/src/core/AppContainer.ts +18 -0
- package/template/apps/web/src/core/AppearanceEffect.tsx +31 -0
- package/template/apps/web/src/core/designsystem/AppCard.tsx +6 -0
- package/template/apps/web/src/features/home/HomeScreen.tsx +15 -0
- package/template/apps/web/src/features/home/home.test.tsx +22 -0
- package/template/apps/web/src/features/settings/Appearance.ts +29 -0
- package/template/apps/web/src/features/settings/LocalStorageSettingsRepository.ts +21 -0
- package/template/apps/web/src/features/settings/SettingsRepository.ts +7 -0
- package/template/apps/web/src/features/settings/SettingsScreen.tsx +44 -0
- package/template/apps/web/src/features/settings/settings.test.ts +45 -0
- package/template/apps/web/src/features/settings/useSettingsViewModel.ts +42 -0
- package/template/apps/web/src/generated/app.ts +9 -0
- package/template/apps/web/src/generated/icons.ts +9 -0
- package/template/apps/web/src/generated/strings.ts +88 -0
- package/template/apps/web/src/generated/tokens.css +86 -0
- package/template/apps/web/src/routeTree.gen.ts +86 -0
- package/template/apps/web/src/router.tsx +23 -0
- package/template/apps/web/src/routes/__root.tsx +72 -0
- package/template/apps/web/src/routes/index.tsx +6 -0
- package/template/apps/web/src/routes/settings.tsx +9 -0
- package/template/apps/web/src/styles.css +9 -0
- package/template/apps/web/tsconfig.json +26 -0
- package/template/apps/web/tsr.config.json +3 -0
- package/template/apps/web/vite.config.ts +9 -0
- package/template/apps/web/vitest.config.ts +9 -0
- package/template/contracts/app.json +7 -0
- package/template/contracts/icons.json +5 -0
- package/template/contracts/strings/en.json +13 -0
- package/template/contracts/tokens.json +40 -0
- package/template/package.json +17 -0
- package/template/spec/decisions.md +10 -0
- package/template/spec/features/home.md +39 -0
- package/template/spec/features/settings.md +50 -0
- package/template/spec/navigation.md +16 -0
- package/template/spec/parity.md +29 -0
- package/README.md +0 -3
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import Observation
|
|
2
|
+
|
|
3
|
+
/// State and actions for the Settings screen.
|
|
4
|
+
@Observable
|
|
5
|
+
final class SettingsViewModel {
|
|
6
|
+
@ObservationIgnored private let repository: any SettingsRepository
|
|
7
|
+
|
|
8
|
+
init(repository: any SettingsRepository) {
|
|
9
|
+
self.repository = repository
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
var appearance: Appearance { repository.appearance }
|
|
13
|
+
|
|
14
|
+
let appearanceOptions = Appearance.allCases
|
|
15
|
+
|
|
16
|
+
var versionText: String {
|
|
17
|
+
Strings.settingsAboutVersion(version: AppIdentity.version, build: AppIdentity.build)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func selectAppearance(_ appearance: Appearance) {
|
|
21
|
+
repository.setAppearance(appearance)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// GENERATED by geeknative from contracts/app.json. Do not edit: change the contract, then run `make gen`.
|
|
2
|
+
|
|
3
|
+
/// The app's name, identifier and version, shared with the Android and web apps.
|
|
4
|
+
nonisolated enum AppIdentity {
|
|
5
|
+
static let name = "GeekNative"
|
|
6
|
+
static let id = "com.example.geeknative"
|
|
7
|
+
static let version = "1.0.0"
|
|
8
|
+
static let build = 1
|
|
9
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"colors" : [
|
|
3
|
+
{
|
|
4
|
+
"color" : {
|
|
5
|
+
"color-space" : "srgb",
|
|
6
|
+
"components" : {
|
|
7
|
+
"alpha" : "1.000",
|
|
8
|
+
"blue" : "0xE5",
|
|
9
|
+
"green" : "0x46",
|
|
10
|
+
"red" : "0x4F"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"idiom" : "universal"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"appearances" : [
|
|
17
|
+
{
|
|
18
|
+
"appearance" : "luminosity",
|
|
19
|
+
"value" : "dark"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"color" : {
|
|
23
|
+
"color-space" : "srgb",
|
|
24
|
+
"components" : {
|
|
25
|
+
"alpha" : "1.000",
|
|
26
|
+
"blue" : "0xFC",
|
|
27
|
+
"green" : "0xB4",
|
|
28
|
+
"red" : "0xA5"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"idiom" : "universal"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"info" : {
|
|
35
|
+
"author" : "xcode",
|
|
36
|
+
"version" : 1
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// GENERATED by geeknative from contracts/icons.json. Do not edit: change the contract, then run `make gen`.
|
|
2
|
+
|
|
3
|
+
/// Icons as SF Symbol names. Use with `Image(systemName: AppIcon.settings)`.
|
|
4
|
+
nonisolated enum AppIcon {
|
|
5
|
+
static let back = "chevron.backward"
|
|
6
|
+
static let home = "house"
|
|
7
|
+
static let settings = "gearshape"
|
|
8
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sourceLanguage" : "en",
|
|
3
|
+
"strings" : {
|
|
4
|
+
"common.back" : {
|
|
5
|
+
"extractionState" : "manual",
|
|
6
|
+
"localizations" : {
|
|
7
|
+
"en" : {
|
|
8
|
+
"stringUnit" : {
|
|
9
|
+
"state" : "translated",
|
|
10
|
+
"value" : "Back"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"home.openSettings" : {
|
|
16
|
+
"extractionState" : "manual",
|
|
17
|
+
"localizations" : {
|
|
18
|
+
"en" : {
|
|
19
|
+
"stringUnit" : {
|
|
20
|
+
"state" : "translated",
|
|
21
|
+
"value" : "Settings"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"home.welcomeBody" : {
|
|
27
|
+
"extractionState" : "manual",
|
|
28
|
+
"localizations" : {
|
|
29
|
+
"en" : {
|
|
30
|
+
"stringUnit" : {
|
|
31
|
+
"state" : "translated",
|
|
32
|
+
"value" : "This app is built natively for iOS, Android and the web from one shared spec. Describe what you want to build to your coding agent, and it will build it for all three."
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"home.welcomeTitle" : {
|
|
38
|
+
"extractionState" : "manual",
|
|
39
|
+
"localizations" : {
|
|
40
|
+
"en" : {
|
|
41
|
+
"stringUnit" : {
|
|
42
|
+
"state" : "translated",
|
|
43
|
+
"value" : "You're all set"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"settings.about.title" : {
|
|
49
|
+
"extractionState" : "manual",
|
|
50
|
+
"localizations" : {
|
|
51
|
+
"en" : {
|
|
52
|
+
"stringUnit" : {
|
|
53
|
+
"state" : "translated",
|
|
54
|
+
"value" : "About"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"settings.about.version" : {
|
|
60
|
+
"extractionState" : "manual",
|
|
61
|
+
"localizations" : {
|
|
62
|
+
"en" : {
|
|
63
|
+
"stringUnit" : {
|
|
64
|
+
"state" : "translated",
|
|
65
|
+
"value" : "Version %1$@ (%2$lld)"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"settings.appearance.dark" : {
|
|
71
|
+
"extractionState" : "manual",
|
|
72
|
+
"localizations" : {
|
|
73
|
+
"en" : {
|
|
74
|
+
"stringUnit" : {
|
|
75
|
+
"state" : "translated",
|
|
76
|
+
"value" : "Dark"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"settings.appearance.light" : {
|
|
82
|
+
"extractionState" : "manual",
|
|
83
|
+
"localizations" : {
|
|
84
|
+
"en" : {
|
|
85
|
+
"stringUnit" : {
|
|
86
|
+
"state" : "translated",
|
|
87
|
+
"value" : "Light"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"settings.appearance.system" : {
|
|
93
|
+
"extractionState" : "manual",
|
|
94
|
+
"localizations" : {
|
|
95
|
+
"en" : {
|
|
96
|
+
"stringUnit" : {
|
|
97
|
+
"state" : "translated",
|
|
98
|
+
"value" : "System"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"settings.appearance.title" : {
|
|
104
|
+
"extractionState" : "manual",
|
|
105
|
+
"localizations" : {
|
|
106
|
+
"en" : {
|
|
107
|
+
"stringUnit" : {
|
|
108
|
+
"state" : "translated",
|
|
109
|
+
"value" : "Appearance"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"settings.title" : {
|
|
115
|
+
"extractionState" : "manual",
|
|
116
|
+
"localizations" : {
|
|
117
|
+
"en" : {
|
|
118
|
+
"stringUnit" : {
|
|
119
|
+
"state" : "translated",
|
|
120
|
+
"value" : "Settings"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"version" : "1.0"
|
|
127
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// GENERATED by geeknative from contracts/strings. Do not edit: change the contract, then run `make gen`.
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
/// User-facing copy. Keys and placeholders match the Android and web apps.
|
|
5
|
+
nonisolated enum Strings {
|
|
6
|
+
/// Back
|
|
7
|
+
static var commonBack: String { NSLocalizedString("common.back", comment: "") }
|
|
8
|
+
|
|
9
|
+
/// Settings
|
|
10
|
+
static var homeOpenSettings: String { NSLocalizedString("home.openSettings", comment: "") }
|
|
11
|
+
|
|
12
|
+
/// This app is built natively for iOS, Android and the web from one shared spec. Describe what you want to build to your coding agent, and it will build it for all three.
|
|
13
|
+
static var homeWelcomeBody: String { NSLocalizedString("home.welcomeBody", comment: "") }
|
|
14
|
+
|
|
15
|
+
/// You're all set
|
|
16
|
+
static var homeWelcomeTitle: String { NSLocalizedString("home.welcomeTitle", comment: "") }
|
|
17
|
+
|
|
18
|
+
/// About
|
|
19
|
+
static var settingsAboutTitle: String { NSLocalizedString("settings.about.title", comment: "") }
|
|
20
|
+
|
|
21
|
+
/// Version {version} ({build})
|
|
22
|
+
static func settingsAboutVersion(version: String, build: Int) -> String {
|
|
23
|
+
String.localizedStringWithFormat(NSLocalizedString("settings.about.version", comment: ""), version, build)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// Dark
|
|
27
|
+
static var settingsAppearanceDark: String { NSLocalizedString("settings.appearance.dark", comment: "") }
|
|
28
|
+
|
|
29
|
+
/// Light
|
|
30
|
+
static var settingsAppearanceLight: String { NSLocalizedString("settings.appearance.light", comment: "") }
|
|
31
|
+
|
|
32
|
+
/// System
|
|
33
|
+
static var settingsAppearanceSystem: String { NSLocalizedString("settings.appearance.system", comment: "") }
|
|
34
|
+
|
|
35
|
+
/// Appearance
|
|
36
|
+
static var settingsAppearanceTitle: String { NSLocalizedString("settings.appearance.title", comment: "") }
|
|
37
|
+
|
|
38
|
+
/// Settings
|
|
39
|
+
static var settingsTitle: String { NSLocalizedString("settings.title", comment: "") }
|
|
40
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// GENERATED by geeknative from contracts/tokens.json. Do not edit: change the contract, then run `make gen`.
|
|
2
|
+
import SwiftUI
|
|
3
|
+
import UIKit
|
|
4
|
+
|
|
5
|
+
/// Colors. Each one adapts to light and dark mode on its own.
|
|
6
|
+
nonisolated enum AppColors {
|
|
7
|
+
static let background = Color(light: 0xFFFFFFFF, dark: 0x0B0D12FF)
|
|
8
|
+
static let onBackground = Color(light: 0x0F172AFF, dark: 0xE6E8EEFF)
|
|
9
|
+
static let surface = Color(light: 0xF4F5F8FF, dark: 0x161A23FF)
|
|
10
|
+
static let onSurface = Color(light: 0x0F172AFF, dark: 0xE6E8EEFF)
|
|
11
|
+
static let surfaceVariant = Color(light: 0xE9EBF1FF, dark: 0x222735FF)
|
|
12
|
+
static let onSurfaceVariant = Color(light: 0x566074FF, dark: 0xA3ABBDFF)
|
|
13
|
+
static let primary = Color(light: 0x4F46E5FF, dark: 0xA5B4FCFF)
|
|
14
|
+
static let onPrimary = Color(light: 0xFFFFFFFF, dark: 0x1E1B4BFF)
|
|
15
|
+
static let outline = Color(light: 0xD8DCE5FF, dark: 0x2D3343FF)
|
|
16
|
+
static let error = Color(light: 0xDC2626FF, dark: 0xF87171FF)
|
|
17
|
+
static let onError = Color(light: 0xFFFFFFFF, dark: 0x450A0AFF)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/// Spacing, in points.
|
|
21
|
+
nonisolated enum AppSpacing {
|
|
22
|
+
static let xs: CGFloat = 4
|
|
23
|
+
static let sm: CGFloat = 8
|
|
24
|
+
static let md: CGFloat = 12
|
|
25
|
+
static let lg: CGFloat = 16
|
|
26
|
+
static let xl: CGFloat = 24
|
|
27
|
+
static let xxl: CGFloat = 32
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/// Corner radii, in points.
|
|
31
|
+
nonisolated enum AppRadius {
|
|
32
|
+
static let sm: CGFloat = 6
|
|
33
|
+
static let md: CGFloat = 10
|
|
34
|
+
static let lg: CGFloat = 16
|
|
35
|
+
static let full: CGFloat = 9999
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// Text styles. Each maps to a Dynamic Type style, so it follows the user's text size setting.
|
|
39
|
+
nonisolated enum AppTypography {
|
|
40
|
+
static let display: Font = .largeTitle.weight(.bold)
|
|
41
|
+
static let headline: Font = .title.weight(.bold)
|
|
42
|
+
static let title: Font = .title3.weight(.semibold)
|
|
43
|
+
static let body: Font = .body.weight(.regular)
|
|
44
|
+
static let label: Font = .subheadline.weight(.medium)
|
|
45
|
+
static let caption: Font = .caption.weight(.regular)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private extension Color {
|
|
49
|
+
nonisolated init(light: UInt32, dark: UInt32) {
|
|
50
|
+
self.init(uiColor: UIColor { traits in
|
|
51
|
+
UIColor(rgba: traits.userInterfaceStyle == .dark ? dark : light)
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private extension UIColor {
|
|
57
|
+
nonisolated convenience init(rgba: UInt32) {
|
|
58
|
+
self.init(
|
|
59
|
+
red: CGFloat((rgba >> 24) & 0xFF) / 255,
|
|
60
|
+
green: CGFloat((rgba >> 16) & 0xFF) / 255,
|
|
61
|
+
blue: CGFloat((rgba >> 8) & 0xFF) / 255,
|
|
62
|
+
alpha: CGFloat(rgba & 0xFF) / 255
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
// !$*UTF8*$!
|
|
2
|
+
{
|
|
3
|
+
archiveVersion = 1;
|
|
4
|
+
classes = {
|
|
5
|
+
};
|
|
6
|
+
objectVersion = 77;
|
|
7
|
+
objects = {
|
|
8
|
+
|
|
9
|
+
/* Begin PBXContainerItemProxy section */
|
|
10
|
+
A1B2C3D4E5F6000000000034 /* PBXContainerItemProxy */ = {
|
|
11
|
+
isa = PBXContainerItemProxy;
|
|
12
|
+
containerPortal = A1B2C3D4E5F6000000000001 /* Project object */;
|
|
13
|
+
proxyType = 1;
|
|
14
|
+
remoteGlobalIDString = A1B2C3D4E5F6000000000020;
|
|
15
|
+
remoteInfo = App;
|
|
16
|
+
};
|
|
17
|
+
/* End PBXContainerItemProxy section */
|
|
18
|
+
|
|
19
|
+
/* Begin PBXFileReference section */
|
|
20
|
+
A1B2C3D4E5F6000000000007 /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
21
|
+
A1B2C3D4E5F6000000000008 /* AppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
22
|
+
A1B2C3D4E5F6000000000010 /* Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
|
|
23
|
+
A1B2C3D4E5F6000000000011 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
|
24
|
+
A1B2C3D4E5F6000000000012 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
|
25
|
+
A1B2C3D4E5F6000000000013 /* App.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = App.xcconfig; sourceTree = "<group>"; };
|
|
26
|
+
A1B2C3D4E5F6000000000014 /* AppTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppTests.xcconfig; sourceTree = "<group>"; };
|
|
27
|
+
A1B2C3D4E5F6000000000015 /* Identity.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Identity.xcconfig; sourceTree = "<group>"; };
|
|
28
|
+
/* End PBXFileReference section */
|
|
29
|
+
|
|
30
|
+
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
|
31
|
+
A1B2C3D4E5F6000000000005 /* App */ = {
|
|
32
|
+
isa = PBXFileSystemSynchronizedRootGroup;
|
|
33
|
+
path = App;
|
|
34
|
+
sourceTree = "<group>";
|
|
35
|
+
};
|
|
36
|
+
A1B2C3D4E5F6000000000006 /* AppTests */ = {
|
|
37
|
+
isa = PBXFileSystemSynchronizedRootGroup;
|
|
38
|
+
path = AppTests;
|
|
39
|
+
sourceTree = "<group>";
|
|
40
|
+
};
|
|
41
|
+
/* End PBXFileSystemSynchronizedRootGroup section */
|
|
42
|
+
|
|
43
|
+
/* Begin PBXFrameworksBuildPhase section */
|
|
44
|
+
A1B2C3D4E5F6000000000022 /* Frameworks */ = {
|
|
45
|
+
isa = PBXFrameworksBuildPhase;
|
|
46
|
+
buildActionMask = 2147483647;
|
|
47
|
+
files = (
|
|
48
|
+
);
|
|
49
|
+
runOnlyForDeploymentPostprocessing = 0;
|
|
50
|
+
};
|
|
51
|
+
A1B2C3D4E5F6000000000032 /* Frameworks */ = {
|
|
52
|
+
isa = PBXFrameworksBuildPhase;
|
|
53
|
+
buildActionMask = 2147483647;
|
|
54
|
+
files = (
|
|
55
|
+
);
|
|
56
|
+
runOnlyForDeploymentPostprocessing = 0;
|
|
57
|
+
};
|
|
58
|
+
/* End PBXFrameworksBuildPhase section */
|
|
59
|
+
|
|
60
|
+
/* Begin PBXGroup section */
|
|
61
|
+
A1B2C3D4E5F6000000000002 = {
|
|
62
|
+
isa = PBXGroup;
|
|
63
|
+
children = (
|
|
64
|
+
A1B2C3D4E5F6000000000004 /* Config */,
|
|
65
|
+
A1B2C3D4E5F6000000000005 /* App */,
|
|
66
|
+
A1B2C3D4E5F6000000000006 /* AppTests */,
|
|
67
|
+
A1B2C3D4E5F6000000000003 /* Products */,
|
|
68
|
+
);
|
|
69
|
+
sourceTree = "<group>";
|
|
70
|
+
};
|
|
71
|
+
A1B2C3D4E5F6000000000003 /* Products */ = {
|
|
72
|
+
isa = PBXGroup;
|
|
73
|
+
children = (
|
|
74
|
+
A1B2C3D4E5F6000000000007 /* App.app */,
|
|
75
|
+
A1B2C3D4E5F6000000000008 /* AppTests.xctest */,
|
|
76
|
+
);
|
|
77
|
+
name = Products;
|
|
78
|
+
sourceTree = "<group>";
|
|
79
|
+
};
|
|
80
|
+
A1B2C3D4E5F6000000000004 /* Config */ = {
|
|
81
|
+
isa = PBXGroup;
|
|
82
|
+
children = (
|
|
83
|
+
A1B2C3D4E5F6000000000010 /* Base.xcconfig */,
|
|
84
|
+
A1B2C3D4E5F6000000000011 /* Debug.xcconfig */,
|
|
85
|
+
A1B2C3D4E5F6000000000012 /* Release.xcconfig */,
|
|
86
|
+
A1B2C3D4E5F6000000000013 /* App.xcconfig */,
|
|
87
|
+
A1B2C3D4E5F6000000000014 /* AppTests.xcconfig */,
|
|
88
|
+
A1B2C3D4E5F6000000000015 /* Identity.xcconfig */,
|
|
89
|
+
);
|
|
90
|
+
path = Config;
|
|
91
|
+
sourceTree = "<group>";
|
|
92
|
+
};
|
|
93
|
+
/* End PBXGroup section */
|
|
94
|
+
|
|
95
|
+
/* Begin PBXNativeTarget section */
|
|
96
|
+
A1B2C3D4E5F6000000000020 /* App */ = {
|
|
97
|
+
isa = PBXNativeTarget;
|
|
98
|
+
buildConfigurationList = A1B2C3D4E5F6000000000050 /* Build configuration list for PBXNativeTarget "App" */;
|
|
99
|
+
buildPhases = (
|
|
100
|
+
A1B2C3D4E5F6000000000021 /* Sources */,
|
|
101
|
+
A1B2C3D4E5F6000000000022 /* Frameworks */,
|
|
102
|
+
A1B2C3D4E5F6000000000023 /* Resources */,
|
|
103
|
+
);
|
|
104
|
+
buildRules = (
|
|
105
|
+
);
|
|
106
|
+
dependencies = (
|
|
107
|
+
);
|
|
108
|
+
fileSystemSynchronizedGroups = (
|
|
109
|
+
A1B2C3D4E5F6000000000005 /* App */,
|
|
110
|
+
);
|
|
111
|
+
name = App;
|
|
112
|
+
packageProductDependencies = (
|
|
113
|
+
);
|
|
114
|
+
productName = App;
|
|
115
|
+
productReference = A1B2C3D4E5F6000000000007 /* App.app */;
|
|
116
|
+
productType = "com.apple.product-type.application";
|
|
117
|
+
};
|
|
118
|
+
A1B2C3D4E5F6000000000030 /* AppTests */ = {
|
|
119
|
+
isa = PBXNativeTarget;
|
|
120
|
+
buildConfigurationList = A1B2C3D4E5F6000000000060 /* Build configuration list for PBXNativeTarget "AppTests" */;
|
|
121
|
+
buildPhases = (
|
|
122
|
+
A1B2C3D4E5F6000000000031 /* Sources */,
|
|
123
|
+
A1B2C3D4E5F6000000000032 /* Frameworks */,
|
|
124
|
+
A1B2C3D4E5F6000000000033 /* Resources */,
|
|
125
|
+
);
|
|
126
|
+
buildRules = (
|
|
127
|
+
);
|
|
128
|
+
dependencies = (
|
|
129
|
+
A1B2C3D4E5F6000000000035 /* PBXTargetDependency */,
|
|
130
|
+
);
|
|
131
|
+
fileSystemSynchronizedGroups = (
|
|
132
|
+
A1B2C3D4E5F6000000000006 /* AppTests */,
|
|
133
|
+
);
|
|
134
|
+
name = AppTests;
|
|
135
|
+
packageProductDependencies = (
|
|
136
|
+
);
|
|
137
|
+
productName = AppTests;
|
|
138
|
+
productReference = A1B2C3D4E5F6000000000008 /* AppTests.xctest */;
|
|
139
|
+
productType = "com.apple.product-type.bundle.unit-test";
|
|
140
|
+
};
|
|
141
|
+
/* End PBXNativeTarget section */
|
|
142
|
+
|
|
143
|
+
/* Begin PBXProject section */
|
|
144
|
+
A1B2C3D4E5F6000000000001 /* Project object */ = {
|
|
145
|
+
isa = PBXProject;
|
|
146
|
+
attributes = {
|
|
147
|
+
BuildIndependentTargetsInParallel = 1;
|
|
148
|
+
LastSwiftUpdateCheck = 2630;
|
|
149
|
+
LastUpgradeCheck = 2630;
|
|
150
|
+
TargetAttributes = {
|
|
151
|
+
A1B2C3D4E5F6000000000020 = {
|
|
152
|
+
CreatedOnToolsVersion = 26.3;
|
|
153
|
+
};
|
|
154
|
+
A1B2C3D4E5F6000000000030 = {
|
|
155
|
+
CreatedOnToolsVersion = 26.3;
|
|
156
|
+
TestTargetID = A1B2C3D4E5F6000000000020;
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
buildConfigurationList = A1B2C3D4E5F6000000000040 /* Build configuration list for PBXProject "App" */;
|
|
161
|
+
developmentRegion = en;
|
|
162
|
+
hasScannedForEncodings = 0;
|
|
163
|
+
knownRegions = (
|
|
164
|
+
en,
|
|
165
|
+
Base,
|
|
166
|
+
);
|
|
167
|
+
mainGroup = A1B2C3D4E5F6000000000002;
|
|
168
|
+
minimizedProjectReferenceProxies = 1;
|
|
169
|
+
preferredProjectObjectVersion = 77;
|
|
170
|
+
productRefGroup = A1B2C3D4E5F6000000000003 /* Products */;
|
|
171
|
+
projectDirPath = "";
|
|
172
|
+
projectRoot = "";
|
|
173
|
+
targets = (
|
|
174
|
+
A1B2C3D4E5F6000000000020 /* App */,
|
|
175
|
+
A1B2C3D4E5F6000000000030 /* AppTests */,
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
/* End PBXProject section */
|
|
179
|
+
|
|
180
|
+
/* Begin PBXResourcesBuildPhase section */
|
|
181
|
+
A1B2C3D4E5F6000000000023 /* Resources */ = {
|
|
182
|
+
isa = PBXResourcesBuildPhase;
|
|
183
|
+
buildActionMask = 2147483647;
|
|
184
|
+
files = (
|
|
185
|
+
);
|
|
186
|
+
runOnlyForDeploymentPostprocessing = 0;
|
|
187
|
+
};
|
|
188
|
+
A1B2C3D4E5F6000000000033 /* Resources */ = {
|
|
189
|
+
isa = PBXResourcesBuildPhase;
|
|
190
|
+
buildActionMask = 2147483647;
|
|
191
|
+
files = (
|
|
192
|
+
);
|
|
193
|
+
runOnlyForDeploymentPostprocessing = 0;
|
|
194
|
+
};
|
|
195
|
+
/* End PBXResourcesBuildPhase section */
|
|
196
|
+
|
|
197
|
+
/* Begin PBXSourcesBuildPhase section */
|
|
198
|
+
A1B2C3D4E5F6000000000021 /* Sources */ = {
|
|
199
|
+
isa = PBXSourcesBuildPhase;
|
|
200
|
+
buildActionMask = 2147483647;
|
|
201
|
+
files = (
|
|
202
|
+
);
|
|
203
|
+
runOnlyForDeploymentPostprocessing = 0;
|
|
204
|
+
};
|
|
205
|
+
A1B2C3D4E5F6000000000031 /* Sources */ = {
|
|
206
|
+
isa = PBXSourcesBuildPhase;
|
|
207
|
+
buildActionMask = 2147483647;
|
|
208
|
+
files = (
|
|
209
|
+
);
|
|
210
|
+
runOnlyForDeploymentPostprocessing = 0;
|
|
211
|
+
};
|
|
212
|
+
/* End PBXSourcesBuildPhase section */
|
|
213
|
+
|
|
214
|
+
/* Begin PBXTargetDependency section */
|
|
215
|
+
A1B2C3D4E5F6000000000035 /* PBXTargetDependency */ = {
|
|
216
|
+
isa = PBXTargetDependency;
|
|
217
|
+
target = A1B2C3D4E5F6000000000020 /* App */;
|
|
218
|
+
targetProxy = A1B2C3D4E5F6000000000034 /* PBXContainerItemProxy */;
|
|
219
|
+
};
|
|
220
|
+
/* End PBXTargetDependency section */
|
|
221
|
+
|
|
222
|
+
/* Begin XCBuildConfiguration section */
|
|
223
|
+
A1B2C3D4E5F6000000000041 /* Debug */ = {
|
|
224
|
+
isa = XCBuildConfiguration;
|
|
225
|
+
baseConfigurationReference = A1B2C3D4E5F6000000000011 /* Debug.xcconfig */;
|
|
226
|
+
buildSettings = {
|
|
227
|
+
};
|
|
228
|
+
name = Debug;
|
|
229
|
+
};
|
|
230
|
+
A1B2C3D4E5F6000000000042 /* Release */ = {
|
|
231
|
+
isa = XCBuildConfiguration;
|
|
232
|
+
baseConfigurationReference = A1B2C3D4E5F6000000000012 /* Release.xcconfig */;
|
|
233
|
+
buildSettings = {
|
|
234
|
+
};
|
|
235
|
+
name = Release;
|
|
236
|
+
};
|
|
237
|
+
A1B2C3D4E5F6000000000051 /* Debug */ = {
|
|
238
|
+
isa = XCBuildConfiguration;
|
|
239
|
+
baseConfigurationReference = A1B2C3D4E5F6000000000013 /* App.xcconfig */;
|
|
240
|
+
buildSettings = {
|
|
241
|
+
};
|
|
242
|
+
name = Debug;
|
|
243
|
+
};
|
|
244
|
+
A1B2C3D4E5F6000000000052 /* Release */ = {
|
|
245
|
+
isa = XCBuildConfiguration;
|
|
246
|
+
baseConfigurationReference = A1B2C3D4E5F6000000000013 /* App.xcconfig */;
|
|
247
|
+
buildSettings = {
|
|
248
|
+
};
|
|
249
|
+
name = Release;
|
|
250
|
+
};
|
|
251
|
+
A1B2C3D4E5F6000000000061 /* Debug */ = {
|
|
252
|
+
isa = XCBuildConfiguration;
|
|
253
|
+
baseConfigurationReference = A1B2C3D4E5F6000000000014 /* AppTests.xcconfig */;
|
|
254
|
+
buildSettings = {
|
|
255
|
+
};
|
|
256
|
+
name = Debug;
|
|
257
|
+
};
|
|
258
|
+
A1B2C3D4E5F6000000000062 /* Release */ = {
|
|
259
|
+
isa = XCBuildConfiguration;
|
|
260
|
+
baseConfigurationReference = A1B2C3D4E5F6000000000014 /* AppTests.xcconfig */;
|
|
261
|
+
buildSettings = {
|
|
262
|
+
};
|
|
263
|
+
name = Release;
|
|
264
|
+
};
|
|
265
|
+
/* End XCBuildConfiguration section */
|
|
266
|
+
|
|
267
|
+
/* Begin XCConfigurationList section */
|
|
268
|
+
A1B2C3D4E5F6000000000040 /* Build configuration list for PBXProject "App" */ = {
|
|
269
|
+
isa = XCConfigurationList;
|
|
270
|
+
buildConfigurations = (
|
|
271
|
+
A1B2C3D4E5F6000000000041 /* Debug */,
|
|
272
|
+
A1B2C3D4E5F6000000000042 /* Release */,
|
|
273
|
+
);
|
|
274
|
+
defaultConfigurationIsVisible = 0;
|
|
275
|
+
defaultConfigurationName = Release;
|
|
276
|
+
};
|
|
277
|
+
A1B2C3D4E5F6000000000050 /* Build configuration list for PBXNativeTarget "App" */ = {
|
|
278
|
+
isa = XCConfigurationList;
|
|
279
|
+
buildConfigurations = (
|
|
280
|
+
A1B2C3D4E5F6000000000051 /* Debug */,
|
|
281
|
+
A1B2C3D4E5F6000000000052 /* Release */,
|
|
282
|
+
);
|
|
283
|
+
defaultConfigurationIsVisible = 0;
|
|
284
|
+
defaultConfigurationName = Release;
|
|
285
|
+
};
|
|
286
|
+
A1B2C3D4E5F6000000000060 /* Build configuration list for PBXNativeTarget "AppTests" */ = {
|
|
287
|
+
isa = XCConfigurationList;
|
|
288
|
+
buildConfigurations = (
|
|
289
|
+
A1B2C3D4E5F6000000000061 /* Debug */,
|
|
290
|
+
A1B2C3D4E5F6000000000062 /* Release */,
|
|
291
|
+
);
|
|
292
|
+
defaultConfigurationIsVisible = 0;
|
|
293
|
+
defaultConfigurationName = Release;
|
|
294
|
+
};
|
|
295
|
+
/* End XCConfigurationList section */
|
|
296
|
+
};
|
|
297
|
+
rootObject = A1B2C3D4E5F6000000000001 /* Project object */;
|
|
298
|
+
}
|