openuispec 0.1.45 → 0.1.47
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 +17 -5
- package/cli/init.ts +21 -3
- package/examples/social-app/.mcp.json +10 -0
- package/examples/social-app/AGENTS.md +114 -0
- package/examples/social-app/CLAUDE.md +114 -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 +164 -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 +259 -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 +340 -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 +103 -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 +79 -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 +104 -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 +138 -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 +99 -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/examples/taskflow/openuispec/openuispec.yaml +2 -0
- package/examples/todo-orbit/openuispec/openuispec.yaml +2 -0
- package/mcp-server/index.ts +200 -10
- package/package.json +1 -1
- package/schema/openuispec.schema.json +7 -0
- package/spec/openuispec-v0.1.md +13 -0
package/README.md
CHANGED
|
@@ -82,10 +82,11 @@ This replaces the old approach of writing instructions in CLAUDE.md and hoping t
|
|
|
82
82
|
| **Claude Code** | `.mcp.json` | Always |
|
|
83
83
|
| **Codex** | `.codex/config.toml` | Always |
|
|
84
84
|
| **VS Code / Copilot** | `.vscode/mcp.json` | If `.vscode/` exists |
|
|
85
|
+
| **Gemini CLI** | `.gemini/settings.json` | If `.gemini/` exists |
|
|
85
86
|
|
|
86
87
|
Manual setup (if needed):
|
|
87
88
|
|
|
88
|
-
**Claude Code** (`.mcp.json`), **VS Code / Copilot** (`.vscode/mcp.json`):
|
|
89
|
+
**Claude Code** (`.mcp.json`), **VS Code / Copilot** (`.vscode/mcp.json`), **Gemini CLI** (`.gemini/settings.json`):
|
|
89
90
|
```json
|
|
90
91
|
{
|
|
91
92
|
"mcpServers": {
|
|
@@ -114,10 +115,14 @@ Or run directly: `openuispec mcp`
|
|
|
114
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 |
|
|
115
116
|
| `openuispec_prepare` | Before UI code generation | Returns spec context, platform config, generation constraints |
|
|
116
117
|
| `openuispec_read_specs` | Before and after generation | Loads spec file contents — the authoritative source for tokens, screens, contracts |
|
|
117
|
-
| `openuispec_check` | After generation | Schema validation + concrete audit checklist from your spec |
|
|
118
|
+
| `openuispec_check` | After generation | Schema validation + concrete audit checklist from your spec. Optional `screens`/`contracts` params scope the audit |
|
|
118
119
|
| `openuispec_validate` | After spec edits | Schema-only validation, optionally filtered by group |
|
|
119
120
|
| `openuispec_drift` | Before updates | Detect spec drift since last snapshot, with semantic explanation |
|
|
120
121
|
| `openuispec_status` | Anytime | Cross-target summary: baselines, drift, next steps |
|
|
122
|
+
| `openuispec_get_screen` | Incremental edits | Get a single screen spec by name — faster than `read_specs` for targeted work |
|
|
123
|
+
| `openuispec_get_contract` | Incremental edits | Get a single contract spec, optionally filtered to one variant |
|
|
124
|
+
| `openuispec_get_tokens` | Incremental edits | Get tokens for a specific category (color, typography, spacing, etc.) |
|
|
125
|
+
| `openuispec_get_locale` | Incremental edits | Get a single locale file, optionally filtered to specific keys |
|
|
121
126
|
|
|
122
127
|
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.
|
|
123
128
|
|
|
@@ -137,6 +142,7 @@ See the examples for reference:
|
|
|
137
142
|
|
|
138
143
|
- [TaskFlow](./examples/taskflow/openuispec/) — compact reference spec covering all 7 contract families
|
|
139
144
|
- [Todo Orbit](./examples/todo-orbit/openuispec/) — bilingual task app with localization, custom contracts, and generated native/web targets
|
|
145
|
+
- [Social App](./examples/social-app/openuispec/) — trilingual social app with feeds, messaging, profiles, and generated Android/web targets
|
|
140
146
|
|
|
141
147
|
## Repository structure
|
|
142
148
|
|
|
@@ -174,6 +180,7 @@ openuispec/
|
|
|
174
180
|
│ │ ├── generated/ # Generated iOS, Android, and web apps
|
|
175
181
|
│ │ ├── README.md # Sample overview and structure
|
|
176
182
|
│ │ └── AGENTS.md / CLAUDE.md # AI rules generated from the package
|
|
183
|
+
│ ├── social-app/ # Social app sample (trilingual, Android + Web)
|
|
177
184
|
│ └── todo-orbit/ # Full showcase sample
|
|
178
185
|
│ ├── openuispec/ # Source OpenUISpec project
|
|
179
186
|
│ ├── generated/ # Generated iOS, Android, and web apps
|
|
@@ -183,7 +190,7 @@ openuispec/
|
|
|
183
190
|
│ ├── index.ts # Entry point
|
|
184
191
|
│ └── init.ts # Project scaffolding + AI rules
|
|
185
192
|
├── mcp-server/ # MCP server (openuispec-mcp)
|
|
186
|
-
│ └── index.ts # Stdio transport,
|
|
193
|
+
│ └── index.ts # Stdio transport, 12 tools
|
|
187
194
|
├── check/ # Composite validation command
|
|
188
195
|
│ └── index.ts # Schema + semantic + readiness
|
|
189
196
|
├── drift/ # Drift detection (spec change tracking)
|
|
@@ -242,6 +249,8 @@ By default, drift stores state in `generated/<target>/<project>/`. To point targ
|
|
|
242
249
|
```yaml
|
|
243
250
|
generation:
|
|
244
251
|
targets: [ios, android, web]
|
|
252
|
+
extra_rules:
|
|
253
|
+
- "Generation hint strings may start with [common], [ios], [android], or [web] to indicate scope."
|
|
245
254
|
output_dir:
|
|
246
255
|
web: "../web-ui/"
|
|
247
256
|
android: "../kmp-ui/"
|
|
@@ -254,6 +263,8 @@ Paths are relative to `openuispec.yaml`. The `.openuispec-state.json` file is st
|
|
|
254
263
|
|
|
255
264
|
If `api.endpoints` are declared, `generation.code_roots.backend` is required. It should point at the backend folder the AI must inspect when generating API clients or wiring request/response behavior.
|
|
256
265
|
|
|
266
|
+
`generation.extra_rules` can hold project-wide generation conventions for AI and humans. For example, projects may declare that generation hint strings use prefixes such as `[common]`, `[ios]`, `[android]`, and `[web]` to indicate scope.
|
|
267
|
+
|
|
257
268
|
`openuispec drift --snapshot --target <target>` requires that target output directory to already exist. If it does not, generate the target code first, then snapshot the accepted baseline.
|
|
258
269
|
|
|
259
270
|
Use the commands like this:
|
|
@@ -344,7 +355,7 @@ to see which targets are already up to date and which ones still need to catch u
|
|
|
344
355
|
|
|
345
356
|
## Status
|
|
346
357
|
|
|
347
|
-
**v0.1 — Draft**. The spec covers all foundational layers. TaskFlow provides a compact reference app,
|
|
358
|
+
**v0.1 — Draft**. The spec covers all foundational layers. TaskFlow provides a compact reference app, Todo Orbit extends coverage with localization, recurring-rule flows, custom contracts, and generated native/web targets, and Social App demonstrates a trilingual social feed app with generated Android and web targets.
|
|
348
359
|
|
|
349
360
|
### Roadmap
|
|
350
361
|
|
|
@@ -363,7 +374,8 @@ to see which targets are already up to date and which ones still need to catch u
|
|
|
363
374
|
- [x] CLI tool (`openuispec init` for project scaffolding + AI rules)
|
|
364
375
|
- [x] MCP server for AI tool integration (`openuispec-mcp`)
|
|
365
376
|
- [x] Multi-platform showcase app (`examples/todo-orbit/`)
|
|
366
|
-
- [
|
|
377
|
+
- [x] Social app example (`examples/social-app/`)
|
|
378
|
+
- [ ] More example apps (e-commerce, dashboard)
|
|
367
379
|
|
|
368
380
|
## Contributing
|
|
369
381
|
|
package/cli/init.ts
CHANGED
|
@@ -208,6 +208,8 @@ i18n:
|
|
|
208
208
|
|
|
209
209
|
generation:
|
|
210
210
|
targets: [${targetList}]
|
|
211
|
+
# extra_rules: # Optional: project-wide AI authoring conventions
|
|
212
|
+
# - "Generation hint strings may start with [common], [ios], [android], or [web] to indicate scope."
|
|
211
213
|
# output_dir: # Optional: map targets to code directories
|
|
212
214
|
# ios: "../ios-app/" # relative to this file
|
|
213
215
|
# android: "../android-app/"
|
|
@@ -272,10 +274,14 @@ When the openuispec MCP server is configured, AI assistants should use these too
|
|
|
272
274
|
| \`openuispec_spec_schema\` | Get the full JSON schema for a specific spec type — exact structure, required fields, allowed values. |
|
|
273
275
|
| \`openuispec_prepare\` | **Before any UI code generation.** Returns spec context, platform config, and constraints. |
|
|
274
276
|
| \`openuispec_read_specs\` | Load spec file contents — the authoritative source for tokens, screens, contracts. |
|
|
275
|
-
| \`openuispec_check\` | After editing spec files. Validates schema + semantics + readiness. |
|
|
277
|
+
| \`openuispec_check\` | After editing spec files. Validates schema + semantics + readiness. Optional \`screens\`/\`contracts\` params scope the audit. |
|
|
276
278
|
| \`openuispec_validate\` | Schema-only validation, optionally by group. |
|
|
277
279
|
| \`openuispec_drift\` | Detect spec changes since last snapshot. |
|
|
278
280
|
| \`openuispec_status\` | To understand cross-target state (baselines, drift, next steps). |
|
|
281
|
+
| \`openuispec_get_screen\` | Get a single screen spec by name — faster than \`read_specs\` for targeted edits. |
|
|
282
|
+
| \`openuispec_get_contract\` | Get a single contract spec, optionally filtered to one variant. |
|
|
283
|
+
| \`openuispec_get_tokens\` | Get tokens for a specific category (color, typography, spacing, etc.). |
|
|
284
|
+
| \`openuispec_get_locale\` | Get a single locale file, optionally filtered to specific keys. |
|
|
279
285
|
|
|
280
286
|
## CLI commands
|
|
281
287
|
|
|
@@ -345,6 +351,15 @@ Call these MCP tools directly. They return structured JSON with everything you n
|
|
|
345
351
|
- Call \`openuispec_spec_schema\` with the specific type to get the full JSON schema.
|
|
346
352
|
- Write the spec file following the schema exactly.
|
|
347
353
|
|
|
354
|
+
**Focused getters (prefer these for incremental edits over \`read_specs\`):**
|
|
355
|
+
- \`openuispec_get_screen(name)\` — single screen spec
|
|
356
|
+
- \`openuispec_get_contract(name, variant?)\` — single contract, optionally one variant
|
|
357
|
+
- \`openuispec_get_tokens(category)\` — single token category (color, typography, spacing, etc.)
|
|
358
|
+
- \`openuispec_get_locale(locale, keys?)\` — single locale file, optionally filtered keys
|
|
359
|
+
- \`openuispec_check(target, screens?, contracts?)\` — scoped audit for specific screens/contracts
|
|
360
|
+
|
|
361
|
+
Use \`read_specs\` for full-project generation; use focused getters when editing one screen or contract.
|
|
362
|
+
|
|
348
363
|
**Other tools:**
|
|
349
364
|
- \`openuispec_status\` — cross-target summary, good starting point
|
|
350
365
|
- \`openuispec_drift\` with \`explain: true\` — property-level spec changes
|
|
@@ -501,12 +516,14 @@ const EXPECTED_MCP_CONFIG = {
|
|
|
501
516
|
* MCP config files by agent:
|
|
502
517
|
* .mcp.json — Claude Code (project scope)
|
|
503
518
|
* .vscode/mcp.json — VS Code / Copilot Chat
|
|
519
|
+
* .gemini/settings.json — Gemini CLI (if .gemini/ exists)
|
|
504
520
|
*
|
|
505
521
|
* All use the same { mcpServers: { openuispec: { command, args } } } shape.
|
|
506
522
|
*/
|
|
507
523
|
const JSON_MCP_PATHS = [
|
|
508
524
|
".mcp.json",
|
|
509
525
|
join(".vscode", "mcp.json"),
|
|
526
|
+
join(".gemini", "settings.json"),
|
|
510
527
|
];
|
|
511
528
|
|
|
512
529
|
/** Codex uses TOML: .codex/config.toml */
|
|
@@ -542,8 +559,9 @@ function configureMcp(cwd: string, showRestart: boolean, quiet: boolean = false)
|
|
|
542
559
|
for (const relPath of JSON_MCP_PATHS) {
|
|
543
560
|
const configPath = join(cwd, relPath);
|
|
544
561
|
|
|
545
|
-
//
|
|
546
|
-
|
|
562
|
+
// Optional dirs: only write config if the parent directory already exists
|
|
563
|
+
const optionalParent = [".vscode", ".gemini"].find((d) => relPath.startsWith(d));
|
|
564
|
+
if (optionalParent && !existsSync(join(cwd, optionalParent))) continue;
|
|
547
565
|
|
|
548
566
|
try {
|
|
549
567
|
let config: Record<string, any> = {};
|
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
**Focused getters (prefer these for incremental edits over `read_specs`):**
|
|
42
|
+
- `openuispec_get_screen(name)` — single screen spec
|
|
43
|
+
- `openuispec_get_contract(name, variant?)` — single contract, optionally one variant
|
|
44
|
+
- `openuispec_get_tokens(category)` — single token category (color, typography, spacing, etc.)
|
|
45
|
+
- `openuispec_get_locale(locale, keys?)` — single locale file, optionally filtered keys
|
|
46
|
+
- `openuispec_check(target, screens?, contracts?)` — scoped audit for specific screens/contracts
|
|
47
|
+
|
|
48
|
+
Use `read_specs` for full-project generation; use focused getters when editing one screen or contract.
|
|
49
|
+
|
|
50
|
+
**Other tools:**
|
|
51
|
+
- `openuispec_status` — cross-target summary, good starting point
|
|
52
|
+
- `openuispec_drift` with `explain: true` — property-level spec changes
|
|
53
|
+
- `openuispec_validate` — schema-only validation by group
|
|
54
|
+
|
|
55
|
+
### CLI fallback (when MCP is not available)
|
|
56
|
+
|
|
57
|
+
If MCP tools are not available, use these CLI commands with `--json` flag:
|
|
58
|
+
- `openuispec prepare --target <t> --json` — build AI-ready work bundle
|
|
59
|
+
- `openuispec check --target <t> --json` — composite validation
|
|
60
|
+
- `openuispec status --json` — cross-target status
|
|
61
|
+
- `openuispec drift --target <t> --explain --json` — semantic drift
|
|
62
|
+
- `openuispec validate [group...] --json` — schema validation
|
|
63
|
+
|
|
64
|
+
### Other CLI commands
|
|
65
|
+
- `openuispec init` — scaffold a new spec project
|
|
66
|
+
- `openuispec drift --snapshot --target <t>` — snapshot current state (only after UI code is updated)
|
|
67
|
+
- `openuispec configure-target <t>` — configure target platform stack
|
|
68
|
+
- `openuispec update-rules` — update AI rules to match installed package version
|
|
69
|
+
|
|
70
|
+
## Spec format reference
|
|
71
|
+
|
|
72
|
+
The spec format, schemas, and generation rules are in the installed `openuispec` package.
|
|
73
|
+
You MUST read the reference files before creating or editing spec files — do NOT guess the format.
|
|
74
|
+
|
|
75
|
+
**Find the package:** `node_modules/openuispec/` or run `npm root -g` → `<prefix>/openuispec/`.
|
|
76
|
+
**Online fallback:** `https://openuispec.rsteam.uz/llms-full.txt`
|
|
77
|
+
|
|
78
|
+
**Reference files (read in order):**
|
|
79
|
+
1. `README.md` — schema tables, file format, root wrapper keys
|
|
80
|
+
2. `spec/openuispec-v0.1.md` — full specification
|
|
81
|
+
3. `examples/taskflow/openuispec/` — complete working example
|
|
82
|
+
4. `schema/` — JSON Schemas for every file type
|
|
83
|
+
|
|
84
|
+
## Spec location
|
|
85
|
+
- Spec root: `openuispec/` — read `openuispec/openuispec.yaml` first for actual paths.
|
|
86
|
+
- Default dirs: tokens/, screens/, flows/, contracts/, platform/, locales/
|
|
87
|
+
|
|
88
|
+
## When to start from spec vs platform code
|
|
89
|
+
|
|
90
|
+
**Spec-first** (use `openuispec_prepare` or `openuispec prepare`):
|
|
91
|
+
- Screen structure, navigation, fields, actions, validation, data binding changes
|
|
92
|
+
- Token, variant, contract, flow, or localization changes
|
|
93
|
+
- Changes affecting multiple platforms
|
|
94
|
+
- Requests in product/UI terms
|
|
95
|
+
|
|
96
|
+
**Platform-first** (skip spec tools):
|
|
97
|
+
- Platform-specific polish (iOS-only, Android-only, web-only)
|
|
98
|
+
- Local bug fixes that don't alter shared semantic behavior
|
|
99
|
+
|
|
100
|
+
## If spec directories are empty (first-time setup)
|
|
101
|
+
|
|
102
|
+
Read `spec/openuispec-v0.1.md` from the package first, then:
|
|
103
|
+
1. Scan codebase for UI screens → create `openuispec/screens/<name>.yaml` as `status: stub`
|
|
104
|
+
2. Extract tokens (colors, fonts, spacing) → `openuispec/tokens/`
|
|
105
|
+
3. Create contract extensions → `openuispec/contracts/`
|
|
106
|
+
4. Create locale files → `openuispec/locales/<locale>.json`
|
|
107
|
+
5. Fill in `data_model`, `api.endpoints` in `openuispec/openuispec.yaml`
|
|
108
|
+
|
|
109
|
+
## Rules
|
|
110
|
+
- Do not snapshot drift unless the UI code has also been updated.
|
|
111
|
+
- Do not modify generated UI without checking whether the spec must change first.
|
|
112
|
+
- Do not use `configure-target --defaults` as silent approval — ask the user to confirm.
|
|
113
|
+
- Always read spec format from the installed package, not from cached/memorized content.
|
|
114
|
+
<!-- openuispec-rules-end -->
|
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
**Focused getters (prefer these for incremental edits over `read_specs`):**
|
|
42
|
+
- `openuispec_get_screen(name)` — single screen spec
|
|
43
|
+
- `openuispec_get_contract(name, variant?)` — single contract, optionally one variant
|
|
44
|
+
- `openuispec_get_tokens(category)` — single token category (color, typography, spacing, etc.)
|
|
45
|
+
- `openuispec_get_locale(locale, keys?)` — single locale file, optionally filtered keys
|
|
46
|
+
- `openuispec_check(target, screens?, contracts?)` — scoped audit for specific screens/contracts
|
|
47
|
+
|
|
48
|
+
Use `read_specs` for full-project generation; use focused getters when editing one screen or contract.
|
|
49
|
+
|
|
50
|
+
**Other tools:**
|
|
51
|
+
- `openuispec_status` — cross-target summary, good starting point
|
|
52
|
+
- `openuispec_drift` with `explain: true` — property-level spec changes
|
|
53
|
+
- `openuispec_validate` — schema-only validation by group
|
|
54
|
+
|
|
55
|
+
### CLI fallback (when MCP is not available)
|
|
56
|
+
|
|
57
|
+
If MCP tools are not available, use these CLI commands with `--json` flag:
|
|
58
|
+
- `openuispec prepare --target <t> --json` — build AI-ready work bundle
|
|
59
|
+
- `openuispec check --target <t> --json` — composite validation
|
|
60
|
+
- `openuispec status --json` — cross-target status
|
|
61
|
+
- `openuispec drift --target <t> --explain --json` — semantic drift
|
|
62
|
+
- `openuispec validate [group...] --json` — schema validation
|
|
63
|
+
|
|
64
|
+
### Other CLI commands
|
|
65
|
+
- `openuispec init` — scaffold a new spec project
|
|
66
|
+
- `openuispec drift --snapshot --target <t>` — snapshot current state (only after UI code is updated)
|
|
67
|
+
- `openuispec configure-target <t>` — configure target platform stack
|
|
68
|
+
- `openuispec update-rules` — update AI rules to match installed package version
|
|
69
|
+
|
|
70
|
+
## Spec format reference
|
|
71
|
+
|
|
72
|
+
The spec format, schemas, and generation rules are in the installed `openuispec` package.
|
|
73
|
+
You MUST read the reference files before creating or editing spec files — do NOT guess the format.
|
|
74
|
+
|
|
75
|
+
**Find the package:** `node_modules/openuispec/` or run `npm root -g` → `<prefix>/openuispec/`.
|
|
76
|
+
**Online fallback:** `https://openuispec.rsteam.uz/llms-full.txt`
|
|
77
|
+
|
|
78
|
+
**Reference files (read in order):**
|
|
79
|
+
1. `README.md` — schema tables, file format, root wrapper keys
|
|
80
|
+
2. `spec/openuispec-v0.1.md` — full specification
|
|
81
|
+
3. `examples/taskflow/openuispec/` — complete working example
|
|
82
|
+
4. `schema/` — JSON Schemas for every file type
|
|
83
|
+
|
|
84
|
+
## Spec location
|
|
85
|
+
- Spec root: `openuispec/` — read `openuispec/openuispec.yaml` first for actual paths.
|
|
86
|
+
- Default dirs: tokens/, screens/, flows/, contracts/, platform/, locales/
|
|
87
|
+
|
|
88
|
+
## When to start from spec vs platform code
|
|
89
|
+
|
|
90
|
+
**Spec-first** (use `openuispec_prepare` or `openuispec prepare`):
|
|
91
|
+
- Screen structure, navigation, fields, actions, validation, data binding changes
|
|
92
|
+
- Token, variant, contract, flow, or localization changes
|
|
93
|
+
- Changes affecting multiple platforms
|
|
94
|
+
- Requests in product/UI terms
|
|
95
|
+
|
|
96
|
+
**Platform-first** (skip spec tools):
|
|
97
|
+
- Platform-specific polish (iOS-only, Android-only, web-only)
|
|
98
|
+
- Local bug fixes that don't alter shared semantic behavior
|
|
99
|
+
|
|
100
|
+
## If spec directories are empty (first-time setup)
|
|
101
|
+
|
|
102
|
+
Read `spec/openuispec-v0.1.md` from the package first, then:
|
|
103
|
+
1. Scan codebase for UI screens → create `openuispec/screens/<name>.yaml` as `status: stub`
|
|
104
|
+
2. Extract tokens (colors, fonts, spacing) → `openuispec/tokens/`
|
|
105
|
+
3. Create contract extensions → `openuispec/contracts/`
|
|
106
|
+
4. Create locale files → `openuispec/locales/<locale>.json`
|
|
107
|
+
5. Fill in `data_model`, `api.endpoints` in `openuispec/openuispec.yaml`
|
|
108
|
+
|
|
109
|
+
## Rules
|
|
110
|
+
- Do not snapshot drift unless the UI code has also been updated.
|
|
111
|
+
- Do not modify generated UI without checking whether the spec must change first.
|
|
112
|
+
- Do not use `configure-target --defaults` as silent approval — ask the user to confirm.
|
|
113
|
+
- Always read spec format from the installed package, not from cached/memorized content.
|
|
114
|
+
<!-- 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
|
+
}
|