Skip to content

Commit 056650f

Browse files
committed
whattheduck: Fix local config, fix camera container background color
1 parent 5c3d48b commit 056650f

File tree

12 files changed

+151
-17
lines changed

12 files changed

+151
-17
lines changed

apps/whattheduck/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,10 @@
1111
- The DM Web interface
1212
- The DM API
1313
- The native WTD Android app.
14+
15+
### Android dev (WebSocket)
16+
17+
The `dev:android` script loads the app from the dev server (HTTP), so WebSocket connections (`ws://`) work via `server.url` on the same network. Prerequisites:
18+
19+
1. Start the API (e.g. "Debug DM API + WTD Android" compound, or `pnpm dev:whattheduck` in another terminal)
20+
2. Run: `pnpm dev:whattheduck:android` or `pnpm dev:android`
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version='1.0' encoding='utf-8'?>
22
<resources>
3-
<string name="app_name">What The Duck (Debug)</string>
4-
<string name="title_activity_main">What The Duck (Debug)</string>
5-
</resources>
3+
<string name="app_name">_What The Duck</string>
4+
<string name="title_activity_main">_What The Duck</string>
5+
</resources>

apps/whattheduck/android/app/src/main/assets/capacitor.config.json

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22
"appId": "net.ducksmanager.whattheduck",
33
"appName": "What The Duck",
44
"webDir": "dist",
5+
"server": {
6+
"url": "http://192.168.1.147:8008",
7+
"cleartext": true,
8+
"androidScheme": "http"
9+
},
510
"android": {
6-
"webContentsDebuggingEnabled": true
11+
"webContentsDebuggingEnabled": true,
12+
"allowMixedContent": true
713
},
814
"ios": {
915
"scheme": "What The Duck"
10-
},
11-
"server": {
12-
"url": "http://192.168.1.147:8008"
1316
}
14-
}
17+
}

apps/whattheduck/capacitor.config.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,18 @@ function getLocalIP(): string {
1111
}
1212
}
1313

14-
const isDev = process.env.NODE_ENV === 'local';
14+
const isDev = process.env.NODE_ENV !== 'production';
1515

1616
const config: CapacitorConfig = {
1717
appId: 'net.ducksmanager.whattheduck',
1818
appName: 'What The Duck',
1919
webDir: 'dist',
20-
// Only set server URL in development mode
20+
// Only set server URL in development mode (so cap sync copies it to android)
2121
...(isDev && {
2222
server: {
2323
url: `http://${getLocalIP()}:8008`,
2424
cleartext: true,
25+
androidScheme: 'http',
2526
},
2627
}),
2728
android: {
@@ -30,6 +31,7 @@ const config: CapacitorConfig = {
3031
keystoreAlias: 'whattheduck',
3132
},
3233
webContentsDebuggingEnabled: true,
34+
...(isDev && { allowMixedContent: true }),
3335
},
3436
ios: {
3537
scheme: 'What The Duck',

apps/whattheduck/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
"optimize-splash-images": "bun run scripts/optimize-splash.ts",
1111
"dev": "pnpm cap:update && pnpm dev:server",
1212
"dev:server": "concurrently -n vite,vue-tsc \"vite --port 8008 --host\" \"vue-tsc --noEmit --watch\"",
13-
"dev:android": "pnpm cap:update && pnpm update-android-capacitor-config && concurrently --kill-others-on-fail -n set-android-socket-url,android,dev \"pnpm set-android-socket-url\" \"ionic cap run android --external --target Pixel_3_API_31 --public-host=`ipconfig getifaddr en0`\" \"pnpm dev:server\"",
13+
"dev:android": "bun run scripts/dev-android.ts",
1414
"lint": "eslint --fix .",
15-
"set-android-socket-url": "echo VITE_DM_SOCKET_URL_NATIVE=http://`ipconfig getifaddr en0`:3001 > .env.local",
15+
"set-android-socket-url": "bun run scripts/set-android-socket-url.ts",
1616
"update-android-capacitor-config": "bun run scripts/update-android-capacitor-config.ts",
1717
"build": "vite build && vue-tsc --noEmit && pnpm sentry:sourcemaps && pnpm cleanup-sourcemaps",
1818
"cleanup-sourcemaps": "find dist -name '*.map' -type f -delete",
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env bun
2+
3+
import { execSync } from 'child_process';
4+
import { writeFileSync } from 'fs';
5+
import { join } from 'path';
6+
7+
const API_PORT = 3001;
8+
9+
async function main() {
10+
const scriptDir = join(import.meta.dir, '..');
11+
12+
console.log('Waiting for API on port 3001...');
13+
execSync("pnpm -F '~api' exec wait-on -l tcp:3001", {
14+
cwd: join(scriptDir, '../..'),
15+
stdio: 'inherit',
16+
});
17+
18+
const ip = execSync('ipconfig getifaddr en0', { encoding: 'utf-8' }).trim();
19+
const socketUrl = `http://${ip}:${API_PORT}`;
20+
21+
console.log(`✓ Using socket URL: ${socketUrl}`);
22+
23+
writeFileSync(join(scriptDir, '.env.local'), `VITE_DM_SOCKET_URL_NATIVE=${socketUrl}\n`);
24+
25+
const { spawn } = await import('child_process');
26+
const cmd =
27+
'pnpm cap:update && pnpm update-android-capacitor-config && concurrently --kill-others-on-fail -n android,dev "ionic cap run android --external --target Pixel_3_API_31 --public-host=$(ipconfig getifaddr en0)" "pnpm dev:server"';
28+
const dev = spawn('sh', ['-c', cmd], {
29+
cwd: scriptDir,
30+
stdio: 'inherit',
31+
});
32+
33+
dev.on('exit', (code) => {
34+
process.exit(code ?? 0);
35+
});
36+
}
37+
38+
main().catch((err) => {
39+
console.error('✗', err.message);
40+
process.exit(1);
41+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env bun
2+
3+
import { execSync } from 'child_process';
4+
import { writeFileSync } from 'fs';
5+
import { join } from 'path';
6+
7+
function getFallbackUrl(): string {
8+
const ip = execSync('ipconfig getifaddr en0', { encoding: 'utf-8' }).trim();
9+
return `http://${ip}:3001`;
10+
}
11+
12+
async function main() {
13+
const socketUrl = process.env.DM_SOCKET_URL_NATIVE_HTTPS ?? getFallbackUrl();
14+
15+
const envLocalPath = join(import.meta.dir, '../.env.local');
16+
writeFileSync(envLocalPath, `VITE_DM_SOCKET_URL_NATIVE=${socketUrl}\n`);
17+
}
18+
19+
main().catch((err) => {
20+
console.error('✗', err.message);
21+
process.exit(1);
22+
});

apps/whattheduck/scripts/update-android-capacitor-config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ try {
2929
const config = JSON.parse(readFileSync(androidConfigPath, 'utf-8'));
3030
config.server = {
3131
url: serverUrl,
32+
cleartext: true,
33+
androidScheme: 'http',
3234
};
35+
config.android = { ...config.android, allowMixedContent: true };
3336
writeFileSync(androidConfigPath, JSON.stringify(config, null, '\t') + '\n');
3437
console.log('✓ Android capacitor.config.json updated successfully');
3538
} catch (error) {

apps/whattheduck/src/components/CameraPreviewOverlay.vue

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,27 @@
11
<template>
2+
<div v-if="boundingClientRect" id="camera-bg-overlays" aria-hidden="true">
3+
<div class="camera-bg-overlay camera-bg-top" :style="{ height: `${boundingClientRect.y}px` }" />
4+
<div
5+
class="camera-bg-overlay camera-bg-bottom"
6+
:style="{ top: `${boundingClientRect.y + boundingClientRect.height}px` }"
7+
/>
8+
<div
9+
class="camera-bg-overlay camera-bg-left"
10+
:style="{
11+
top: `${boundingClientRect.y}px`,
12+
width: `${boundingClientRect.x}px`,
13+
height: `${boundingClientRect.height}px`,
14+
}"
15+
/>
16+
<div
17+
class="camera-bg-overlay camera-bg-right"
18+
:style="{
19+
top: `${boundingClientRect.y}px`,
20+
left: `${boundingClientRect.x + boundingClientRect.width}px`,
21+
height: `${boundingClientRect.height}px`,
22+
}"
23+
/>
24+
</div>
225
<div id="camera-preview" ref="cameraPreview"></div>
326
<ion-row id="overlay" ref="overlay" :class="{ portrait: isPortrait, landscape: !isPortrait }">
427
<ion-button ref="takePhotoButton" size="large" :disabled="isSearching" @click="takePhoto()">
@@ -134,6 +157,38 @@ watch([overlayHeight, currentRatioIndex], async () => {
134157
</script>
135158

136159
<style scoped>
160+
#camera-bg-overlays {
161+
position: fixed;
162+
inset: 0;
163+
z-index: 9998;
164+
pointer-events: none;
165+
}
166+
167+
.camera-bg-overlay {
168+
position: absolute;
169+
background: var(--dm-background-color);
170+
}
171+
172+
.camera-bg-top {
173+
top: 0;
174+
left: 0;
175+
right: 0;
176+
}
177+
178+
.camera-bg-bottom {
179+
left: 0;
180+
right: 0;
181+
bottom: 0;
182+
}
183+
184+
.camera-bg-left {
185+
left: 0;
186+
}
187+
188+
.camera-bg-right {
189+
right: 0;
190+
}
191+
137192
#camera-preview,
138193
#overlay {
139194
display: flex;
@@ -161,6 +216,7 @@ watch([overlayHeight, currentRatioIndex], async () => {
161216
}
162217
#overlay {
163218
position: absolute;
219+
background: var(--dm-background-color);
164220
&.portrait {
165221
bottom: 1rem;
166222
height: 4rem;

apps/whattheduck/src/theme/variables.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ $dmConditions: (
1515
--ion-margin: 48px;
1616
--ion-background-color: #303030;
1717
--ion-background-color-rgb: 48,48,48;
18+
/* App background, not overridden when camera preview is active */
19+
--dm-background-color: #303030;
1820

1921
--ion-text-color: #ffffff;
2022
--ion-text-color-rgb: 255,255,255;
@@ -195,6 +197,7 @@ $dmConditions: (
195197
.ios body {
196198
--ion-background-color: #000000;
197199
--ion-background-color-rgb: 0, 0, 0;
200+
--dm-background-color: #000000;
198201

199202
--ion-text-color: white;
200203
--ion-text-color-rgb: 255, 255, 255;
@@ -238,6 +241,7 @@ $dmConditions: (
238241
.md body {
239242
--ion-background-color: #121212;
240243
--ion-background-color-rgb: 18, 18, 18;
244+
--dm-background-color: #121212;
241245

242246
--ion-text-color: white;
243247
--ion-text-color-rgb: 255, 255, 255;

0 commit comments

Comments
 (0)