Skip to content
cccskills
FreePublished on 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.

The English summary is being prepared. Showing the original description.

See how to install

Files included (1)

  • SKILL.md4.7 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

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

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

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

The English summary is being prepared. Showing the original description.

po4yka/RIPDPI81Updated Oct 20, 2026

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.

The English summary is being prepared. Showing the original description.

po4yka/RIPDPI81Updated Oct 20, 2026

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.

The English summary is being prepared. Showing the original description.

po4yka/RIPDPI81Updated Oct 20, 2026

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.

The English summary is being prepared. Showing the original description.

po4yka/RIPDPI81Updated Oct 20, 2026

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

The English summary is being prepared. Showing the original description.

po4yka/RIPDPI81Updated Oct 20, 2026

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

The English summary is being prepared. Showing the original description.

po4yka/RIPDPI81Updated Oct 20, 2026

See all skills by po4yka

Report a problem with this skill