Skip to content

Patchself/FlipClock

Repository files navigation

FlipClock · Android (Jetpack Compose)

WeChat MiniProgram wx1b56c32a1e5c1714 rewritten as a native Android app using Jetpack Compose + Material 3.

Stack

  • Kotlin 2.3.20, AGP 9.0.1
  • Jetpack Compose (BOM 2026.03.01) + Material 3
  • Navigation 3 with typed keys (kotlinx.serialization)
  • Coroutines + StateFlow for reactive state
  • Min SDK 26, target SDK 36

Project layout

app/src/main/java/com/example/flipclock/
├── MainActivity.kt            # Entry point, sets up theme + navigation
├── Navigation.kt              # NavDisplay wiring, shared BleManager
├── NavigationKeys.kt          # @Serializable NavKeys (Home, AddClockKey)
├── theme/                     # Material 3 color/typography/shape
├── data/
│   ├── Alarm.kt               # Alarm entity + RepeatMode enum
│   └── DeviceState.kt         # Aggregate device state + FeatureTab
├── ble/
│   ├── Opcodes.kt             # Protocol constants transcribed 1:1 from JS
│   ├── BleCodec.kt            # ByteArray packet builders
│   ├── BleManager.kt          # Transport interface
│   └── FakeBleManager.kt      # In-memory impl (decodes writes back onto state)
└── ui/
    ├── components/
    │   ├── FlipClockDisplay.kt   # Split-flap digit + HH:MM row
    │   └── CommonCards.kt        # FlipCard, NoticeBanner, SettingsRow
    ├── home/
    │   ├── HomeScreen.kt         # Scaffold, clock, status card, tabs
    │   ├── HomeViewModel.kt      # Bridges UI events to BleManager
    │   ├── AlarmSection.kt       # 闹钟
    │   ├── TomatoSection.kt      # 橘子时钟
    │   ├── DrinkWaterSection.kt  # 喝水提醒
    │   ├── SoundSection.kt       # 四档音量滑块
    │   └── CalibrationSection.kt # 校时 / 主页展示 / 轮子偏移 / OTA
    └── addclock/
        └── AddClockScreen.kt     # 新增 / 编辑 / 喝水闹钟

BLE protocol

Every opcode and packet layout from the original MiniProgram is kept byte-for-byte in ble/Opcodes.kt and ble/BleCodec.kt. Swap FakeBleManager for a real BluetoothGatt-backed implementation and the UI keeps working unchanged.

Opcode Purpose Payload
0 Set volume byte channel + byte 0..100
2 Sync time uint32 epoch (LE)
5 Add / update alarm 12-byte alarm struct
6 Delete alarm uint32 alarmSn
8 Wheel offset int8 left + int8 right
9 / 10 Enter / exit production
11 Close connection
12 Factory reset
13 Wipe a flap page byte page
34/35/37 OTA header/chunk/commit see BleManager.startOta

Building

cd android
./gradlew :app:assembleDebug          # produces app/build/outputs/apk/debug/app-debug.apk
./gradlew :app:installDebug           # deploy to connected device / emulator

Or open the android/ folder in Android Studio and hit ▶.

What's still TODO

  • Real BLE scan/connect/GATT pipeline (BleManager implementation against BluetoothLeScanner / BluetoothGatt).
  • OTA end-to-end wiring on the home screen (the codec is in place).
  • DrinkWater "enable" switch + interval picker round-trip.
  • Persist user preferences (DataStore) so state survives device disconnects.
  • Runtime permission prompts for BLUETOOTH_SCAN / BLUETOOTH_CONNECT.

The UI, theming, data models, and protocol encoders are complete and verified against the original MiniProgram source.

About

Self make control for 时光流响 FlipClock

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages