d42786d0c7
PLAN.md (AI requirements doc) converted to README.md (human-facing project overview with feature status table). CLAUDE.md added for Claude Code with commands, architecture, and key conventions. DEVELOPMENT.md covers first-time setup, per-component build commands, hot-reload guidance, and ADB bundling notes. TODO.md tracks implementation status across all phases.
238 lines
7.3 KiB
Markdown
238 lines
7.3 KiB
Markdown
# DroidScope — Development Guide
|
|
|
|
## Prerequisites
|
|
|
|
| Tool | Version | Install |
|
|
|---|---|---|
|
|
| Go | 1.23+ | https://go.dev/dl |
|
|
| Node.js | 20+ | https://nodejs.org |
|
|
| Wails CLI | v2 | `go install github.com/wailsapp/wails/v2/cmd/wails@latest` |
|
|
| Git | any | — |
|
|
|
|
> **macOS only:** Wails requires Xcode Command Line Tools — `xcode-select --install`
|
|
>
|
|
> **Linux only:** Wails requires `libgtk-3-dev libwebkit2gtk-4.0-dev` (Debian/Ubuntu) or equivalent.
|
|
>
|
|
> **Windows only:** Wails requires WebView2 (ships with Windows 11, otherwise install from Microsoft).
|
|
|
|
---
|
|
|
|
## First-time Setup
|
|
|
|
```bash
|
|
# 1. Install frontend dependencies
|
|
cd frontend-react
|
|
npm install
|
|
|
|
# 2. (Optional) Download bundled ADB binaries for distribution builds
|
|
# Skip this for local dev — the app falls back to your system ADB
|
|
bash scripts/download-adb.sh
|
|
|
|
# 3. Make sure your system ADB is accessible for local dev
|
|
# Either via ANDROID_HOME or PATH:
|
|
export ANDROID_HOME=~/Library/Android/sdk # macOS example
|
|
# or: ensure `adb` is on your PATH
|
|
```
|
|
|
|
---
|
|
|
|
## Running in Development
|
|
|
|
```bash
|
|
bash scripts/dev.sh
|
|
```
|
|
|
|
**What `dev.sh` does, in order:**
|
|
|
|
| Step | Command | What it checks |
|
|
|---|---|---|
|
|
| 1 | `go build ./...` in `backend-go/` | Backend packages compile without errors |
|
|
| 2 | `go build ./...` in `desktop/` | Desktop Go code (app.go, main.go, embeds) compiles |
|
|
| 3 | `wails generate module` in `desktop/` | Regenerates `frontend-react/src/wailsjs/` from current `app.go` bindings |
|
|
| 4 | `npm install` + `tsc -b --noEmit` in `frontend-react/` | Installs any new deps, type-checks TypeScript |
|
|
| — | `wails dev` in `desktop/` | Starts the desktop app with hot reload |
|
|
|
|
If any step fails the script exits immediately (due to `set -e`) — fix the error and re-run.
|
|
|
|
**What happens once running:**
|
|
- Wails compiles the Go backend and opens a native desktop window
|
|
- Wails starts the Vite dev server (`npm run dev` in `frontend-react/`)
|
|
- React/TS changes hot-reload instantly without restarting
|
|
- Go changes (in `app.go`, `backend-go/`) require re-running `dev.sh`
|
|
|
|
> **When to re-run `dev.sh` vs just saving a file:**
|
|
> - Edited only `.tsx` / `.ts` / `.css` → Vite hot-reloads automatically, no restart needed
|
|
> - Edited `app.go` (added/changed a bound method) → re-run `dev.sh` to rebuild Go + regenerate bindings
|
|
> - Edited anything under `backend-go/` → re-run `dev.sh` to rebuild
|
|
|
|
**Frontend only** (browser preview, no Wails bindings):
|
|
|
|
```bash
|
|
cd frontend-react
|
|
npm run dev
|
|
# → http://localhost:5173
|
|
```
|
|
|
|
> Wails bindings (`ListDevices`, `GetDeviceInfo`, etc.) are no-ops in plain browser mode — they only work inside the Wails desktop window.
|
|
|
|
---
|
|
|
|
## Building for Production
|
|
|
|
### Full desktop app (recommended)
|
|
|
|
```bash
|
|
bash scripts/build.sh
|
|
```
|
|
|
|
Or manually:
|
|
|
|
```bash
|
|
# Step 1 — build frontend (outputs to desktop/frontend/dist/)
|
|
cd frontend-react
|
|
npm run build
|
|
|
|
# Step 2 — build desktop binary (embeds frontend dist + ADB binaries)
|
|
cd desktop
|
|
export PATH="$PATH:$(go env GOPATH)/bin"
|
|
wails build
|
|
```
|
|
|
|
Output: `desktop/build/bin/DroidScope` (macOS/Linux) or `desktop/build/bin/DroidScope.exe` (Windows)
|
|
|
|
---
|
|
|
|
### Backend only
|
|
|
|
```bash
|
|
cd backend-go
|
|
go build ./...
|
|
```
|
|
|
|
---
|
|
|
|
### Frontend only (static bundle)
|
|
|
|
```bash
|
|
cd frontend-react
|
|
npm run build
|
|
# Output: desktop/frontend/dist/
|
|
```
|
|
|
|
---
|
|
|
|
### Android SDK
|
|
|
|
```bash
|
|
cd android-sdk
|
|
./gradlew :sdk:assembleDebug # debug AAR
|
|
./gradlew :sdk:assembleRelease # release AAR
|
|
# Output: android-sdk/sdk/build/outputs/aar/
|
|
```
|
|
|
|
---
|
|
|
|
## Type Checking (no build)
|
|
|
|
```bash
|
|
# TypeScript
|
|
cd frontend-react
|
|
npx tsc -b --noEmit
|
|
|
|
# Go
|
|
cd backend-go && go build ./...
|
|
cd desktop && go build ./...
|
|
```
|
|
|
|
---
|
|
|
|
## Regenerating Wails JS Bindings
|
|
|
|
Run this after adding or changing any exported method on `App` in `desktop/app.go`:
|
|
|
|
```bash
|
|
cd desktop
|
|
export PATH="$PATH:$(go env GOPATH)/bin"
|
|
wails generate module
|
|
# Output: frontend-react/src/wailsjs/
|
|
```
|
|
|
|
---
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
DroidScope/
|
|
├── desktop/ ← Wails app (Go entry point)
|
|
│ ├── app.go ← Wails-bound methods (called from frontend)
|
|
│ ├── main.go ← App bootstrap
|
|
│ ├── wails.json ← Wails config (frontend dir, dev server)
|
|
│ └── internal/adbembed/ ← ADB binary embedding + runtime extraction
|
|
│
|
|
├── backend-go/ ← Go backend packages
|
|
│ ├── adb/ ← ADB command wrapper
|
|
│ ├── device/ ← Device manager + DeviceInfo fetcher
|
|
│ ├── logcat/ ← (stub) Logcat streaming
|
|
│ ├── network/ ← (stub) Network inspector
|
|
│ ├── storage/ ← (stub) SharedPrefs, SQLite, files
|
|
│ ├── runtime/ ← (stub) Runtime config override
|
|
│ ├── session/ ← (stub) Session management
|
|
│ └── protocol/ ← Shared event types (Go structs)
|
|
│
|
|
├── frontend-react/ ← Vite + React + TypeScript
|
|
│ ├── src/
|
|
│ │ ├── wailsjs/ ← Auto-generated Wails bindings (do not edit)
|
|
│ │ ├── features/ ← Feature modules (devices, logcat, network…)
|
|
│ │ ├── components/ ← Shared UI components (layout, shadcn/ui)
|
|
│ │ ├── hooks/ ← Shared hooks (useActiveDevice)
|
|
│ │ ├── store/ ← Zustand global state
|
|
│ │ └── types/ ← Shared TypeScript types (protocol)
|
|
│ └── vite.config.ts ← Build outputs to ../desktop/frontend/dist/
|
|
│
|
|
├── android-sdk/ ← Kotlin Android SDK (Gradle)
|
|
│ └── sdk/src/main/kotlin/dev/achmad/droidscope/
|
|
│
|
|
├── scripts/
|
|
│ ├── dev.sh ← Start full dev environment
|
|
│ ├── build.sh ← Production build
|
|
│ └── download-adb.sh ← Download ADB binaries for bundling
|
|
│
|
|
├── go.work ← Go workspace (links desktop + backend-go)
|
|
├── README.md ← Project overview and feature roadmap
|
|
├── TODO.md ← Implementation status
|
|
└── DEVELOPMENT.md ← This file
|
|
```
|
|
|
|
---
|
|
|
|
## Key Conventions
|
|
|
|
### Adding a new Go method callable from the frontend
|
|
|
|
1. Add the method to `desktop/app.go` (must be exported, receiver `*App`)
|
|
2. Run `wails generate module` from `desktop/`
|
|
3. Import from `@/wailsjs/go/main/App` in React
|
|
|
|
### Adding a new backend-go package
|
|
|
|
1. Create the package under `backend-go/`
|
|
2. The `go.work` workspace + `replace` directive in `desktop/go.mod` handle local resolution — no publishing needed
|
|
|
|
### Active device scoping (all features)
|
|
|
|
- Import `useActiveDevice` from `@/hooks/use-active-device`
|
|
- Check `isMonitoring` before starting streams or polls
|
|
- Store per-device data in `deviceCache` via `patchDeviceCache(deviceId, data)` — never cleared on device switch
|
|
- Show `<NoDeviceSelected />` when `!isMonitoring`
|
|
|
|
---
|
|
|
|
## ADB Binary Bundling
|
|
|
|
For **local development** the app resolves ADB in this order:
|
|
1. Embedded binary in `desktop/internal/adbembed/bin/` (empty until `download-adb.sh` is run)
|
|
2. `$ANDROID_HOME/platform-tools/adb`
|
|
3. `adb` on `$PATH`
|
|
|
|
For **distribution builds** run `scripts/download-adb.sh` once before `wails build` to embed ADB for all platforms.
|