@livx.cc/appwrap 0.39.1 → 0.39.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livx.cc/appwrap",
3
- "version": "0.39.1",
3
+ "version": "0.39.3",
4
4
  "description": "Wrap any PWA into a native app with native capabilities (appwrap runtime + @livx.cc/native-kit).",
5
5
  "license": "MIT",
6
6
  "author": "Elya Livshitz",
@@ -256,8 +256,12 @@ export function registerAndroidHandlers(): void {
256
256
  let motionListener: android.hardware.SensorEventListener | null = null;
257
257
  const lastMotion = { ax: 0, ay: 0, az: 0, rx: 0, ry: 0, rz: 0 };
258
258
 
259
- bridge.register('motion.start', () => {
259
+ bridge.register('motion.start', (p: { hz?: number } = {}) => {
260
260
  if (motionListener) return; // already streaming
261
+ // Emit rate configurable (default 10 Hz; up to 60 for crisp tilt). SENSOR_DELAY_GAME feeds ~50 Hz;
262
+ // we throttle the EMIT to the requested rate. Higher Hz = more bridge traffic/battery.
263
+ const hz = Math.max(5, Math.min(60, p.hz || 10));
264
+ const minMs = 1000 / hz;
261
265
  const sm = sensorManager();
262
266
  const accel = sm.getDefaultSensor(android.hardware.Sensor.TYPE_ACCELEROMETER);
263
267
  if (!accel) throw err('UNSUPPORTED', 'No accelerometer on this device');
@@ -274,12 +278,13 @@ export function registerAndroidHandlers(): void {
274
278
  lastMotion.rx = v[0]; lastMotion.ry = v[1]; lastMotion.rz = v[2];
275
279
  }
276
280
  const now = java.lang.System.currentTimeMillis();
277
- if (now - last < 100) return; // ~10Hz, matches iOS
281
+ if (now - last < minMs) return; // throttle emit to the requested Hz
278
282
  last = now;
279
283
  bridge.emit('motion.data', { ...lastMotion });
280
284
  },
281
285
  });
282
- const RATE = android.hardware.SensorManager.SENSOR_DELAY_GAME;
286
+ const RATE = hz > 30 ? android.hardware.SensorManager.SENSOR_DELAY_FASTEST
287
+ : android.hardware.SensorManager.SENSOR_DELAY_GAME;
283
288
  sm.registerListener(motionListener, accel, RATE);
284
289
  if (gyro) sm.registerListener(motionListener, gyro, RATE);
285
290
  });
@@ -172,13 +172,18 @@ export function registerParityHandlers(): void {
172
172
  let motionManager: CMMotionManager | null = null;
173
173
  let motionTimer: ReturnType<typeof setInterval> | null = null;
174
174
 
175
- bridge.register('motion.start', () => {
175
+ bridge.register('motion.start', (p: { hz?: number } = {}) => {
176
176
  if (!isIOS) throw iosOnly();
177
177
  if (motionManager) return;
178
+ // Emit rate is configurable (default 10 Hz; games can ask up to 60 for crisp tilt). Both the JS
179
+ // poll cadence AND the CoreMotion sample interval are set — the poll is the actual emit rate, so
180
+ // bumping deviceMotionUpdateInterval alone wouldn't help. Higher Hz = more bridge traffic/battery.
181
+ const hz = Math.max(5, Math.min(60, p.hz || 10));
182
+ const ms = 1000 / hz;
178
183
  const mm = CMMotionManager.new();
179
184
  if (!mm.deviceMotionAvailable) throw err('UNSUPPORTED', 'No motion sensors (simulator?)');
180
185
  motionManager = mm;
181
- mm.deviceMotionUpdateInterval = 0.1;
186
+ mm.deviceMotionUpdateInterval = ms / 1000;
182
187
  mm.startDeviceMotionUpdates();
183
188
  const G = 9.81; // CoreMotion reports in g — kit contract is m/s²
184
189
  motionTimer = setInterval(() => {
@@ -192,7 +197,7 @@ export function registerParityHandlers(): void {
192
197
  ry: m.rotationRate.y,
193
198
  rz: m.rotationRate.z,
194
199
  });
195
- }, 100);
200
+ }, ms);
196
201
  });
197
202
 
198
203
  bridge.register('motion.stop', () => {
@@ -13,16 +13,18 @@ on:
13
13
  push:
14
14
  tags: ['v*']
15
15
 
16
- # Monotonic store build number (Android versionCode). appwrap CLI reads APPWRAP_BUILD_NUMBER over the
17
- # constant derived default — Play rejects a versionCode it has already seen. run_number is increasing.
18
- env:
19
- APPWRAP_BUILD_NUMBER: ${{ github.run_number + 100 }}
16
+ # Monotonic store build number (Android versionCode): computed in the shell below — GitHub Actions
17
+ # expressions have NO arithmetic operators, so `${{ github.run_number + 100 }}` is an INVALID workflow
18
+ # expression → startup_failure on EVERY push (not just tags). appwrap CLI reads APPWRAP_BUILD_NUMBER
19
+ # over the constant derived default — Play rejects a versionCode it has already seen. run_number is increasing.
20
20
 
21
21
  jobs:
22
22
  play:
23
23
  runs-on: ubuntu-latest
24
24
  steps:
25
25
  - uses: actions/checkout@v5
26
+ - name: Build number (run_number + 100 — arithmetic must be done in the shell, not an expression)
27
+ run: echo "APPWRAP_BUILD_NUMBER=$(( ${{ github.run_number }} + 100 ))" >> "$GITHUB_ENV"
26
28
  - uses: oven-sh/setup-bun@v2
27
29
  - uses: actions/setup-node@v5
28
30
  with: { node-version: 22 }
@@ -14,17 +14,19 @@ on:
14
14
  push:
15
15
  tags: ['v*']
16
16
 
17
- # Monotonic store build number (CFBundleVersion). The appwrap CLI reads APPWRAP_BUILD_NUMBER and it wins
18
- # over the (constant-per-version) derived default — without this, repeat uploads of the same marketing
19
- # version 409 ("build already exists"). run_number is strictly increasing; +100 clears low derived values.
20
- env:
21
- APPWRAP_BUILD_NUMBER: ${{ github.run_number + 100 }}
17
+ # Monotonic store build number (CFBundleVersion): computed in the shell below — GitHub Actions
18
+ # expressions have NO arithmetic operators, so `${{ github.run_number + 100 }}` is an INVALID workflow
19
+ # expression → startup_failure on EVERY push (not just tags). run_number is strictly increasing; +100
20
+ # clears low derived values. The appwrap CLI reads APPWRAP_BUILD_NUMBER and it wins over the derived
21
+ # default — without it, repeat uploads of the same marketing version 409 ("build already exists").
22
22
 
23
23
  jobs:
24
24
  testflight:
25
25
  runs-on: macos-15
26
26
  steps:
27
27
  - uses: actions/checkout@v5
28
+ - name: Build number (run_number + 100 — arithmetic must be done in the shell, not an expression)
29
+ run: echo "APPWRAP_BUILD_NUMBER=$(( ${{ github.run_number }} + 100 ))" >> "$GITHUB_ENV"
28
30
  # Apple requires the iOS 26 SDK (Xcode 26+) for uploads — runners may default to older Xcode.
29
31
  - uses: maxim-lobanov/setup-xcode@v1
30
32
  with: { xcode-version: latest-stable }