openuispec 0.2.9 → 0.2.11
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/README.md +3 -1
- package/cli/index.ts +80 -2
- package/cli/init.ts +23 -8
- package/docs/cli.md +42 -7
- package/drift/index.ts +41 -15
- package/mcp-server/index.ts +247 -117
- package/mcp-server/screenshot-android.ts +185 -44
- package/mcp-server/screenshot-ios.ts +242 -30
- package/mcp-server/screenshot.ts +96 -1
- package/package.json +5 -2
- package/prepare/index.ts +16 -0
- package/scripts/take-all-screenshots.ts +507 -0
- package/status/index.ts +2 -2
- package/examples/social-app/.mcp.json +0 -10
- package/examples/social-app/AGENTS.md +0 -124
- package/examples/social-app/CLAUDE.md +0 -124
- package/examples/social-app/backend/.gitkeep +0 -1
- package/examples/social-app/generated/android/social-app/app/.paparazzi-hashes.json +0 -3
- package/examples/social-app/generated/android/social-app/app/build.gradle.kts +0 -94
- package/examples/social-app/generated/android/social-app/app/src/main/AndroidManifest.xml +0 -26
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/AppContainer.kt +0 -20
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/MainActivity.kt +0 -35
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/SocialAppApplication.kt +0 -13
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/MockData.kt +0 -98
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/AppPreferences.kt +0 -19
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/DataStorePreferencesRepository.kt +0 -68
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/PreferencesRepository.kt +0 -15
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/model/Models.kt +0 -34
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/MainShell.kt +0 -390
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/components/Components.kt +0 -234
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/components/ContractPrimitives.kt +0 -641
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/navigation/RootComponent.kt +0 -113
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/ChatDetailScreen.kt +0 -212
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/CreatePostScreen.kt +0 -113
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/DiscoverScreen.kt +0 -137
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/EditProfileScreen.kt +0 -180
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/HomeFeedScreen.kt +0 -169
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/MessagesInboxScreen.kt +0 -85
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/NotificationsScreen.kt +0 -74
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/PostDetailScreen.kt +0 -293
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/ProfileSelfScreen.kt +0 -116
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SearchResultsScreen.kt +0 -161
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SettingsScreen.kt +0 -164
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SettingsStore.kt +0 -95
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/UserProfileScreen.kt +0 -123
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Color.kt +0 -33
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Shape.kt +0 -41
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Spacing.kt +0 -20
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Theme.kt +0 -82
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Type.kt +0 -60
- package/examples/social-app/generated/android/social-app/app/src/main/res/drawable/ic_launcher_foreground.xml +0 -9
- package/examples/social-app/generated/android/social-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +0 -5
- package/examples/social-app/generated/android/social-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +0 -5
- package/examples/social-app/generated/android/social-app/app/src/main/res/values/strings.xml +0 -91
- package/examples/social-app/generated/android/social-app/app/src/main/res/values/themes.xml +0 -10
- package/examples/social-app/generated/android/social-app/app/src/main/res/values-ru/strings.xml +0 -79
- package/examples/social-app/generated/android/social-app/app/src/main/res/values-uz/strings.xml +0 -79
- package/examples/social-app/generated/android/social-app/app/src/main/xml/AndroidManifest.xml +0 -23
- package/examples/social-app/generated/android/social-app/app/src/test/kotlin/com/social/app/screenshots/HomeFeedScreenshotTest.kt +0 -34
- package/examples/social-app/generated/android/social-app/build.gradle.kts +0 -7
- package/examples/social-app/generated/android/social-app/gradle/libs.versions.toml +0 -50
- package/examples/social-app/generated/android/social-app/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/examples/social-app/generated/android/social-app/gradle/wrapper/gradle-wrapper.properties +0 -8
- package/examples/social-app/generated/android/social-app/gradle.properties +0 -11
- package/examples/social-app/generated/android/social-app/gradlew +0 -248
- package/examples/social-app/generated/android/social-app/settings.gradle.kts +0 -27
- package/examples/social-app/generated/web/social-app/index.html +0 -12
- package/examples/social-app/generated/web/social-app/package-lock.json +0 -2517
- package/examples/social-app/generated/web/social-app/package.json +0 -27
- package/examples/social-app/generated/web/social-app/src/app/App.tsx +0 -58
- package/examples/social-app/generated/web/social-app/src/components/Shell.tsx +0 -259
- package/examples/social-app/generated/web/social-app/src/components/cards.tsx +0 -317
- package/examples/social-app/generated/web/social-app/src/components/ui.tsx +0 -340
- package/examples/social-app/generated/web/social-app/src/flows/CreatePostFlow.tsx +0 -86
- package/examples/social-app/generated/web/social-app/src/i18n.tsx +0 -59
- package/examples/social-app/generated/web/social-app/src/lib/icons.tsx +0 -85
- package/examples/social-app/generated/web/social-app/src/lib/tokens.ts +0 -70
- package/examples/social-app/generated/web/social-app/src/lib/utils.ts +0 -97
- package/examples/social-app/generated/web/social-app/src/locales/en.json +0 -67
- package/examples/social-app/generated/web/social-app/src/locales/ru.json +0 -67
- package/examples/social-app/generated/web/social-app/src/locales/uz.json +0 -67
- package/examples/social-app/generated/web/social-app/src/main.tsx +0 -16
- package/examples/social-app/generated/web/social-app/src/screens/ChatDetailScreen.tsx +0 -90
- package/examples/social-app/generated/web/social-app/src/screens/DiscoverScreen.tsx +0 -86
- package/examples/social-app/generated/web/social-app/src/screens/EditProfileScreen.tsx +0 -57
- package/examples/social-app/generated/web/social-app/src/screens/HomeFeedScreen.tsx +0 -103
- package/examples/social-app/generated/web/social-app/src/screens/MessagesInboxScreen.tsx +0 -52
- package/examples/social-app/generated/web/social-app/src/screens/NotificationsScreen.tsx +0 -41
- package/examples/social-app/generated/web/social-app/src/screens/PostDetailScreen.tsx +0 -115
- package/examples/social-app/generated/web/social-app/src/screens/ProfileSelfScreen.tsx +0 -57
- package/examples/social-app/generated/web/social-app/src/screens/ProfileUserScreen.tsx +0 -76
- package/examples/social-app/generated/web/social-app/src/screens/SearchResultsScreen.tsx +0 -96
- package/examples/social-app/generated/web/social-app/src/screens/SettingsScreen.tsx +0 -79
- package/examples/social-app/generated/web/social-app/src/state/store.ts +0 -592
- package/examples/social-app/generated/web/social-app/src/styles.css +0 -125
- package/examples/social-app/generated/web/social-app/src/vite-env.d.ts +0 -1
- package/examples/social-app/generated/web/social-app/tsconfig.json +0 -22
- package/examples/social-app/generated/web/social-app/tsconfig.node.json +0 -13
- package/examples/social-app/generated/web/social-app/tsconfig.node.tsbuildinfo +0 -1
- package/examples/social-app/generated/web/social-app/tsconfig.tsbuildinfo +0 -1
- package/examples/social-app/generated/web/social-app/vite.config.d.ts +0 -2
- package/examples/social-app/generated/web/social-app/vite.config.js +0 -6
- package/examples/social-app/generated/web/social-app/vite.config.ts +0 -7
- package/examples/social-app/package.json +0 -13
- package/examples/social-app/take-web-screenshots.ts +0 -97
- package/examples/taskflow/.codex/config.toml +0 -4
- package/examples/taskflow/.mcp.json +0 -10
- package/examples/taskflow/AGENTS.md +0 -124
- package/examples/taskflow/CLAUDE.md +0 -124
- package/examples/taskflow/backend/.gitkeep +0 -1
- package/examples/taskflow/generated/android/TaskFlow/README.md +0 -43
- package/examples/taskflow/generated/android/TaskFlow/app/build.gradle.kts +0 -76
- package/examples/taskflow/generated/android/TaskFlow/app/proguard-rules.pro +0 -1
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/AndroidManifest.xml +0 -21
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/MainActivity.kt +0 -19
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/TaskFlowApp.kt +0 -283
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/model/DomainModels.kt +0 -106
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/model/SampleData.kt +0 -57
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/components/Common.kt +0 -109
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/HomeScreen.kt +0 -112
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/ProjectsScreen.kt +0 -61
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/SettingsScreen.kt +0 -82
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/screens/TaskDetailScreen.kt +0 -111
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/sheets/Sheets.kt +0 -77
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Color.kt +0 -30
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Theme.kt +0 -86
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/java/uz/rsteam/taskflow/ui/theme/Type.kt +0 -57
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/res/values/strings.xml +0 -155
- package/examples/taskflow/generated/android/TaskFlow/app/src/main/res/values/themes.xml +0 -4
- package/examples/taskflow/generated/android/TaskFlow/build.gradle.kts +0 -5
- package/examples/taskflow/generated/android/TaskFlow/gradle/gradle-daemon-jvm.properties +0 -12
- package/examples/taskflow/generated/android/TaskFlow/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/examples/taskflow/generated/android/TaskFlow/gradle/wrapper/gradle-wrapper.properties +0 -7
- package/examples/taskflow/generated/android/TaskFlow/gradle.properties +0 -4
- package/examples/taskflow/generated/android/TaskFlow/gradlew +0 -18
- package/examples/taskflow/generated/android/TaskFlow/gradlew.bat +0 -12
- package/examples/taskflow/generated/android/TaskFlow/settings.gradle.kts +0 -18
- package/examples/taskflow/generated/ios/TaskFlow/README.md +0 -21
- package/examples/taskflow/generated/ios/TaskFlow/Resources/en.lproj/Localizable.strings +0 -115
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/App/TaskFlowApp.swift +0 -24
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Components/AppChrome.swift +0 -150
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Flows/TaskEditorSheet.swift +0 -220
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Models/DomainModels.swift +0 -122
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/CalendarView.swift +0 -21
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/HomeView.swift +0 -201
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProfileEditView.swift +0 -48
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProjectDetailView.swift +0 -59
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/ProjectsView.swift +0 -63
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/SettingsView.swift +0 -85
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Screens/TaskDetailView.swift +0 -219
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Support/AppModel.swift +0 -320
- package/examples/taskflow/generated/ios/TaskFlow/Sources/TaskFlow/Support/AppSupport.swift +0 -41
- package/examples/taskflow/generated/ios/TaskFlow/project.yml +0 -26
- package/examples/taskflow/generated/web/TaskFlow/README.md +0 -19
- package/examples/taskflow/generated/web/TaskFlow/index.html +0 -12
- package/examples/taskflow/generated/web/TaskFlow/package-lock.json +0 -1908
- package/examples/taskflow/generated/web/TaskFlow/package.json +0 -24
- package/examples/taskflow/generated/web/TaskFlow/src/App.tsx +0 -58
- package/examples/taskflow/generated/web/TaskFlow/src/AppShell.tsx +0 -55
- package/examples/taskflow/generated/web/TaskFlow/src/components/Common.tsx +0 -82
- package/examples/taskflow/generated/web/TaskFlow/src/components/Modals.tsx +0 -191
- package/examples/taskflow/generated/web/TaskFlow/src/components/Nav.tsx +0 -41
- package/examples/taskflow/generated/web/TaskFlow/src/generated/messages.ts +0 -131
- package/examples/taskflow/generated/web/TaskFlow/src/hooks.ts +0 -25
- package/examples/taskflow/generated/web/TaskFlow/src/i18n.ts +0 -39
- package/examples/taskflow/generated/web/TaskFlow/src/locales.en.json +0 -111
- package/examples/taskflow/generated/web/TaskFlow/src/main.tsx +0 -13
- package/examples/taskflow/generated/web/TaskFlow/src/screens/HomeScreen.tsx +0 -111
- package/examples/taskflow/generated/web/TaskFlow/src/screens/ProjectsScreen.tsx +0 -82
- package/examples/taskflow/generated/web/TaskFlow/src/screens/SettingsScreens.tsx +0 -132
- package/examples/taskflow/generated/web/TaskFlow/src/screens/TaskDetail.tsx +0 -105
- package/examples/taskflow/generated/web/TaskFlow/src/store.ts +0 -216
- package/examples/taskflow/generated/web/TaskFlow/src/styles.css +0 -617
- package/examples/taskflow/generated/web/TaskFlow/src/types.ts +0 -64
- package/examples/taskflow/generated/web/TaskFlow/src/utils.ts +0 -78
- package/examples/taskflow/generated/web/TaskFlow/tsconfig.json +0 -21
- package/examples/taskflow/generated/web/TaskFlow/vite.config.ts +0 -6
- package/examples/todo-orbit/.codex/config.toml +0 -4
- package/examples/todo-orbit/.mcp.json +0 -10
- package/examples/todo-orbit/AGENTS.md +0 -124
- package/examples/todo-orbit/CLAUDE.md +0 -124
- package/examples/todo-orbit/backend/.gitkeep +0 -1
- package/examples/todo-orbit/generated/android/Todo Orbit/README.md +0 -14
- package/examples/todo-orbit/generated/android/Todo Orbit/app/build.gradle.kts +0 -58
- package/examples/todo-orbit/generated/android/Todo Orbit/app/proguard-rules.pro +0 -1
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/AndroidManifest.xml +0 -20
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/MainActivity.kt +0 -14
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/TodoOrbitApp.kt +0 -345
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/AppLogic.kt +0 -231
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/Models.kt +0 -169
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/Strings.kt +0 -8
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/components/CommonComponents.kt +0 -236
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/AnalyticsScreen.kt +0 -193
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/SettingsScreen.kt +0 -102
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/TasksScreen.kt +0 -347
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/sheets/EditorSheets.kt +0 -347
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/theme/TodoOrbitTheme.kt +0 -59
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values/strings.xml +0 -149
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values-ru/strings.xml +0 -155
- package/examples/todo-orbit/generated/android/Todo Orbit/build.gradle.kts +0 -4
- package/examples/todo-orbit/generated/android/Todo Orbit/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/gradle/wrapper/gradle-wrapper.properties +0 -7
- package/examples/todo-orbit/generated/android/Todo Orbit/gradle.properties +0 -4
- package/examples/todo-orbit/generated/android/Todo Orbit/gradlew +0 -248
- package/examples/todo-orbit/generated/android/Todo Orbit/gradlew.bat +0 -93
- package/examples/todo-orbit/generated/android/Todo Orbit/settings.gradle.kts +0 -18
- package/examples/todo-orbit/generated/ios/Todo Orbit/.screenshot-uitest/Sources/ScreenshotUITest.swift +0 -36
- package/examples/todo-orbit/generated/ios/Todo Orbit/README.md +0 -29
- package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/en.lproj/Localizable.strings +0 -119
- package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/ru.lproj/Localizable.strings +0 -119
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/App/TodoOrbitApp.swift +0 -50
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/OrbitChrome.swift +0 -204
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/SchedulePreviewView.swift +0 -126
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/TrendChartView.swift +0 -70
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/RecurringRuleSheet.swift +0 -126
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/TaskEditorSheet.swift +0 -61
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Models/DomainModels.swift +0 -238
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/AnalyticsView.swift +0 -94
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/SettingsView.swift +0 -76
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/TasksHomeView.swift +0 -364
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Support/AppModel.swift +0 -324
- package/examples/todo-orbit/generated/ios/Todo Orbit/TodoOrbit.xcodeproj/project.pbxproj +0 -400
- package/examples/todo-orbit/generated/ios/Todo Orbit/TodoOrbit.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- package/examples/todo-orbit/generated/ios/Todo Orbit/project.yml +0 -25
- package/examples/todo-orbit/generated/web/Todo Orbit/index.html +0 -16
- package/examples/todo-orbit/generated/web/Todo Orbit/package-lock.json +0 -1087
- package/examples/todo-orbit/generated/web/Todo Orbit/package.json +0 -24
- package/examples/todo-orbit/generated/web/Todo Orbit/src/App.tsx +0 -2167
- package/examples/todo-orbit/generated/web/Todo Orbit/src/main.tsx +0 -13
- package/examples/todo-orbit/generated/web/Todo Orbit/src/styles.css +0 -926
- package/examples/todo-orbit/generated/web/Todo Orbit/tsconfig.json +0 -19
- package/examples/todo-orbit/generated/web/Todo Orbit/vite.config.ts +0 -6
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import Charts
|
|
2
|
-
import SwiftUI
|
|
3
|
-
|
|
4
|
-
struct TrendChartView: View {
|
|
5
|
-
let title: String
|
|
6
|
-
let subtitle: String
|
|
7
|
-
let emptyMessage: String
|
|
8
|
-
let legendCompleted: String
|
|
9
|
-
let legendCreated: String
|
|
10
|
-
let points: [TrendPoint]
|
|
11
|
-
|
|
12
|
-
var body: some View {
|
|
13
|
-
VStack(alignment: .leading, spacing: 14) {
|
|
14
|
-
Text(subtitle)
|
|
15
|
-
.font(.caption.weight(.bold))
|
|
16
|
-
.foregroundStyle(.secondary)
|
|
17
|
-
.textCase(.uppercase)
|
|
18
|
-
Text(title)
|
|
19
|
-
.font(.title3.weight(.semibold))
|
|
20
|
-
|
|
21
|
-
if points.isEmpty {
|
|
22
|
-
Text(emptyMessage)
|
|
23
|
-
.font(.body)
|
|
24
|
-
.foregroundStyle(.secondary)
|
|
25
|
-
.frame(maxWidth: .infinity, alignment: .leading)
|
|
26
|
-
.padding(.vertical, 40)
|
|
27
|
-
} else {
|
|
28
|
-
Chart(points) { point in
|
|
29
|
-
LineMark(
|
|
30
|
-
x: .value("Label", point.label),
|
|
31
|
-
y: .value(legendCreated, point.created)
|
|
32
|
-
)
|
|
33
|
-
.foregroundStyle(.orange)
|
|
34
|
-
.interpolationMethod(.catmullRom)
|
|
35
|
-
|
|
36
|
-
LineMark(
|
|
37
|
-
x: .value("Label", point.label),
|
|
38
|
-
y: .value(legendCompleted, point.completed)
|
|
39
|
-
)
|
|
40
|
-
.foregroundStyle(.teal)
|
|
41
|
-
.interpolationMethod(.catmullRom)
|
|
42
|
-
|
|
43
|
-
AreaMark(
|
|
44
|
-
x: .value("Label", point.label),
|
|
45
|
-
y: .value(legendCompleted, point.completed)
|
|
46
|
-
)
|
|
47
|
-
.foregroundStyle(.teal.opacity(0.08))
|
|
48
|
-
}
|
|
49
|
-
.frame(height: 280)
|
|
50
|
-
|
|
51
|
-
HStack(spacing: 18) {
|
|
52
|
-
legend(.teal, title: legendCompleted)
|
|
53
|
-
legend(.orange, title: legendCreated)
|
|
54
|
-
}
|
|
55
|
-
.font(.footnote)
|
|
56
|
-
.foregroundStyle(.secondary)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
.orbitCard(fill: Color(uiColor: .systemBackground), stroke: Color.teal.opacity(0.18))
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
private func legend(_ color: Color, title: String) -> some View {
|
|
63
|
-
HStack(spacing: 8) {
|
|
64
|
-
Circle()
|
|
65
|
-
.fill(color)
|
|
66
|
-
.frame(width: 10, height: 10)
|
|
67
|
-
Text(title)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import SwiftUI
|
|
2
|
-
|
|
3
|
-
struct RecurringRuleSheet: View {
|
|
4
|
-
@Environment(\.dismiss) private var dismiss
|
|
5
|
-
@ObservedObject var model: AppModel
|
|
6
|
-
|
|
7
|
-
@State private var draft = RecurringRuleDraft()
|
|
8
|
-
@State private var errors: [String: String] = [:]
|
|
9
|
-
|
|
10
|
-
var body: some View {
|
|
11
|
-
NavigationStack {
|
|
12
|
-
ScrollView {
|
|
13
|
-
VStack(alignment: .leading, spacing: 18) {
|
|
14
|
-
if !errors.isEmpty {
|
|
15
|
-
Text(model.string("validation.fix_errors"))
|
|
16
|
-
.font(.footnote.weight(.medium))
|
|
17
|
-
.foregroundStyle(.orange)
|
|
18
|
-
.padding(14)
|
|
19
|
-
.frame(maxWidth: .infinity, alignment: .leading)
|
|
20
|
-
.background(Color.orange.opacity(0.1), in: CutCornerShape(cut: 12))
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
VStack(spacing: 14) {
|
|
24
|
-
TextField(model.string("recurring_rule.field_name"), text: $draft.name)
|
|
25
|
-
errorText("name")
|
|
26
|
-
|
|
27
|
-
TextField(model.string("recurring_rule.field_confirm_name"), text: $draft.confirmName)
|
|
28
|
-
errorText("confirmName")
|
|
29
|
-
|
|
30
|
-
Picker(model.string("recurring_rule.field_cadence"), selection: $draft.cadence) {
|
|
31
|
-
Text("—").tag(RecurrenceCadence?.none)
|
|
32
|
-
ForEach(RecurrenceCadence.allCases) { cadence in
|
|
33
|
-
Text(model.string("recurring_rule.cadence_\(cadence.rawValue)"))
|
|
34
|
-
.tag(RecurrenceCadence?.some(cadence))
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
.pickerStyle(.segmented)
|
|
38
|
-
errorText("cadence")
|
|
39
|
-
|
|
40
|
-
TextField(model.string("recurring_rule.field_interval"), text: $draft.interval)
|
|
41
|
-
.keyboardType(.numberPad)
|
|
42
|
-
errorText("interval")
|
|
43
|
-
|
|
44
|
-
if draft.cadence == .weekly {
|
|
45
|
-
Picker(model.string("recurring_rule.field_weekday"), selection: $draft.weekday) {
|
|
46
|
-
Text("—").tag(Weekday?.none)
|
|
47
|
-
ForEach(Weekday.allCases) { weekday in
|
|
48
|
-
Text(model.label(for: weekday)).tag(Weekday?.some(weekday))
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
.pickerStyle(.menu)
|
|
52
|
-
errorText("weekday")
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if draft.cadence == .monthly {
|
|
56
|
-
TextField(model.string("recurring_rule.field_month_day"), text: $draft.monthDay)
|
|
57
|
-
.keyboardType(.numberPad)
|
|
58
|
-
errorText("monthDay")
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
DatePicker(model.string("recurring_rule.field_start_date"), selection: $draft.startDate, displayedComponents: .date)
|
|
62
|
-
|
|
63
|
-
Toggle(model.string("recurring_rule.field_has_end_date"), isOn: $draft.hasEndDate)
|
|
64
|
-
if draft.hasEndDate {
|
|
65
|
-
DatePicker(model.string("recurring_rule.field_end_date"), selection: $draft.endDate, displayedComponents: .date)
|
|
66
|
-
errorText("endDate")
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if model.preferences.remindersEnabled {
|
|
70
|
-
TextField(model.string("recurring_rule.field_remind_at"), text: $draft.remindAt)
|
|
71
|
-
.textInputAutocapitalization(.never)
|
|
72
|
-
errorText("remindAt")
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
Toggle(model.string("recurring_rule.field_enable_summary"), isOn: $draft.enableSummary)
|
|
76
|
-
if draft.enableSummary {
|
|
77
|
-
Picker(model.string("recurring_rule.field_summary_channel"), selection: $draft.summaryChannel) {
|
|
78
|
-
Text("—").tag(SummaryChannel?.none)
|
|
79
|
-
ForEach(SummaryChannel.allCases) { channel in
|
|
80
|
-
Text(model.string("recurring_rule.summary_\(channel.rawValue)"))
|
|
81
|
-
.tag(SummaryChannel?.some(channel))
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
.pickerStyle(.segmented)
|
|
85
|
-
errorText("summaryChannel")
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
.textFieldStyle(.roundedBorder)
|
|
89
|
-
.orbitCard(fill: Color(uiColor: .secondarySystemGroupedBackground), stroke: Color.teal.opacity(0.18))
|
|
90
|
-
|
|
91
|
-
SchedulePreviewView(
|
|
92
|
-
model: model,
|
|
93
|
-
title: model.string("recurring_preview.title"),
|
|
94
|
-
result: SchedulePreviewView.compute(from: draft)
|
|
95
|
-
)
|
|
96
|
-
}
|
|
97
|
-
.padding()
|
|
98
|
-
}
|
|
99
|
-
.navigationTitle(model.string("recurring_rule.title"))
|
|
100
|
-
.toolbar {
|
|
101
|
-
ToolbarItem(placement: .topBarLeading) {
|
|
102
|
-
Button(model.string("common.cancel")) { dismiss() }
|
|
103
|
-
}
|
|
104
|
-
ToolbarItem(placement: .topBarTrailing) {
|
|
105
|
-
Button(model.string("recurring_rule.save")) {
|
|
106
|
-
errors = model.addRecurringRule(from: draft)
|
|
107
|
-
if errors.isEmpty {
|
|
108
|
-
dismiss()
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
.presentationDetents([.large])
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
@ViewBuilder
|
|
118
|
-
private func errorText(_ key: String) -> some View {
|
|
119
|
-
if let message = errors[key] {
|
|
120
|
-
Text(message)
|
|
121
|
-
.font(.footnote)
|
|
122
|
-
.foregroundStyle(.red)
|
|
123
|
-
.frame(maxWidth: .infinity, alignment: .leading)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/TaskEditorSheet.swift
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import SwiftUI
|
|
2
|
-
|
|
3
|
-
struct TaskEditorSheet: View {
|
|
4
|
-
@Environment(\.dismiss) private var dismiss
|
|
5
|
-
@ObservedObject var model: AppModel
|
|
6
|
-
let editingTaskID: UUID?
|
|
7
|
-
|
|
8
|
-
@State private var draft = TaskEditorDraft(title: "", notes: "", priority: .medium, dueDate: nil)
|
|
9
|
-
@State private var validationError: String?
|
|
10
|
-
|
|
11
|
-
var body: some View {
|
|
12
|
-
NavigationStack {
|
|
13
|
-
Form {
|
|
14
|
-
if let validationError {
|
|
15
|
-
Section {
|
|
16
|
-
Text(validationError)
|
|
17
|
-
.font(.footnote.weight(.medium))
|
|
18
|
-
.foregroundStyle(.red)
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
Section {
|
|
23
|
-
TextField(model.string(editingTaskID == nil ? "create_task.field_title" : "edit_task.field_title"), text: $draft.title)
|
|
24
|
-
TextField(model.string(editingTaskID == nil ? "create_task.field_notes" : "edit_task.field_notes"), text: $draft.notes, axis: .vertical)
|
|
25
|
-
Picker(model.string(editingTaskID == nil ? "create_task.field_priority" : "edit_task.field_priority"), selection: $draft.priority) {
|
|
26
|
-
ForEach(TaskPriority.allCases) { priority in
|
|
27
|
-
Text(model.label(for: priority)).tag(priority)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
.pickerStyle(.segmented)
|
|
31
|
-
DatePicker(
|
|
32
|
-
model.string(editingTaskID == nil ? "create_task.field_due_date" : "edit_task.field_due_date"),
|
|
33
|
-
selection: Binding(
|
|
34
|
-
get: { draft.dueDate ?? .now },
|
|
35
|
-
set: { draft.dueDate = $0 }
|
|
36
|
-
),
|
|
37
|
-
displayedComponents: .date
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
.navigationTitle(model.string(editingTaskID == nil ? "create_task.title" : "edit_task.title"))
|
|
42
|
-
.toolbar {
|
|
43
|
-
ToolbarItem(placement: .topBarLeading) {
|
|
44
|
-
Button(model.string("common.cancel")) { dismiss() }
|
|
45
|
-
}
|
|
46
|
-
ToolbarItem(placement: .topBarTrailing) {
|
|
47
|
-
Button(model.string(editingTaskID == nil ? "create_task.save" : "edit_task.save")) {
|
|
48
|
-
validationError = model.submitTask(draft, editing: editingTaskID)
|
|
49
|
-
if validationError == nil {
|
|
50
|
-
dismiss()
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
.onAppear {
|
|
57
|
-
draft = model.makeTaskDraft(for: model.task(id: editingTaskID))
|
|
58
|
-
}
|
|
59
|
-
.presentationDetents([.medium, .large])
|
|
60
|
-
}
|
|
61
|
-
}
|
package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Models/DomainModels.swift
DELETED
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import SwiftUI
|
|
3
|
-
|
|
4
|
-
enum AppLocale: String, CaseIterable, Identifiable {
|
|
5
|
-
case en
|
|
6
|
-
case ru
|
|
7
|
-
|
|
8
|
-
var id: String { rawValue }
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
enum ThemePreference: String, CaseIterable, Identifiable {
|
|
12
|
-
case light
|
|
13
|
-
case dark
|
|
14
|
-
|
|
15
|
-
var id: String { rawValue }
|
|
16
|
-
|
|
17
|
-
var colorScheme: ColorScheme {
|
|
18
|
-
switch self {
|
|
19
|
-
case .light: .light
|
|
20
|
-
case .dark: .dark
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
enum TaskStatus: String, CaseIterable, Identifiable {
|
|
26
|
-
case open
|
|
27
|
-
case done
|
|
28
|
-
|
|
29
|
-
var id: String { rawValue }
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
enum TaskPriority: String, CaseIterable, Identifiable {
|
|
33
|
-
case low
|
|
34
|
-
case medium
|
|
35
|
-
case high
|
|
36
|
-
|
|
37
|
-
var id: String { rawValue }
|
|
38
|
-
|
|
39
|
-
var tint: Color {
|
|
40
|
-
switch self {
|
|
41
|
-
case .low: Color(red: 148 / 255, green: 163 / 255, blue: 184 / 255)
|
|
42
|
-
case .medium: Color(red: 37 / 255, green: 99 / 255, blue: 235 / 255)
|
|
43
|
-
case .high: Color(red: 217 / 255, green: 119 / 255, blue: 6 / 255)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
enum TaskFilter: String, CaseIterable, Identifiable {
|
|
49
|
-
case all
|
|
50
|
-
case open
|
|
51
|
-
case done
|
|
52
|
-
|
|
53
|
-
var id: String { rawValue }
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
enum AnalyticsPeriod: String, CaseIterable, Identifiable {
|
|
57
|
-
case week
|
|
58
|
-
case month
|
|
59
|
-
case quarter
|
|
60
|
-
|
|
61
|
-
var id: String { rawValue }
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
enum RecurrenceCadence: String, CaseIterable, Identifiable {
|
|
65
|
-
case daily
|
|
66
|
-
case weekly
|
|
67
|
-
case monthly
|
|
68
|
-
|
|
69
|
-
var id: String { rawValue }
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
enum Weekday: String, CaseIterable, Identifiable {
|
|
73
|
-
case mon
|
|
74
|
-
case tue
|
|
75
|
-
case wed
|
|
76
|
-
case thu
|
|
77
|
-
case fri
|
|
78
|
-
case sat
|
|
79
|
-
case sun
|
|
80
|
-
|
|
81
|
-
var id: String { rawValue }
|
|
82
|
-
|
|
83
|
-
var calendarIndex: Int {
|
|
84
|
-
switch self {
|
|
85
|
-
case .sun: 1
|
|
86
|
-
case .mon: 2
|
|
87
|
-
case .tue: 3
|
|
88
|
-
case .wed: 4
|
|
89
|
-
case .thu: 5
|
|
90
|
-
case .fri: 6
|
|
91
|
-
case .sat: 7
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
enum SummaryChannel: String, CaseIterable, Identifiable {
|
|
97
|
-
case push
|
|
98
|
-
case email
|
|
99
|
-
|
|
100
|
-
var id: String { rawValue }
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
struct Preferences: Equatable {
|
|
104
|
-
var locale: AppLocale
|
|
105
|
-
var theme: ThemePreference
|
|
106
|
-
var remindersEnabled: Bool
|
|
107
|
-
var dailySummaryEnabled: Bool
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
struct Task: Identifiable, Equatable {
|
|
111
|
-
let id: UUID
|
|
112
|
-
var title: String
|
|
113
|
-
var notes: String
|
|
114
|
-
var status: TaskStatus
|
|
115
|
-
var priority: TaskPriority
|
|
116
|
-
var dueDate: Date?
|
|
117
|
-
let createdAt: Date
|
|
118
|
-
var updatedAt: Date
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
struct RecurringRule: Identifiable, Equatable {
|
|
122
|
-
let id: UUID
|
|
123
|
-
var name: String
|
|
124
|
-
var cadence: RecurrenceCadence
|
|
125
|
-
var interval: Int
|
|
126
|
-
var weekday: Weekday?
|
|
127
|
-
var monthDay: Int?
|
|
128
|
-
var startDate: Date
|
|
129
|
-
var endDate: Date?
|
|
130
|
-
var remindAt: String?
|
|
131
|
-
var summaryChannel: SummaryChannel?
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
struct TrendPoint: Identifiable, Equatable {
|
|
135
|
-
let id = UUID()
|
|
136
|
-
let label: String
|
|
137
|
-
let completed: Int
|
|
138
|
-
let created: Int
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
struct AnalyticsSnapshot: Equatable {
|
|
142
|
-
let completedToday: Int
|
|
143
|
-
let openTasks: Int
|
|
144
|
-
let overdueTasks: Int
|
|
145
|
-
let completionRate: Int
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
struct ToastMessage: Identifiable, Equatable {
|
|
149
|
-
enum Level {
|
|
150
|
-
case success
|
|
151
|
-
case warning
|
|
152
|
-
case error
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
let id = UUID()
|
|
156
|
-
let level: Level
|
|
157
|
-
let text: String
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
struct TaskEditorDraft {
|
|
161
|
-
var title: String
|
|
162
|
-
var notes: String
|
|
163
|
-
var priority: TaskPriority
|
|
164
|
-
var dueDate: Date?
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
struct RecurringRuleDraft {
|
|
168
|
-
var name: String = ""
|
|
169
|
-
var confirmName: String = ""
|
|
170
|
-
var cadence: RecurrenceCadence?
|
|
171
|
-
var interval: String = "1"
|
|
172
|
-
var weekday: Weekday?
|
|
173
|
-
var monthDay: String = ""
|
|
174
|
-
var startDate: Date = .now
|
|
175
|
-
var hasEndDate: Bool = false
|
|
176
|
-
var endDate: Date = .now
|
|
177
|
-
var remindAt: String = ""
|
|
178
|
-
var enableSummary: Bool = false
|
|
179
|
-
var summaryChannel: SummaryChannel?
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
extension Task {
|
|
183
|
-
static func seed(referenceDate: Date = .now) -> [Task] {
|
|
184
|
-
let calendar = Calendar.current
|
|
185
|
-
return [
|
|
186
|
-
Task(
|
|
187
|
-
id: UUID(uuidString: "A6AC1D32-DF3E-4A87-9E11-6E9C2A52CF11")!,
|
|
188
|
-
title: "Prepare bilingual launch notes",
|
|
189
|
-
notes: "Document the web, iOS, and Android behavior differences before review.",
|
|
190
|
-
status: .open,
|
|
191
|
-
priority: .high,
|
|
192
|
-
dueDate: calendar.date(byAdding: .day, value: 2, to: referenceDate),
|
|
193
|
-
createdAt: calendar.date(byAdding: .day, value: -6, to: referenceDate)!,
|
|
194
|
-
updatedAt: calendar.date(byAdding: .day, value: -1, to: referenceDate)!
|
|
195
|
-
),
|
|
196
|
-
Task(
|
|
197
|
-
id: UUID(uuidString: "A6AC1D32-DF3E-4A87-9E11-6E9C2A52CF12")!,
|
|
198
|
-
title: "Review recurring-rule validation",
|
|
199
|
-
notes: "Confirm async uniqueness checks and cross-field constraints.",
|
|
200
|
-
status: .done,
|
|
201
|
-
priority: .medium,
|
|
202
|
-
dueDate: calendar.date(byAdding: .day, value: -1, to: referenceDate),
|
|
203
|
-
createdAt: calendar.date(byAdding: .day, value: -5, to: referenceDate)!,
|
|
204
|
-
updatedAt: referenceDate
|
|
205
|
-
),
|
|
206
|
-
Task(
|
|
207
|
-
id: UUID(uuidString: "A6AC1D32-DF3E-4A87-9E11-6E9C2A52CF13")!,
|
|
208
|
-
title: "Polish analytics empty states",
|
|
209
|
-
notes: "Ensure chart and overdue list degrade gracefully on zero-data snapshots.",
|
|
210
|
-
status: .open,
|
|
211
|
-
priority: .medium,
|
|
212
|
-
dueDate: calendar.date(byAdding: .day, value: 5, to: referenceDate),
|
|
213
|
-
createdAt: calendar.date(byAdding: .day, value: -4, to: referenceDate)!,
|
|
214
|
-
updatedAt: calendar.date(byAdding: .day, value: -2, to: referenceDate)!
|
|
215
|
-
),
|
|
216
|
-
Task(
|
|
217
|
-
id: UUID(uuidString: "A6AC1D32-DF3E-4A87-9E11-6E9C2A52CF14")!,
|
|
218
|
-
title: "Regenerate drift snapshots",
|
|
219
|
-
notes: "Refresh ios, android, and web state after spec edits.",
|
|
220
|
-
status: .open,
|
|
221
|
-
priority: .low,
|
|
222
|
-
dueDate: calendar.date(byAdding: .day, value: -3, to: referenceDate),
|
|
223
|
-
createdAt: calendar.date(byAdding: .day, value: -3, to: referenceDate)!,
|
|
224
|
-
updatedAt: calendar.date(byAdding: .day, value: -3, to: referenceDate)!
|
|
225
|
-
),
|
|
226
|
-
Task(
|
|
227
|
-
id: UUID(uuidString: "A6AC1D32-DF3E-4A87-9E11-6E9C2A52CF15")!,
|
|
228
|
-
title: "Prototype schedule preview contract",
|
|
229
|
-
notes: "Use derived occurrences to prove custom-contract generation.",
|
|
230
|
-
status: .done,
|
|
231
|
-
priority: .high,
|
|
232
|
-
dueDate: calendar.date(byAdding: .day, value: 1, to: referenceDate),
|
|
233
|
-
createdAt: calendar.date(byAdding: .day, value: -8, to: referenceDate)!,
|
|
234
|
-
updatedAt: calendar.date(byAdding: .day, value: -1, to: referenceDate)!
|
|
235
|
-
)
|
|
236
|
-
]
|
|
237
|
-
}
|
|
238
|
-
}
|
package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/AnalyticsView.swift
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import SwiftUI
|
|
2
|
-
|
|
3
|
-
struct AnalyticsView: View {
|
|
4
|
-
@ObservedObject var model: AppModel
|
|
5
|
-
@State private var period: AnalyticsPeriod = .week
|
|
6
|
-
|
|
7
|
-
private let grid = [
|
|
8
|
-
GridItem(.flexible(), spacing: 12),
|
|
9
|
-
GridItem(.flexible(), spacing: 12)
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
var body: some View {
|
|
13
|
-
let snapshot = model.analyticsSnapshot()
|
|
14
|
-
let points = model.trendSeries(period: period)
|
|
15
|
-
let overdue = model.overdueTasks()
|
|
16
|
-
|
|
17
|
-
ScrollView {
|
|
18
|
-
VStack(alignment: .leading, spacing: 18) {
|
|
19
|
-
VStack(alignment: .leading, spacing: 6) {
|
|
20
|
-
Text(model.string("analytics.title"))
|
|
21
|
-
.font(.largeTitle.weight(.bold))
|
|
22
|
-
Text(model.string("analytics.subtitle"))
|
|
23
|
-
.foregroundStyle(.secondary)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
Picker("Period", selection: $period) {
|
|
27
|
-
ForEach(AnalyticsPeriod.allCases) { period in
|
|
28
|
-
Text(model.string("analytics.period_\(period.rawValue)")).tag(period)
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
.pickerStyle(.segmented)
|
|
32
|
-
|
|
33
|
-
LazyVGrid(columns: grid, spacing: 12) {
|
|
34
|
-
statCard(model.string("analytics.completed_today"), value: "\(snapshot.completedToday)")
|
|
35
|
-
statCard(model.string("analytics.open_tasks"), value: "\(snapshot.openTasks)")
|
|
36
|
-
statCard(model.string("analytics.overdue_tasks"), value: "\(snapshot.overdueTasks)")
|
|
37
|
-
statCard(model.string("analytics.completion_rate"), value: "\(snapshot.completionRate)%")
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
TrendChartView(
|
|
41
|
-
title: model.string("analytics.title"),
|
|
42
|
-
subtitle: model.string("analytics.trend_subtitle"),
|
|
43
|
-
emptyMessage: model.string("analytics.empty_trend"),
|
|
44
|
-
legendCompleted: model.string("analytics.legend_completed"),
|
|
45
|
-
legendCreated: model.string("analytics.legend_created"),
|
|
46
|
-
points: points
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
VStack(alignment: .leading, spacing: 14) {
|
|
50
|
-
Text(model.string("analytics.overdue_section"))
|
|
51
|
-
.font(.title3.weight(.semibold))
|
|
52
|
-
Text(model.string("analytics.overdue_subtitle"))
|
|
53
|
-
.foregroundStyle(.secondary)
|
|
54
|
-
|
|
55
|
-
if overdue.isEmpty {
|
|
56
|
-
Text(model.string("analytics.empty_overdue_body"))
|
|
57
|
-
.foregroundStyle(.secondary)
|
|
58
|
-
} else {
|
|
59
|
-
ForEach(overdue) { task in
|
|
60
|
-
HStack {
|
|
61
|
-
VStack(alignment: .leading, spacing: 4) {
|
|
62
|
-
Text(task.title)
|
|
63
|
-
.font(.headline)
|
|
64
|
-
Text(model.label(for: task.priority))
|
|
65
|
-
.foregroundStyle(.secondary)
|
|
66
|
-
}
|
|
67
|
-
Spacer()
|
|
68
|
-
Text(model.formatDate(task.dueDate))
|
|
69
|
-
.font(.subheadline.weight(.semibold))
|
|
70
|
-
}
|
|
71
|
-
.padding(.vertical, 10)
|
|
72
|
-
Divider()
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
.orbitCard()
|
|
77
|
-
}
|
|
78
|
-
.padding()
|
|
79
|
-
}
|
|
80
|
-
.navigationTitle(model.string("nav.analytics"))
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private func statCard(_ title: String, value: String) -> some View {
|
|
84
|
-
VStack(alignment: .leading, spacing: 10) {
|
|
85
|
-
Text(title)
|
|
86
|
-
.font(.caption.weight(.semibold))
|
|
87
|
-
.foregroundStyle(.secondary)
|
|
88
|
-
Text(value)
|
|
89
|
-
.font(.title.weight(.bold))
|
|
90
|
-
}
|
|
91
|
-
.frame(maxWidth: .infinity, alignment: .leading)
|
|
92
|
-
.orbitCard()
|
|
93
|
-
}
|
|
94
|
-
}
|
package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/SettingsView.swift
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import SwiftUI
|
|
2
|
-
|
|
3
|
-
struct SettingsView: View {
|
|
4
|
-
@ObservedObject var model: AppModel
|
|
5
|
-
@State private var draft = Preferences(locale: .en, theme: .light, remindersEnabled: true, dailySummaryEnabled: false)
|
|
6
|
-
@State private var showRecurringSheet = false
|
|
7
|
-
|
|
8
|
-
var body: some View {
|
|
9
|
-
ScrollView {
|
|
10
|
-
VStack(alignment: .leading, spacing: 18) {
|
|
11
|
-
VStack(alignment: .leading, spacing: 6) {
|
|
12
|
-
Text(model.string("settings.title"))
|
|
13
|
-
.font(.largeTitle.weight(.bold))
|
|
14
|
-
Text(model.string("settings.subtitle"))
|
|
15
|
-
.foregroundStyle(.secondary)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
VStack(spacing: 14) {
|
|
19
|
-
Picker(model.string("settings.language"), selection: $draft.locale) {
|
|
20
|
-
Text(model.string("settings.language_en")).tag(AppLocale.en)
|
|
21
|
-
Text(model.string("settings.language_ru")).tag(AppLocale.ru)
|
|
22
|
-
}
|
|
23
|
-
.pickerStyle(.segmented)
|
|
24
|
-
|
|
25
|
-
Picker(model.string("settings.theme"), selection: $draft.theme) {
|
|
26
|
-
Text(model.string("settings.theme_light")).tag(ThemePreference.light)
|
|
27
|
-
Text(model.string("settings.theme_dark")).tag(ThemePreference.dark)
|
|
28
|
-
}
|
|
29
|
-
.pickerStyle(.segmented)
|
|
30
|
-
|
|
31
|
-
Toggle(model.string("settings.reminders"), isOn: $draft.remindersEnabled)
|
|
32
|
-
Toggle(model.string("settings.daily_summary"), isOn: $draft.dailySummaryEnabled)
|
|
33
|
-
|
|
34
|
-
Button(model.string("settings.save")) {
|
|
35
|
-
model.savePreferences(draft)
|
|
36
|
-
}
|
|
37
|
-
.buttonStyle(OrbitPrimaryButtonStyle())
|
|
38
|
-
.frame(maxWidth: .infinity, alignment: .leading)
|
|
39
|
-
}
|
|
40
|
-
.orbitCard()
|
|
41
|
-
|
|
42
|
-
VStack(alignment: .leading, spacing: 14) {
|
|
43
|
-
Text(model.string("settings.automation_title"))
|
|
44
|
-
.font(.title3.weight(.semibold))
|
|
45
|
-
Text(model.string("settings.automation_subtitle"))
|
|
46
|
-
.foregroundStyle(.secondary)
|
|
47
|
-
|
|
48
|
-
Button(model.string("settings.automation_create_rule")) {
|
|
49
|
-
showRecurringSheet = true
|
|
50
|
-
}
|
|
51
|
-
.buttonStyle(OrbitPrimaryButtonStyle())
|
|
52
|
-
|
|
53
|
-
if !model.rules.isEmpty {
|
|
54
|
-
ForEach(model.rules) { rule in
|
|
55
|
-
VStack(alignment: .leading, spacing: 6) {
|
|
56
|
-
Text(rule.name)
|
|
57
|
-
.font(.headline)
|
|
58
|
-
Text(model.describe(rule: rule))
|
|
59
|
-
.foregroundStyle(.secondary)
|
|
60
|
-
}
|
|
61
|
-
.frame(maxWidth: .infinity, alignment: .leading)
|
|
62
|
-
.padding(.vertical, 8)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
.orbitCard()
|
|
67
|
-
}
|
|
68
|
-
.padding()
|
|
69
|
-
}
|
|
70
|
-
.navigationTitle(model.string("nav.settings"))
|
|
71
|
-
.onAppear { draft = model.preferences }
|
|
72
|
-
.sheet(isPresented: $showRecurringSheet) {
|
|
73
|
-
RecurringRuleSheet(model: model)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|