本文へ移動
cccskills
無料GitHub で公開

protobuf-datastore

Kotlin mapping for the AppSettings proto-backed DataStore: UI-state and native-preferences conversion. Use when adding or reading an app-settings field. Removing a field: use protobuf-schema-evolution first.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md4.7 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Protobuf DataStore

Overview

RIPDPI persists all app settings as a single Protobuf message (AppSettings) stored via Jetpack DataStore. The schema is the source of truth for all configurable values.

Key Files

FilePurpose
core/data/model/src/main/proto/app_settings.protoSchema definition for persisted app settings
core/data/settings/src/main/kotlin/com/poyka/ripdpi/data/AppSettingsSerializer.ktSerializer with default values
core/data/settings/src/main/kotlin/com/poyka/ripdpi/data/AppDataStore.ktDataStore extension property
core/engine/.../core/RipDpiProxyPreferences.ktProto -> native preferences conversion
app/.../activities/SettingsViewModel.ktProto -> UI state conversion
app/.../activities/ConfigViewModel.ktConfig draft validation and persistence

Adding a New Setting

  1. Add field to proto schema (app_settings.proto):

    bool your_new_setting = <next_field_number>;
    

    Use next available field number. Never reuse or renumber existing fields.

  2. Set default in serializer (AppSettingsSerializer.kt):

    override val defaultValue: AppSettings = AppSettings.newBuilder()
        // ... existing defaults ...
        .setYourNewSetting(false)
        .build()
    
  3. Expose in UI state (SettingsUiState or ConfigDraft):

    data class SettingsUiState(
        // ... existing fields ...
        val yourNewSetting: Boolean = false,
    )
    
  4. Map in conversion function (AppSettings.toUiState() or toConfigDraft()):

    fun AppSettings.toUiState() = SettingsUiState(
        // ... existing mappings ...
        yourNewSetting = this.yourNewSetting,
    )
    
  5. Persist changes via DataStore:

    context.settingsStore.updateData { current ->
        current.toBuilder().setYourNewSetting(value).build()
    }
    

Reading Settings

// Reactive (preferred): Flow<AppSettings>
context.settingsStore.data.collect { settings ->
    val value = settings.yourSetting
}

// In ViewModel: combine with other flows
val uiState = combine(application.settingsStore.data, otherFlow) { settings, other ->
    UiState(setting = settings.yourSetting, /* ... */)
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), UiState())

Proto Field Groups

GroupFieldsNotes
Generalapp_theme, ripdpi_mode, dns_ip, ipv6_enableMode is "vpn" or "proxy"
Command modeenable_cmd_settings, cmd_argsRaw CLI args for command-line mode of the native RIPDPI proxy
Proxyproxy_ip, proxy_port, max_connections, buffer_sizeDefaults: 127.0.0.1:1080
Desyncdefault_ttl, custom_ttl, fake_ttl, fake_sni, fake_offset, oob_data, drop_sack, etc.desync_method and split_position are reserved/removed; grep app_settings.proto for the current field list
Protocolsdesync_http, desync_https, desync_udpBool flags for which protocols to desync
Hostshosts_mode, hosts_blacklist, hosts_whitelistMode: disable/blacklist/whitelist
TLStls_minor_enabled, etc.tlsrec_* names are reserved/removed (TLS record splitting is a desync chain step now); grep app_settings.proto for the current field list
Apponboarding_complete, biometric_enabled, backup_pinApp lifecycle settings

Preferences Conversion (Proto -> Native)

RipDpiProxyPreferences.fromSettingsStore(context) reads the proto and creates either:

  • RipDpiProxyCmdPreferences(args) if enable_cmd_settings is true
  • RipDpiProxyUIPreferences(...) mapping all 27 proxy parameters

Diagnostics Interaction

  • enable_cmd_settings = true is a hard stop for automatic probing/audit. Those workflows require UI-config JSON so they can launch isolated strategy trials.
  • If a change touches diagnostics availability or recommendation flow, also inspect core:diagnostics and the diagnostics UI layer. The proto flag alone is not the whole behavior.

Common Mistakes

MistakeFix
Reusing proto field numbersAlways use next available number; old numbers are reserved forever
Forgetting default in serializerEvery field needs an explicit default in AppSettingsSerializer.defaultValue
Reading DataStore on main threadAlways use Flow.collect or updateData (both suspend)
Not updating toUiState() mappingNew fields must be mapped in all conversion functions
String enums without validationProto stores strings ("vpn", "proxy") -- validate on read

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

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).

日本語の概要は準備中です。原文の説明を表示しています。

po4yka/RIPDPI792026年10月13日 更新

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.

日本語の概要は準備中です。原文の説明を表示しています。

po4yka/RIPDPI792026年10月13日 更新

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.

日本語の概要は準備中です。原文の説明を表示しています。

po4yka/RIPDPI792026年10月13日 更新

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.

日本語の概要は準備中です。原文の説明を表示しています。

po4yka/RIPDPI792026年10月13日 更新

RIPDPI Appium failure triage: flaky tests, locator/session/wait issues, screenshot and element-tree debugging. Use when an Appium test fails or is flaky.

日本語の概要は準備中です。原文の説明を表示しています。

po4yka/RIPDPI792026年10月13日 更新

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).

日本語の概要は準備中です。原文の説明を表示しています。

po4yka/RIPDPI792026年10月13日 更新

po4yka のスキルをすべて見る

このスキルの問題を報告する