ADB-based RIPDPI device/emulator debugging: build/install/launch, logcat filtering, fixture port-forwarding, instrumented tests, crash/ANR triage. Use when debugging on a real device or emulator.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI's own Compose conventions: ViewModel pattern, Route/Screen split, DataStore->StateFlow, RipDpiThemeTokens. Use for how this app does Compose, not generic Compose API questions (see compose).
インストール方法を見るインストールする前に、エージェントに与えられる指示の中身を確認できます。
RIPDPI uses Jetpack Compose with Material 3 and a sealed-class navigation system. State flows from DataStore through ViewModels to Composables via StateFlow + collectAsStateWithLifecycle().
Diagnostics UI is a current hotspot in this repo. It layers internal UI models over shared diagnostics contracts, exposes stable automation tags through RipDpiTestTags, and routes callback-style actions such as opening Advanced Settings or candidate-detail sheets through screen-level parameters.
DataStore (proto) -> ViewModel (StateFlow + combine) -> Composable (collectAsStateWithLifecycle)
User action -> ViewModel method -> DataStore.updateData { } or ServiceManager.start/stop
One-shot effects -> Channel<Effect> -> receiveAsFlow() -> LaunchedEffect collector
Routes are defined as a sealed class in app/.../ui/navigation/Route.kt.
Route sealed class with route string, @StringRes titleRes, optional iconRoute.topLevel listRoute.all listcomposable(Route.YourRoute.route) { ... } in RipDpiNavHost.ktnavController.navigate(Route.YourRoute.route) { launchSingleTop = true; restoreState = true }launchSingleTop = true and restoreState = true for all navigationsisTopLevelDestination() routesclass ExampleViewModel(application: Application) : AndroidViewModel(application) {
// State: combine multiple sources into single UI state
val uiState: StateFlow<UiState> = combine(
application.settingsStore.data,
_localState,
) { settings, local -> UiState(/*...*/) }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), UiState())
// Effects: one-shot events (navigation, snackbar, permission requests)
private val _effects = Channel<Effect>(Channel.BUFFERED)
val effects = _effects.receiveAsFlow()
// Actions: public methods called by Composables
fun onAction() { viewModelScope.launch { /* ... */ } }
}
SharingStarted.WhileSubscribed(5_000) for all StateFlow exportsAndroidViewModel (not plain ViewModel) when DataStore access neededMutex for thread-safe state transitions (see MainViewModel.toggleService)Channel<Effect> for one-shot UI events, collected via LaunchedEffect// Route composable: connects ViewModel to screen
@Composable
fun ExampleRoute(viewModel: ExampleViewModel, navController: NavController) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
ExampleScreen(uiState = uiState, onAction = viewModel::onAction)
}
// Screen composable: pure UI, no ViewModel reference
@Composable
fun ExampleScreen(uiState: UiState, onAction: () -> Unit) { /* ... */ }
collectAsStateWithLifecycle() (not collectAsState())RipDpiThemeTokens for colors, spacing, typography| ViewModel | Location | Purpose |
|---|---|---|
MainViewModel | activities/MainViewModel.kt | Connection state, VPN/proxy toggle, metrics |
ConfigViewModel | activities/ConfigViewModel.kt | Proxy config presets, draft editing, validation |
SettingsViewModel | activities/SettingsViewModel.kt | App settings, theme, DataStore persistence |
DiagnosticsViewModel | activities/DiagnosticsViewModel.kt | Diagnostics scan orchestration, history, export/share state, and strategy-probe presentation |
activities/DiagnosticsUi* support files instead of recomputing report metadata directly in composables.app/src/main/kotlin/com/poyka/ripdpi/ui/testing/RipDpiTestTags.kt for any new externally exercised UI.onOpenAdvancedSettings, onSelectCandidate, and sheet-dismiss actions through Route/Screen parameters rather than letting deep child composables navigate directly.| Mistake | Fix |
|---|---|
Using collectAsState() | Use collectAsStateWithLifecycle() for lifecycle awareness |
| Passing ViewModel to Screen composable | Pass uiState and callbacks; keep Screen stateless |
| Hardcoding colors/spacing | Use RipDpiThemeTokens and Material 3 theme |
Missing WhileSubscribed(5_000) | Required for proper lifecycle handling in all StateFlow exports |
| Creating ViewModel in Composable | Use viewModel() in Route composable or pass from NavHost |
compose (.agents/skills/compose/SKILL.md):
General Jetpack Compose API reference (guidance docs plus a live-fetch index into the
actual androidx source) and the scored RIPDPI Compose quality audit.
Use for questions about how Compose APIs work internally, correct API usage patterns,
recomposition mechanics, Modifier ordering, side-effects, performance, or accessibility.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
ADB-based RIPDPI device/emulator debugging: build/install/launch, logcat filtering, fixture port-forwarding, instrumented tests, crash/ANR triage. Use when debugging on a real device or emulator.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium launch-contract reference: start routes and permission/service/data presets. Use when a test launches to the wrong screen or a new automation route is added. General flakiness: appium-test-debug.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium test authoring: page objects, resource-id locators, assertions, wait tiers. Use when writing a new Appium test or page object, or adding coverage for a new screen.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium failure triage: flaky tests, locator/session/wait issues, screenshot and element-tree debugging. Use when an Appium test fails or is flaky.
日本語の概要は準備中です。原文の説明を表示しています。
Add or modify a GitHub Actions job. Use when editing a file under .github/workflows/. Not for running a workflow locally (local-ci-act) or release signing (release-signing).
日本語の概要は準備中です。原文の説明を表示しています。
Conservative review of end-user legal exposure from diagnostics targets and probe hosts, by jurisdiction. Use when shipping or editing diagnostics target lists, probe hosts, or bootstrap endpoints.
日本語の概要は準備中です。原文の説明を表示しています。