openuispec 0.1.44 → 0.1.46
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 +79 -55
- package/cli/init.ts +14 -3
- package/examples/social-app/.mcp.json +10 -0
- package/examples/social-app/AGENTS.md +105 -0
- package/examples/social-app/CLAUDE.md +105 -0
- package/examples/social-app/README.md +19 -0
- package/examples/social-app/backend/.gitkeep +1 -0
- package/examples/social-app/generated/android/social-app/app/build.gradle.kts +92 -0
- package/examples/social-app/generated/android/social-app/app/src/main/AndroidManifest.xml +26 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/AppContainer.kt +20 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/MainActivity.kt +35 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/SocialAppApplication.kt +13 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/MockData.kt +98 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/AppPreferences.kt +19 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/DataStorePreferencesRepository.kt +68 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/PreferencesRepository.kt +15 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/model/Models.kt +34 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/MainShell.kt +390 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/components/Components.kt +234 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/components/ContractPrimitives.kt +641 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/navigation/RootComponent.kt +113 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/ChatDetailScreen.kt +212 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/CreatePostScreen.kt +113 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/DiscoverScreen.kt +137 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/EditProfileScreen.kt +180 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/HomeFeedScreen.kt +157 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/MessagesInboxScreen.kt +85 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/NotificationsScreen.kt +74 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/PostDetailScreen.kt +293 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/ProfileSelfScreen.kt +116 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SearchResultsScreen.kt +161 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SettingsScreen.kt +162 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SettingsStore.kt +95 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/UserProfileScreen.kt +123 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Color.kt +33 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Shape.kt +41 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Spacing.kt +20 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Theme.kt +82 -0
- package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Type.kt +60 -0
- package/examples/social-app/generated/android/social-app/app/src/main/res/drawable/ic_launcher_foreground.xml +9 -0
- package/examples/social-app/generated/android/social-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
- package/examples/social-app/generated/android/social-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
- package/examples/social-app/generated/android/social-app/app/src/main/res/values/strings.xml +91 -0
- package/examples/social-app/generated/android/social-app/app/src/main/res/values/themes.xml +10 -0
- package/examples/social-app/generated/android/social-app/app/src/main/res/values-ru/strings.xml +79 -0
- package/examples/social-app/generated/android/social-app/app/src/main/res/values-uz/strings.xml +79 -0
- package/examples/social-app/generated/android/social-app/app/src/main/xml/AndroidManifest.xml +23 -0
- package/examples/social-app/generated/android/social-app/build.gradle.kts +6 -0
- package/examples/social-app/generated/android/social-app/gradle/libs.versions.toml +48 -0
- package/examples/social-app/generated/android/social-app/gradle/wrapper/gradle-wrapper.properties +8 -0
- package/examples/social-app/generated/android/social-app/gradle.properties +11 -0
- package/examples/social-app/generated/android/social-app/gradlew +25 -0
- package/examples/social-app/generated/android/social-app/settings.gradle.kts +23 -0
- package/examples/social-app/generated/web/social-app/index.html +12 -0
- package/examples/social-app/generated/web/social-app/package-lock.json +2517 -0
- package/examples/social-app/generated/web/social-app/package.json +27 -0
- package/examples/social-app/generated/web/social-app/src/app/App.tsx +58 -0
- package/examples/social-app/generated/web/social-app/src/components/Shell.tsx +247 -0
- package/examples/social-app/generated/web/social-app/src/components/cards.tsx +317 -0
- package/examples/social-app/generated/web/social-app/src/components/ui.tsx +328 -0
- package/examples/social-app/generated/web/social-app/src/flows/CreatePostFlow.tsx +86 -0
- package/examples/social-app/generated/web/social-app/src/i18n.tsx +59 -0
- package/examples/social-app/generated/web/social-app/src/lib/icons.tsx +85 -0
- package/examples/social-app/generated/web/social-app/src/lib/tokens.ts +70 -0
- package/examples/social-app/generated/web/social-app/src/lib/utils.ts +97 -0
- package/examples/social-app/generated/web/social-app/src/locales/en.json +67 -0
- package/examples/social-app/generated/web/social-app/src/locales/ru.json +67 -0
- package/examples/social-app/generated/web/social-app/src/locales/uz.json +67 -0
- package/examples/social-app/generated/web/social-app/src/main.tsx +16 -0
- package/examples/social-app/generated/web/social-app/src/screens/ChatDetailScreen.tsx +90 -0
- package/examples/social-app/generated/web/social-app/src/screens/DiscoverScreen.tsx +86 -0
- package/examples/social-app/generated/web/social-app/src/screens/EditProfileScreen.tsx +57 -0
- package/examples/social-app/generated/web/social-app/src/screens/HomeFeedScreen.tsx +113 -0
- package/examples/social-app/generated/web/social-app/src/screens/MessagesInboxScreen.tsx +52 -0
- package/examples/social-app/generated/web/social-app/src/screens/NotificationsScreen.tsx +41 -0
- package/examples/social-app/generated/web/social-app/src/screens/PostDetailScreen.tsx +115 -0
- package/examples/social-app/generated/web/social-app/src/screens/ProfileSelfScreen.tsx +57 -0
- package/examples/social-app/generated/web/social-app/src/screens/ProfileUserScreen.tsx +76 -0
- package/examples/social-app/generated/web/social-app/src/screens/SearchResultsScreen.tsx +96 -0
- package/examples/social-app/generated/web/social-app/src/screens/SettingsScreen.tsx +77 -0
- package/examples/social-app/generated/web/social-app/src/state/store.ts +592 -0
- package/examples/social-app/generated/web/social-app/src/styles.css +124 -0
- package/examples/social-app/generated/web/social-app/src/vite-env.d.ts +1 -0
- package/examples/social-app/generated/web/social-app/tsconfig.json +22 -0
- package/examples/social-app/generated/web/social-app/tsconfig.node.json +13 -0
- package/examples/social-app/generated/web/social-app/tsconfig.node.tsbuildinfo +1 -0
- package/examples/social-app/generated/web/social-app/tsconfig.tsbuildinfo +1 -0
- package/examples/social-app/generated/web/social-app/vite.config.d.ts +2 -0
- package/examples/social-app/generated/web/social-app/vite.config.js +6 -0
- package/examples/social-app/generated/web/social-app/vite.config.ts +7 -0
- package/examples/social-app/openuispec/README.md +56 -0
- package/examples/social-app/openuispec/contracts/.gitkeep +0 -0
- package/examples/social-app/openuispec/contracts/action_trigger.yaml +73 -0
- package/examples/social-app/openuispec/contracts/collection.yaml +43 -0
- package/examples/social-app/openuispec/contracts/data_display.yaml +47 -0
- package/examples/social-app/openuispec/contracts/feedback.yaml +49 -0
- package/examples/social-app/openuispec/contracts/input_field.yaml +41 -0
- package/examples/social-app/openuispec/contracts/nav_container.yaml +34 -0
- package/examples/social-app/openuispec/contracts/surface.yaml +41 -0
- package/examples/social-app/openuispec/flows/.gitkeep +0 -0
- package/examples/social-app/openuispec/flows/create_post.yaml +66 -0
- package/examples/social-app/openuispec/locales/.gitkeep +0 -0
- package/examples/social-app/openuispec/locales/en.json +67 -0
- package/examples/social-app/openuispec/locales/ru.json +67 -0
- package/examples/social-app/openuispec/locales/uz.json +67 -0
- package/examples/social-app/openuispec/openuispec.yaml +214 -0
- package/examples/social-app/openuispec/platform/.gitkeep +0 -0
- package/examples/social-app/openuispec/platform/android.yaml +30 -0
- package/examples/social-app/openuispec/platform/ios.yaml +19 -0
- package/examples/social-app/openuispec/platform/web.yaml +23 -0
- package/examples/social-app/openuispec/screens/.gitkeep +0 -0
- package/examples/social-app/openuispec/screens/chat_detail.yaml +53 -0
- package/examples/social-app/openuispec/screens/discover.yaml +78 -0
- package/examples/social-app/openuispec/screens/edit_profile.yaml +78 -0
- package/examples/social-app/openuispec/screens/home_feed.yaml +123 -0
- package/examples/social-app/openuispec/screens/messages_inbox.yaml +43 -0
- package/examples/social-app/openuispec/screens/notifications.yaml +29 -0
- package/examples/social-app/openuispec/screens/post_detail.yaml +86 -0
- package/examples/social-app/openuispec/screens/profile_self.yaml +53 -0
- package/examples/social-app/openuispec/screens/profile_user.yaml +60 -0
- package/examples/social-app/openuispec/screens/search_results.yaml +62 -0
- package/examples/social-app/openuispec/screens/settings.yaml +94 -0
- package/examples/social-app/openuispec/tokens/.gitkeep +0 -0
- package/examples/social-app/openuispec/tokens/color.yaml +76 -0
- package/examples/social-app/openuispec/tokens/elevation.yaml +31 -0
- package/examples/social-app/openuispec/tokens/icons.yaml +147 -0
- package/examples/social-app/openuispec/tokens/layout.yaml +37 -0
- package/examples/social-app/openuispec/tokens/motion.yaml +28 -0
- package/examples/social-app/openuispec/tokens/spacing.yaml +19 -0
- package/examples/social-app/openuispec/tokens/themes.yaml +31 -0
- package/examples/social-app/openuispec/tokens/typography.yaml +50 -0
- package/examples/social-app/package.json +12 -0
- package/mcp-server/index.ts +69 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,25 +52,92 @@ cd your-project
|
|
|
52
52
|
openuispec init
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
This scaffolds a spec directory, starter tokens,
|
|
56
|
-
Use `openuispec init --no-configure-targets` if you want to scaffold first and choose target stacks later.
|
|
55
|
+
This scaffolds a spec directory, starter tokens, and **configures the MCP server** for your AI coding agent (Claude Code, VS Code/Copilot, Codex). Use `openuispec init --no-configure-targets` to scaffold first and choose target stacks later.
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
## AI integration (MCP)
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
OpenUISpec is designed to be used by AI coding agents. The package includes an **MCP server** that exposes tools AI assistants call automatically during UI work — no manual prompting needed.
|
|
60
|
+
|
|
61
|
+
### How it works
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
openuispec init → configures MCP for your agent → AI calls tools automatically
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
When you ask your AI to "add a settings page" or "update the home feed," the MCP server:
|
|
68
|
+
|
|
69
|
+
1. **Schema reference** — `openuispec_spec_types` and `openuispec_spec_schema` give the AI the exact format for any spec file it needs to create or edit
|
|
70
|
+
2. **Before generation** — `openuispec_prepare` gives the AI your spec context, platform config, and constraints
|
|
71
|
+
3. **During generation** — `openuispec_read_specs` feeds the AI the actual spec file contents as the authoritative source
|
|
72
|
+
4. **After generation** — `openuispec_check` returns a concrete audit checklist derived from your spec (every contract `must_handle` item, every screen section, every locale key) and the AI verifies its code matches
|
|
73
|
+
|
|
74
|
+
This replaces the old approach of writing instructions in CLAUDE.md and hoping the AI follows them. MCP tools are called reliably because they're part of the AI's tool-calling loop, not a text instruction it can skip.
|
|
75
|
+
|
|
76
|
+
### Setup
|
|
77
|
+
|
|
78
|
+
`openuispec init` and `openuispec update-rules` automatically configure MCP for all supported agents:
|
|
79
|
+
|
|
80
|
+
| Agent | Config file | Created automatically |
|
|
81
|
+
|-------|------------|----------------------|
|
|
82
|
+
| **Claude Code** | `.mcp.json` | Always |
|
|
83
|
+
| **Codex** | `.codex/config.toml` | Always |
|
|
84
|
+
| **VS Code / Copilot** | `.vscode/mcp.json` | If `.vscode/` exists |
|
|
85
|
+
| **Gemini CLI** | `.gemini/settings.json` | If `.gemini/` exists |
|
|
86
|
+
|
|
87
|
+
Manual setup (if needed):
|
|
88
|
+
|
|
89
|
+
**Claude Code** (`.mcp.json`), **VS Code / Copilot** (`.vscode/mcp.json`), **Gemini CLI** (`.gemini/settings.json`):
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"mcpServers": {
|
|
93
|
+
"openuispec": {
|
|
94
|
+
"command": "openuispec",
|
|
95
|
+
"args": ["mcp"]
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Codex** (`.codex/config.toml`):
|
|
102
|
+
```toml
|
|
103
|
+
[mcp_servers.openuispec]
|
|
104
|
+
command = "openuispec"
|
|
105
|
+
args = ["mcp"]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Or run directly: `openuispec mcp`
|
|
109
|
+
|
|
110
|
+
### Tools
|
|
61
111
|
|
|
62
|
-
|
|
112
|
+
| Tool | When | What it does |
|
|
113
|
+
|------|------|-------------|
|
|
114
|
+
| `openuispec_spec_types` | Before creating spec files | Lists all available spec types with descriptions — discover what kinds of spec files exist |
|
|
115
|
+
| `openuispec_spec_schema` | Before creating/editing spec files | Returns the full JSON schema for a specific spec type — exact structure, required fields, allowed values |
|
|
116
|
+
| `openuispec_prepare` | Before UI code generation | Returns spec context, platform config, generation constraints |
|
|
117
|
+
| `openuispec_read_specs` | Before and after generation | Loads spec file contents — the authoritative source for tokens, screens, contracts |
|
|
118
|
+
| `openuispec_check` | After generation | Schema validation + concrete audit checklist from your spec |
|
|
119
|
+
| `openuispec_validate` | After spec edits | Schema-only validation, optionally filtered by group |
|
|
120
|
+
| `openuispec_drift` | Before updates | Detect spec drift since last snapshot, with semantic explanation |
|
|
121
|
+
| `openuispec_status` | Anytime | Cross-target summary: baselines, drift, next steps |
|
|
122
|
+
|
|
123
|
+
The server includes **protocol-level instructions** that trigger on UI-related requests independently of CLAUDE.md rules — so even if CLAUDE.md is buried under other project rules, the MCP enforcement still works.
|
|
124
|
+
|
|
125
|
+
## Using without MCP
|
|
126
|
+
|
|
127
|
+
You can also use OpenUISpec with any AI by providing context manually:
|
|
128
|
+
|
|
129
|
+
> Generate a native iOS app from this OpenUISpec. Follow all contract state machines, apply token ranges for iOS, and implement navigation flows as defined. Use `platform/ios.yaml` for SwiftUI-specific overrides.
|
|
63
130
|
|
|
64
131
|
For platform generation, treat these as hard output constraints:
|
|
65
132
|
|
|
66
|
-
- Generate a valid native project
|
|
67
|
-
- Do not ship unresolved resource identifiers
|
|
68
|
-
-
|
|
133
|
+
- Generate a valid native project that bundles every required runtime resource
|
|
134
|
+
- Do not ship unresolved resource identifiers (raw locale keys, token refs, placeholder paths)
|
|
135
|
+
- Define behavior for every supported size class and form factor
|
|
69
136
|
|
|
70
|
-
See the examples for
|
|
137
|
+
See the examples for reference:
|
|
71
138
|
|
|
72
|
-
- [TaskFlow](./examples/taskflow/openuispec/)
|
|
73
|
-
- [Todo Orbit](./examples/todo-orbit/openuispec/)
|
|
139
|
+
- [TaskFlow](./examples/taskflow/openuispec/) — compact reference spec covering all 7 contract families
|
|
140
|
+
- [Todo Orbit](./examples/todo-orbit/openuispec/) — bilingual task app with localization, custom contracts, and generated native/web targets
|
|
74
141
|
|
|
75
142
|
## Repository structure
|
|
76
143
|
|
|
@@ -117,7 +184,7 @@ openuispec/
|
|
|
117
184
|
│ ├── index.ts # Entry point
|
|
118
185
|
│ └── init.ts # Project scaffolding + AI rules
|
|
119
186
|
├── mcp-server/ # MCP server (openuispec-mcp)
|
|
120
|
-
│ └── index.ts # Stdio transport,
|
|
187
|
+
│ └── index.ts # Stdio transport, 8 tools
|
|
121
188
|
├── check/ # Composite validation command
|
|
122
189
|
│ └── index.ts # Schema + semantic + readiness
|
|
123
190
|
├── drift/ # Drift detection (spec change tracking)
|
|
@@ -245,49 +312,6 @@ to see which targets are already up to date and which ones still need to catch u
|
|
|
245
312
|
|
|
246
313
|
`drift --snapshot` is bookkeeping. It does not prove that the target code matches the spec, and it will not create a missing target output directory for you.
|
|
247
314
|
|
|
248
|
-
## MCP server
|
|
249
|
-
|
|
250
|
-
OpenUISpec includes an MCP (Model Context Protocol) server that exposes CLI commands as tools for AI assistants. This is the recommended way to integrate with Claude Code and other MCP-compatible clients — tools are called more reliably than CLAUDE.md instructions.
|
|
251
|
-
|
|
252
|
-
### Setup
|
|
253
|
-
|
|
254
|
-
`openuispec init` automatically configures the MCP server for your coding agent. For existing projects, run `openuispec update-rules` or add the config manually:
|
|
255
|
-
|
|
256
|
-
**Claude Code** (`.mcp.json`), **VS Code / Copilot** (`.vscode/mcp.json`):
|
|
257
|
-
```json
|
|
258
|
-
{
|
|
259
|
-
"mcpServers": {
|
|
260
|
-
"openuispec": {
|
|
261
|
-
"command": "openuispec",
|
|
262
|
-
"args": ["mcp"]
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
**Codex** (`.codex/config.toml`):
|
|
269
|
-
```toml
|
|
270
|
-
[mcp_servers.openuispec]
|
|
271
|
-
command = "openuispec"
|
|
272
|
-
args = ["mcp"]
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
Or run directly: `openuispec mcp`
|
|
276
|
-
|
|
277
|
-
Set `OPENUISPEC_PROJECT_DIR` to override the working directory.
|
|
278
|
-
|
|
279
|
-
### Tools
|
|
280
|
-
|
|
281
|
-
| Tool | Description |
|
|
282
|
-
|------|-------------|
|
|
283
|
-
| `openuispec_prepare` | Build AI-ready work bundle for a target. **Call before any UI code generation.** |
|
|
284
|
-
| `openuispec_check` | Schema validation + semantic lint + prepare readiness. Call after spec edits. |
|
|
285
|
-
| `openuispec_status` | Cross-target summary: baselines, drift, next steps. |
|
|
286
|
-
| `openuispec_validate` | Schema-only validation, optionally filtered by group. |
|
|
287
|
-
| `openuispec_drift` | Detect spec drift since last snapshot, with optional semantic explanation. |
|
|
288
|
-
|
|
289
|
-
All tools return structured JSON. The server includes protocol-level instructions that tell AI assistants to call `openuispec_prepare` before any UI work — this works independently of CLAUDE.md rules.
|
|
290
|
-
|
|
291
315
|
## Spec at a glance
|
|
292
316
|
|
|
293
317
|
| Section | What it defines |
|
package/cli/init.ts
CHANGED
|
@@ -268,11 +268,14 @@ When the openuispec MCP server is configured, AI assistants should use these too
|
|
|
268
268
|
|
|
269
269
|
| Tool | When to use |
|
|
270
270
|
|------|-------------|
|
|
271
|
+
| \`openuispec_spec_types\` | Discover available spec types and their descriptions. |
|
|
272
|
+
| \`openuispec_spec_schema\` | Get the full JSON schema for a specific spec type — exact structure, required fields, allowed values. |
|
|
271
273
|
| \`openuispec_prepare\` | **Before any UI code generation.** Returns spec context, platform config, and constraints. |
|
|
274
|
+
| \`openuispec_read_specs\` | Load spec file contents — the authoritative source for tokens, screens, contracts. |
|
|
272
275
|
| \`openuispec_check\` | After editing spec files. Validates schema + semantics + readiness. |
|
|
273
|
-
| \`openuispec_status\` | To understand cross-target state (baselines, drift, next steps). |
|
|
274
276
|
| \`openuispec_validate\` | Schema-only validation, optionally by group. |
|
|
275
277
|
| \`openuispec_drift\` | Detect spec changes since last snapshot. |
|
|
278
|
+
| \`openuispec_status\` | To understand cross-target state (baselines, drift, next steps). |
|
|
276
279
|
|
|
277
280
|
## CLI commands
|
|
278
281
|
|
|
@@ -337,6 +340,11 @@ Call these MCP tools directly. They return structured JSON with everything you n
|
|
|
337
340
|
- Navigation targets match flow definitions
|
|
338
341
|
8. Report any real gaps found and fix them before finishing.
|
|
339
342
|
|
|
343
|
+
**Creating new spec files:**
|
|
344
|
+
- Call \`openuispec_spec_types\` to discover available spec types.
|
|
345
|
+
- Call \`openuispec_spec_schema\` with the specific type to get the full JSON schema.
|
|
346
|
+
- Write the spec file following the schema exactly.
|
|
347
|
+
|
|
340
348
|
**Other tools:**
|
|
341
349
|
- \`openuispec_status\` — cross-target summary, good starting point
|
|
342
350
|
- \`openuispec_drift\` with \`explain: true\` — property-level spec changes
|
|
@@ -493,12 +501,14 @@ const EXPECTED_MCP_CONFIG = {
|
|
|
493
501
|
* MCP config files by agent:
|
|
494
502
|
* .mcp.json — Claude Code (project scope)
|
|
495
503
|
* .vscode/mcp.json — VS Code / Copilot Chat
|
|
504
|
+
* .gemini/settings.json — Gemini CLI (if .gemini/ exists)
|
|
496
505
|
*
|
|
497
506
|
* All use the same { mcpServers: { openuispec: { command, args } } } shape.
|
|
498
507
|
*/
|
|
499
508
|
const JSON_MCP_PATHS = [
|
|
500
509
|
".mcp.json",
|
|
501
510
|
join(".vscode", "mcp.json"),
|
|
511
|
+
join(".gemini", "settings.json"),
|
|
502
512
|
];
|
|
503
513
|
|
|
504
514
|
/** Codex uses TOML: .codex/config.toml */
|
|
@@ -534,8 +544,9 @@ function configureMcp(cwd: string, showRestart: boolean, quiet: boolean = false)
|
|
|
534
544
|
for (const relPath of JSON_MCP_PATHS) {
|
|
535
545
|
const configPath = join(cwd, relPath);
|
|
536
546
|
|
|
537
|
-
//
|
|
538
|
-
|
|
547
|
+
// Optional dirs: only write config if the parent directory already exists
|
|
548
|
+
const optionalParent = [".vscode", ".gemini"].find((d) => relPath.startsWith(d));
|
|
549
|
+
if (optionalParent && !existsSync(join(cwd, optionalParent))) continue;
|
|
539
550
|
|
|
540
551
|
try {
|
|
541
552
|
let config: Record<string, any> = {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<!-- openuispec-rules-start -->
|
|
2
|
+
<!-- openuispec-rules-version: 0.1.45 -->
|
|
3
|
+
# OpenUISpec — AI Assistant Rules
|
|
4
|
+
# ================================
|
|
5
|
+
# This project uses OpenUISpec to define UI as a semantic spec.
|
|
6
|
+
# Spec files are the single source of truth for all UI across platforms.
|
|
7
|
+
# Targets: "ios", "android", "web"
|
|
8
|
+
|
|
9
|
+
## MANDATORY — UI work requires OpenUISpec tools
|
|
10
|
+
|
|
11
|
+
When the user's request involves UI — screens, navigation, layout, tokens, flows, localization,
|
|
12
|
+
or any visual/structural change — you MUST use the OpenUISpec tools before writing any code.
|
|
13
|
+
|
|
14
|
+
### MCP Tools (use these when available)
|
|
15
|
+
|
|
16
|
+
Call these MCP tools directly. They return structured JSON with everything you need.
|
|
17
|
+
|
|
18
|
+
**Pre-generation:**
|
|
19
|
+
1. Call `openuispec_prepare` with the target platform — returns spec context, platform config, constraints.
|
|
20
|
+
2. Call `openuispec_read_specs` to load spec file contents. Use these as the AUTHORITATIVE source.
|
|
21
|
+
3. If spec changes are needed, update spec files FIRST, then call `openuispec_check`.
|
|
22
|
+
4. Generate or update the platform UI code based on the spec contents.
|
|
23
|
+
|
|
24
|
+
**Post-generation (EVERY TIME after writing UI code):**
|
|
25
|
+
5. Call `openuispec_check` to validate spec integrity.
|
|
26
|
+
6. Call `openuispec_read_specs` for the screens/contracts you just generated code for.
|
|
27
|
+
7. Audit your generated code against the spec. For each screen, verify:
|
|
28
|
+
- Every field/action in the spec has a corresponding UI element
|
|
29
|
+
- Token values (colors, spacing, radii) match exactly — no approximations
|
|
30
|
+
- Contract `must_handle` states are all implemented (loading, error, empty, etc.)
|
|
31
|
+
- Adaptive breakpoints match the spec's `size_classes`
|
|
32
|
+
- Locale keys match `$t:` references
|
|
33
|
+
- Navigation targets match flow definitions
|
|
34
|
+
8. Report any real gaps found and fix them before finishing.
|
|
35
|
+
|
|
36
|
+
**Creating new spec files:**
|
|
37
|
+
- Call `openuispec_spec_types` to discover available spec types.
|
|
38
|
+
- Call `openuispec_spec_schema` with the specific type to get the full JSON schema.
|
|
39
|
+
- Write the spec file following the schema exactly.
|
|
40
|
+
|
|
41
|
+
**Other tools:**
|
|
42
|
+
- `openuispec_status` — cross-target summary, good starting point
|
|
43
|
+
- `openuispec_drift` with `explain: true` — property-level spec changes
|
|
44
|
+
- `openuispec_validate` — schema-only validation by group
|
|
45
|
+
|
|
46
|
+
### CLI fallback (when MCP is not available)
|
|
47
|
+
|
|
48
|
+
If MCP tools are not available, use these CLI commands with `--json` flag:
|
|
49
|
+
- `openuispec prepare --target <t> --json` — build AI-ready work bundle
|
|
50
|
+
- `openuispec check --target <t> --json` — composite validation
|
|
51
|
+
- `openuispec status --json` — cross-target status
|
|
52
|
+
- `openuispec drift --target <t> --explain --json` — semantic drift
|
|
53
|
+
- `openuispec validate [group...] --json` — schema validation
|
|
54
|
+
|
|
55
|
+
### Other CLI commands
|
|
56
|
+
- `openuispec init` — scaffold a new spec project
|
|
57
|
+
- `openuispec drift --snapshot --target <t>` — snapshot current state (only after UI code is updated)
|
|
58
|
+
- `openuispec configure-target <t>` — configure target platform stack
|
|
59
|
+
- `openuispec update-rules` — update AI rules to match installed package version
|
|
60
|
+
|
|
61
|
+
## Spec format reference
|
|
62
|
+
|
|
63
|
+
The spec format, schemas, and generation rules are in the installed `openuispec` package.
|
|
64
|
+
You MUST read the reference files before creating or editing spec files — do NOT guess the format.
|
|
65
|
+
|
|
66
|
+
**Find the package:** `node_modules/openuispec/` or run `npm root -g` → `<prefix>/openuispec/`.
|
|
67
|
+
**Online fallback:** `https://openuispec.rsteam.uz/llms-full.txt`
|
|
68
|
+
|
|
69
|
+
**Reference files (read in order):**
|
|
70
|
+
1. `README.md` — schema tables, file format, root wrapper keys
|
|
71
|
+
2. `spec/openuispec-v0.1.md` — full specification
|
|
72
|
+
3. `examples/taskflow/openuispec/` — complete working example
|
|
73
|
+
4. `schema/` — JSON Schemas for every file type
|
|
74
|
+
|
|
75
|
+
## Spec location
|
|
76
|
+
- Spec root: `openuispec/` — read `openuispec/openuispec.yaml` first for actual paths.
|
|
77
|
+
- Default dirs: tokens/, screens/, flows/, contracts/, platform/, locales/
|
|
78
|
+
|
|
79
|
+
## When to start from spec vs platform code
|
|
80
|
+
|
|
81
|
+
**Spec-first** (use `openuispec_prepare` or `openuispec prepare`):
|
|
82
|
+
- Screen structure, navigation, fields, actions, validation, data binding changes
|
|
83
|
+
- Token, variant, contract, flow, or localization changes
|
|
84
|
+
- Changes affecting multiple platforms
|
|
85
|
+
- Requests in product/UI terms
|
|
86
|
+
|
|
87
|
+
**Platform-first** (skip spec tools):
|
|
88
|
+
- Platform-specific polish (iOS-only, Android-only, web-only)
|
|
89
|
+
- Local bug fixes that don't alter shared semantic behavior
|
|
90
|
+
|
|
91
|
+
## If spec directories are empty (first-time setup)
|
|
92
|
+
|
|
93
|
+
Read `spec/openuispec-v0.1.md` from the package first, then:
|
|
94
|
+
1. Scan codebase for UI screens → create `openuispec/screens/<name>.yaml` as `status: stub`
|
|
95
|
+
2. Extract tokens (colors, fonts, spacing) → `openuispec/tokens/`
|
|
96
|
+
3. Create contract extensions → `openuispec/contracts/`
|
|
97
|
+
4. Create locale files → `openuispec/locales/<locale>.json`
|
|
98
|
+
5. Fill in `data_model`, `api.endpoints` in `openuispec/openuispec.yaml`
|
|
99
|
+
|
|
100
|
+
## Rules
|
|
101
|
+
- Do not snapshot drift unless the UI code has also been updated.
|
|
102
|
+
- Do not modify generated UI without checking whether the spec must change first.
|
|
103
|
+
- Do not use `configure-target --defaults` as silent approval — ask the user to confirm.
|
|
104
|
+
- Always read spec format from the installed package, not from cached/memorized content.
|
|
105
|
+
<!-- openuispec-rules-end -->
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<!-- openuispec-rules-start -->
|
|
2
|
+
<!-- openuispec-rules-version: 0.1.45 -->
|
|
3
|
+
# OpenUISpec — AI Assistant Rules
|
|
4
|
+
# ================================
|
|
5
|
+
# This project uses OpenUISpec to define UI as a semantic spec.
|
|
6
|
+
# Spec files are the single source of truth for all UI across platforms.
|
|
7
|
+
# Targets: "ios", "android", "web"
|
|
8
|
+
|
|
9
|
+
## MANDATORY — UI work requires OpenUISpec tools
|
|
10
|
+
|
|
11
|
+
When the user's request involves UI — screens, navigation, layout, tokens, flows, localization,
|
|
12
|
+
or any visual/structural change — you MUST use the OpenUISpec tools before writing any code.
|
|
13
|
+
|
|
14
|
+
### MCP Tools (use these when available)
|
|
15
|
+
|
|
16
|
+
Call these MCP tools directly. They return structured JSON with everything you need.
|
|
17
|
+
|
|
18
|
+
**Pre-generation:**
|
|
19
|
+
1. Call `openuispec_prepare` with the target platform — returns spec context, platform config, constraints.
|
|
20
|
+
2. Call `openuispec_read_specs` to load spec file contents. Use these as the AUTHORITATIVE source.
|
|
21
|
+
3. If spec changes are needed, update spec files FIRST, then call `openuispec_check`.
|
|
22
|
+
4. Generate or update the platform UI code based on the spec contents.
|
|
23
|
+
|
|
24
|
+
**Post-generation (EVERY TIME after writing UI code):**
|
|
25
|
+
5. Call `openuispec_check` to validate spec integrity.
|
|
26
|
+
6. Call `openuispec_read_specs` for the screens/contracts you just generated code for.
|
|
27
|
+
7. Audit your generated code against the spec. For each screen, verify:
|
|
28
|
+
- Every field/action in the spec has a corresponding UI element
|
|
29
|
+
- Token values (colors, spacing, radii) match exactly — no approximations
|
|
30
|
+
- Contract `must_handle` states are all implemented (loading, error, empty, etc.)
|
|
31
|
+
- Adaptive breakpoints match the spec's `size_classes`
|
|
32
|
+
- Locale keys match `$t:` references
|
|
33
|
+
- Navigation targets match flow definitions
|
|
34
|
+
8. Report any real gaps found and fix them before finishing.
|
|
35
|
+
|
|
36
|
+
**Creating new spec files:**
|
|
37
|
+
- Call `openuispec_spec_types` to discover available spec types.
|
|
38
|
+
- Call `openuispec_spec_schema` with the specific type to get the full JSON schema.
|
|
39
|
+
- Write the spec file following the schema exactly.
|
|
40
|
+
|
|
41
|
+
**Other tools:**
|
|
42
|
+
- `openuispec_status` — cross-target summary, good starting point
|
|
43
|
+
- `openuispec_drift` with `explain: true` — property-level spec changes
|
|
44
|
+
- `openuispec_validate` — schema-only validation by group
|
|
45
|
+
|
|
46
|
+
### CLI fallback (when MCP is not available)
|
|
47
|
+
|
|
48
|
+
If MCP tools are not available, use these CLI commands with `--json` flag:
|
|
49
|
+
- `openuispec prepare --target <t> --json` — build AI-ready work bundle
|
|
50
|
+
- `openuispec check --target <t> --json` — composite validation
|
|
51
|
+
- `openuispec status --json` — cross-target status
|
|
52
|
+
- `openuispec drift --target <t> --explain --json` — semantic drift
|
|
53
|
+
- `openuispec validate [group...] --json` — schema validation
|
|
54
|
+
|
|
55
|
+
### Other CLI commands
|
|
56
|
+
- `openuispec init` — scaffold a new spec project
|
|
57
|
+
- `openuispec drift --snapshot --target <t>` — snapshot current state (only after UI code is updated)
|
|
58
|
+
- `openuispec configure-target <t>` — configure target platform stack
|
|
59
|
+
- `openuispec update-rules` — update AI rules to match installed package version
|
|
60
|
+
|
|
61
|
+
## Spec format reference
|
|
62
|
+
|
|
63
|
+
The spec format, schemas, and generation rules are in the installed `openuispec` package.
|
|
64
|
+
You MUST read the reference files before creating or editing spec files — do NOT guess the format.
|
|
65
|
+
|
|
66
|
+
**Find the package:** `node_modules/openuispec/` or run `npm root -g` → `<prefix>/openuispec/`.
|
|
67
|
+
**Online fallback:** `https://openuispec.rsteam.uz/llms-full.txt`
|
|
68
|
+
|
|
69
|
+
**Reference files (read in order):**
|
|
70
|
+
1. `README.md` — schema tables, file format, root wrapper keys
|
|
71
|
+
2. `spec/openuispec-v0.1.md` — full specification
|
|
72
|
+
3. `examples/taskflow/openuispec/` — complete working example
|
|
73
|
+
4. `schema/` — JSON Schemas for every file type
|
|
74
|
+
|
|
75
|
+
## Spec location
|
|
76
|
+
- Spec root: `openuispec/` — read `openuispec/openuispec.yaml` first for actual paths.
|
|
77
|
+
- Default dirs: tokens/, screens/, flows/, contracts/, platform/, locales/
|
|
78
|
+
|
|
79
|
+
## When to start from spec vs platform code
|
|
80
|
+
|
|
81
|
+
**Spec-first** (use `openuispec_prepare` or `openuispec prepare`):
|
|
82
|
+
- Screen structure, navigation, fields, actions, validation, data binding changes
|
|
83
|
+
- Token, variant, contract, flow, or localization changes
|
|
84
|
+
- Changes affecting multiple platforms
|
|
85
|
+
- Requests in product/UI terms
|
|
86
|
+
|
|
87
|
+
**Platform-first** (skip spec tools):
|
|
88
|
+
- Platform-specific polish (iOS-only, Android-only, web-only)
|
|
89
|
+
- Local bug fixes that don't alter shared semantic behavior
|
|
90
|
+
|
|
91
|
+
## If spec directories are empty (first-time setup)
|
|
92
|
+
|
|
93
|
+
Read `spec/openuispec-v0.1.md` from the package first, then:
|
|
94
|
+
1. Scan codebase for UI screens → create `openuispec/screens/<name>.yaml` as `status: stub`
|
|
95
|
+
2. Extract tokens (colors, fonts, spacing) → `openuispec/tokens/`
|
|
96
|
+
3. Create contract extensions → `openuispec/contracts/`
|
|
97
|
+
4. Create locale files → `openuispec/locales/<locale>.json`
|
|
98
|
+
5. Fill in `data_model`, `api.endpoints` in `openuispec/openuispec.yaml`
|
|
99
|
+
|
|
100
|
+
## Rules
|
|
101
|
+
- Do not snapshot drift unless the UI code has also been updated.
|
|
102
|
+
- Do not modify generated UI without checking whether the spec must change first.
|
|
103
|
+
- Do not use `configure-target --defaults` as silent approval — ask the user to confirm.
|
|
104
|
+
- Always read spec format from the installed package, not from cached/memorized content.
|
|
105
|
+
<!-- openuispec-rules-end -->
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# social-app
|
|
2
|
+
|
|
3
|
+
Test project for exercising the local [`openuispec`](../openuispec) checkout.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
- `openuispec/` contains the spec scaffold.
|
|
8
|
+
- `AGENTS.md` and `CLAUDE.md` include the OpenUISpec assistant rules generated by the local CLI.
|
|
9
|
+
|
|
10
|
+
## Commands
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm run validate
|
|
14
|
+
npm run validate:semantic
|
|
15
|
+
npm run status
|
|
16
|
+
npm run openuispec -- init
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The scripts call the local `../openuispec` repo directly, so this project can be used without installing `openuispec` globally.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
plugins {
|
|
2
|
+
alias(libs.plugins.android.application)
|
|
3
|
+
alias(libs.plugins.compose.compiler)
|
|
4
|
+
kotlin("plugin.serialization")
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
android {
|
|
8
|
+
namespace = "com.social.app"
|
|
9
|
+
compileSdk = 36
|
|
10
|
+
|
|
11
|
+
defaultConfig {
|
|
12
|
+
applicationId = "com.social.app"
|
|
13
|
+
minSdk = 26
|
|
14
|
+
targetSdk = 36
|
|
15
|
+
versionCode = 1
|
|
16
|
+
versionName = "1.0"
|
|
17
|
+
|
|
18
|
+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
19
|
+
vectorDrawables {
|
|
20
|
+
useSupportLibrary = true
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
buildTypes {
|
|
25
|
+
release {
|
|
26
|
+
isMinifyEnabled = false
|
|
27
|
+
proguardFiles(
|
|
28
|
+
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
29
|
+
"proguard-rules.pro"
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
compileOptions {
|
|
34
|
+
sourceCompatibility = JavaVersion.VERSION_11
|
|
35
|
+
targetCompatibility = JavaVersion.VERSION_11
|
|
36
|
+
}
|
|
37
|
+
kotlin {
|
|
38
|
+
compilerOptions {
|
|
39
|
+
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
buildFeatures {
|
|
43
|
+
compose = true
|
|
44
|
+
}
|
|
45
|
+
packaging {
|
|
46
|
+
resources {
|
|
47
|
+
excludes += "/META-INF/{AL2.0,LGPL2.1}"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
dependencies {
|
|
53
|
+
implementation(libs.androidx.core.ktx)
|
|
54
|
+
implementation(libs.androidx.lifecycle.runtime.ktx)
|
|
55
|
+
implementation(libs.androidx.activity.compose)
|
|
56
|
+
implementation(platform(libs.androidx.compose.bom))
|
|
57
|
+
implementation(libs.androidx.ui)
|
|
58
|
+
implementation(libs.androidx.ui.graphics)
|
|
59
|
+
implementation(libs.androidx.ui.tooling.preview)
|
|
60
|
+
implementation(libs.androidx.material3)
|
|
61
|
+
implementation(libs.androidx.material.icons.extended)
|
|
62
|
+
implementation(libs.google.material)
|
|
63
|
+
implementation(libs.coil.compose)
|
|
64
|
+
implementation(libs.coil.network)
|
|
65
|
+
|
|
66
|
+
// Decompose
|
|
67
|
+
implementation(libs.decompose)
|
|
68
|
+
implementation(libs.decompose.extensions.compose)
|
|
69
|
+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
|
|
70
|
+
|
|
71
|
+
// MVIKotlin
|
|
72
|
+
implementation(libs.mvikotlin)
|
|
73
|
+
implementation(libs.mvikotlin.main)
|
|
74
|
+
implementation(libs.mvikotlin.logging)
|
|
75
|
+
implementation("com.arkivanov.mvikotlin:mvikotlin-extensions-coroutines:4.3.0")
|
|
76
|
+
|
|
77
|
+
// Essenty
|
|
78
|
+
implementation(libs.essenty.lifecycle)
|
|
79
|
+
implementation(libs.essenty.instancekeeper)
|
|
80
|
+
|
|
81
|
+
// DataStore
|
|
82
|
+
implementation(libs.androidx.datastore.preferences)
|
|
83
|
+
implementation(libs.androidx.datastore.core)
|
|
84
|
+
|
|
85
|
+
testImplementation("junit:junit:4.13.2")
|
|
86
|
+
androidTestImplementation("androidx.test.ext:junit:1.2.1")
|
|
87
|
+
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
|
|
88
|
+
androidTestImplementation(platform(libs.androidx.compose.bom))
|
|
89
|
+
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
|
90
|
+
debugImplementation(libs.androidx.ui.tooling)
|
|
91
|
+
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
|
92
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
|
+
|
|
4
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
5
|
+
|
|
6
|
+
<application
|
|
7
|
+
android:name=".SocialAppApplication"
|
|
8
|
+
android:allowBackup="true"
|
|
9
|
+
android:icon="@mipmap/ic_launcher"
|
|
10
|
+
android:label="@string/nav_home"
|
|
11
|
+
android:roundIcon="@mipmap/ic_launcher_round"
|
|
12
|
+
android:supportsRtl="true"
|
|
13
|
+
android:theme="@style/Theme.SocialApp">
|
|
14
|
+
<activity
|
|
15
|
+
android:name=".MainActivity"
|
|
16
|
+
android:exported="true"
|
|
17
|
+
android:label="@string/nav_home"
|
|
18
|
+
android:theme="@style/Theme.SocialApp">
|
|
19
|
+
<intent-filter>
|
|
20
|
+
<action android:name="android.intent.action.MAIN" />
|
|
21
|
+
<category android:name="android.intent.category.LAUNCHER" />
|
|
22
|
+
</intent-filter>
|
|
23
|
+
</activity>
|
|
24
|
+
</application>
|
|
25
|
+
|
|
26
|
+
</manifest>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.social.app
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import com.arkivanov.decompose.ComponentContext
|
|
5
|
+
import com.arkivanov.mvikotlin.core.store.StoreFactory
|
|
6
|
+
import com.social.app.data.preferences.DataStorePreferencesRepository
|
|
7
|
+
import com.social.app.data.preferences.PreferencesRepository
|
|
8
|
+
import com.social.app.ui.navigation.DefaultRootComponent
|
|
9
|
+
import com.social.app.ui.navigation.RootComponent
|
|
10
|
+
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
|
|
11
|
+
import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory
|
|
12
|
+
|
|
13
|
+
class AppContainer(
|
|
14
|
+
context: Context,
|
|
15
|
+
) {
|
|
16
|
+
val preferencesRepository: PreferencesRepository = DataStorePreferencesRepository(context.applicationContext)
|
|
17
|
+
val storeFactory: StoreFactory = LoggingStoreFactory(DefaultStoreFactory())
|
|
18
|
+
|
|
19
|
+
fun createRootComponent(componentContext: ComponentContext): RootComponent = DefaultRootComponent(componentContext)
|
|
20
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
package com.social.app
|
|
2
|
+
|
|
3
|
+
import android.os.Bundle
|
|
4
|
+
import androidx.activity.ComponentActivity
|
|
5
|
+
import androidx.activity.compose.setContent
|
|
6
|
+
import androidx.activity.enableEdgeToEdge
|
|
7
|
+
import androidx.compose.runtime.collectAsState
|
|
8
|
+
import androidx.compose.runtime.getValue
|
|
9
|
+
import com.arkivanov.decompose.defaultComponentContext
|
|
10
|
+
import com.social.app.data.preferences.AppPreferences
|
|
11
|
+
import com.social.app.ui.MainShell
|
|
12
|
+
import com.social.app.ui.theme.SocialAppTheme
|
|
13
|
+
|
|
14
|
+
class MainActivity : ComponentActivity() {
|
|
15
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
16
|
+
super.onCreate(savedInstanceState)
|
|
17
|
+
val appContainer = (application as SocialAppApplication).appContainer
|
|
18
|
+
val root = appContainer.createRootComponent(defaultComponentContext())
|
|
19
|
+
|
|
20
|
+
enableEdgeToEdge()
|
|
21
|
+
setContent {
|
|
22
|
+
val preferences by appContainer.preferencesRepository.preferences.collectAsState(initial = AppPreferences())
|
|
23
|
+
|
|
24
|
+
SocialAppTheme(
|
|
25
|
+
themeMode = preferences.themeMode,
|
|
26
|
+
) {
|
|
27
|
+
MainShell(
|
|
28
|
+
root = root,
|
|
29
|
+
preferencesRepository = appContainer.preferencesRepository,
|
|
30
|
+
storeFactory = appContainer.storeFactory,
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package com.social.app
|
|
2
|
+
|
|
3
|
+
import android.app.Application
|
|
4
|
+
|
|
5
|
+
class SocialAppApplication : Application() {
|
|
6
|
+
lateinit var appContainer: AppContainer
|
|
7
|
+
private set
|
|
8
|
+
|
|
9
|
+
override fun onCreate() {
|
|
10
|
+
super.onCreate()
|
|
11
|
+
appContainer = AppContainer(this)
|
|
12
|
+
}
|
|
13
|
+
}
|