feat(android): add capacitor wrapper project

This commit is contained in:
DeskClaw Bot
2026-04-21 16:15:22 +00:00
Unverified
parent 3075310961
commit 60432833f2
5 changed files with 105 additions and 0 deletions

11
.gitignore vendored
View File

@@ -53,6 +53,7 @@ test-results/
*.AppImage *.AppImage
*.deb *.deb
*.rpm *.rpm
*.apk
resources/bin resources/bin
@@ -88,3 +89,13 @@ artifacts/**
!artifacts/releases/**/*.AppImage !artifacts/releases/**/*.AppImage
!artifacts/releases/**/*.deb !artifacts/releases/**/*.deb
!artifacts/releases/**/*.rpm !artifacts/releases/**/*.rpm
# Allow committing release binaries when explicitly staged under installers/.
!installers/
installers/**
!installers/**/*.exe
!installers/**/*.apk
!installers/**/*.aab
!installers/**/*.zip
!installers/**/*.yml
!installers/**/*.blockmap

18
mobile/README.md Normal file
View File

@@ -0,0 +1,18 @@
# DeskClaw Android (APK)
This is a Capacitor wrapper around the DeskClaw web UI.
It produces an APK that bundles the UI for offline rendering. It does not embed the full Electron main-process features.
## Build (Debug APK)
```bash
cd mobile
pnpm run web:build
pnpm run web:sync
pnpm install
pnpm exec cap sync android
cd android
./gradlew assembleDebug
```

View File

@@ -0,0 +1,14 @@
import type { CapacitorConfig } from '@capacitor/cli'
const config: CapacitorConfig = {
appId: 'dev.deskclaw.app',
appName: 'DeskClaw',
webDir: 'www',
bundledWebRuntime: false,
server: {
androidScheme: 'https',
},
}
export default config

24
mobile/package.json Normal file
View File

@@ -0,0 +1,24 @@
{
"name": "deskclaw-mobile",
"private": true,
"version": "0.0.0",
"type": "module",
"packageManager": "pnpm@10.31.0",
"scripts": {
"web:build": "cd .. && pnpm run build:vite",
"web:sync": "node scripts/sync-web.mjs",
"android:init": "pnpm install && pnpm exec cap init DeskClaw dev.deskclaw.app --web-dir=www --npm-client=pnpm",
"android:add": "pnpm exec cap add android",
"android:sync": "pnpm exec cap sync android",
"android:apk:debug": "cd android && ./gradlew assembleDebug",
"android:apk:release": "cd android && ./gradlew assembleRelease"
},
"dependencies": {
"@capacitor/android": "^7.4.3",
"@capacitor/core": "^7.4.3"
},
"devDependencies": {
"@capacitor/cli": "^7.4.3"
}
}

View File

@@ -0,0 +1,38 @@
import { mkdir, readdir, rm, copyFile, stat } from 'node:fs/promises'
import { join, resolve } from 'node:path'
async function copyDir(srcDir, dstDir) {
await mkdir(dstDir, { recursive: true })
const entries = await readdir(srcDir, { withFileTypes: true })
for (const entry of entries) {
const src = join(srcDir, entry.name)
const dst = join(dstDir, entry.name)
if (entry.isDirectory()) {
await copyDir(src, dst)
continue
}
if (entry.isFile()) {
await copyFile(src, dst)
}
}
}
async function main() {
const repoRoot = resolve(process.cwd(), '..')
const fromDir = join(repoRoot, 'dist')
const toDir = resolve(process.cwd(), 'www')
const st = await stat(fromDir).catch(() => null)
if (!st || !st.isDirectory()) {
throw new Error(`Missing dist/ at ${fromDir}. Run: pnpm -C .. run build:vite`)
}
await rm(toDir, { recursive: true, force: true })
await copyDir(fromDir, toDir)
}
main().catch((err) => {
console.error(err)
process.exit(1)
})