@rubytech/create-maxy 1.0.783 → 1.0.785

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": "@rubytech/create-maxy",
3
- "version": "1.0.783",
3
+ "version": "1.0.785",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy": "./dist/index.js"
@@ -291,13 +291,13 @@ function portalHTML() {
291
291
  <div class="card" style="padding:32px 16px">
292
292
  <div class="success-icon">&#10003;</div>
293
293
  <h1>Connected!</h1>
294
- <p class="hint">${escapedBrandName} is now online. Redirecting in <span id="redirect-countdown">20</span>s…</p>
294
+ <p class="hint">${escapedBrandName} is now online. Redirecting in <span id="redirect-countdown">15</span>s…</p>
295
295
  <div class="address-box">
296
296
  <a id="device-link" href="#"></a>
297
297
  </div>
298
- <p class="hint" id="ip-fallback" style="display:none">If the page above doesn't load (some Android browsers don't resolve <code>.local</code>), use this direct IP:</p>
299
- <div class="address-box" id="ip-fallback-box" style="display:none">
300
- <a id="device-link-ip" href="#"></a>
298
+ <p class="hint" id="manual-hint" style="display:none">If your phone doesn't redirect automatically, open this in your normal browser:</p>
299
+ <div class="address-box" id="manual-box" style="display:none">
300
+ <span id="device-link-text" style="user-select:all"></span>
301
301
  </div>
302
302
  <p class="hint">This access point will close shortly.<br>Your phone will reconnect to your WiFi automatically.</p>
303
303
  </div>
@@ -419,37 +419,44 @@ function portalHTML() {
419
419
  ? "http://" + data.hostname + ".local" + devicePort
420
420
  : null;
421
421
  var ipAddr = data.ip ? "http://" + data.ip + devicePort : null;
422
- // Display: prefer the friendly .local URL.
423
- // Auto-redirect target: the raw IP. On Android (notably Brave) the
424
- // mDNS .local lookup fails and the auto-navigate would dead-end;
425
- // the IP works on every platform.
426
- var displayAddr = hostnameAddr || ipAddr;
422
+ // Auto-navigate target: prefer the IP because mDNS .local resolution
423
+ // is flaky on Android (notably Brave) and the redirect dead-ends.
424
+ // The displayed link uses the same URL so what the user sees is what
425
+ // they get if they tap.
427
426
  var redirectAddr = ipAddr || hostnameAddr;
428
427
  var link = document.getElementById("device-link");
429
- link.href = displayAddr;
430
- link.textContent = displayAddr;
431
- if (hostnameAddr && ipAddr && hostnameAddr !== ipAddr) {
432
- var ipLink = document.getElementById("device-link-ip");
433
- ipLink.href = ipAddr;
434
- ipLink.textContent = ipAddr;
435
- document.getElementById("ip-fallback").style.display = "block";
436
- document.getElementById("ip-fallback-box").style.display = "block";
428
+ link.href = redirectAddr;
429
+ link.textContent = redirectAddr;
430
+ // Always surface a manual fallback line captive webviews on some
431
+ // phone OSes silently swallow JS navigation, and the user needs to
432
+ // be able to copy-paste the URL into a real browser.
433
+ var manualText = document.getElementById("device-link-text");
434
+ if (manualText) {
435
+ manualText.textContent = redirectAddr;
436
+ document.getElementById("manual-hint").style.display = "block";
437
+ document.getElementById("manual-box").style.display = "block";
437
438
  }
438
439
  showScreen("success-screen");
439
- // Countdown timing: the Pi keeps the AP up for ~10s after writing the
440
- // success result (so this poll can land), then tears it down. The
441
- // phone then needs ~5s to drop the AP SSID and auto-rejoin its home
442
- // WiFi. A 20s countdown crosses both gates so the redirect lands
443
- // when the phone is back on its home network and the device is
444
- // routable on its new IP.
445
- var remaining = 20;
440
+ // 15s countdown: the Pi keeps the AP up for ~10s after writing the
441
+ // success result so this poll can land, then tears it down; the
442
+ // phone then needs ~5s to drop the AP SSID and rejoin home WiFi.
443
+ var remaining = 15;
446
444
  var countdownEl = document.getElementById("redirect-countdown");
447
445
  var ticker = setInterval(function() {
448
446
  remaining -= 1;
449
447
  if (countdownEl) countdownEl.textContent = String(remaining);
450
448
  if (remaining <= 0) {
451
449
  clearInterval(ticker);
452
- window.location.href = redirectAddr;
450
+ // Try multiple navigation primitives — captive webviews on some
451
+ // platforms ignore one but accept another.
452
+ try { window.location.replace(redirectAddr); } catch(e) {}
453
+ try { window.location.href = redirectAddr; } catch(e) {}
454
+ // Last-resort: synthesise a click on a freshly-built anchor.
455
+ try {
456
+ var a = document.createElement("a");
457
+ a.href = redirectAddr; a.rel = "noopener";
458
+ document.body.appendChild(a); a.click();
459
+ } catch(e) {}
453
460
  }
454
461
  }, 1000);
455
462
  }
@@ -40,15 +40,21 @@ PLATFORM_ROOT="${MAXY_PLATFORM_ROOT:-$(dirname "$SCRIPT_DIR")}"
40
40
  BRAND_JSON="${PLATFORM_ROOT}/config/brand.json"
41
41
  CONFIG_DIR=".maxy"
42
42
  PRODUCT_NAME="Maxy"
43
- HOSTNAME_NAME="maxy"
44
43
  if [ -f "$BRAND_JSON" ] && command -v jq >/dev/null 2>&1; then
45
44
  _dir=$(jq -r '.configDir // empty' "$BRAND_JSON" 2>/dev/null) || true
46
45
  [ -n "$_dir" ] && CONFIG_DIR="$_dir"
47
46
  _name=$(jq -r '.productName // empty' "$BRAND_JSON" 2>/dev/null) || true
48
47
  [ -n "$_name" ] && PRODUCT_NAME="$_name"
49
- _host=$(jq -r '.hostname // empty' "$BRAND_JSON" 2>/dev/null) || true
50
- [ -n "$_host" ] && HOSTNAME_NAME="$_host"
51
48
  fi
49
+ # HOSTNAME_NAME must be the **actual system hostname** (the name Avahi
50
+ # advertises and the post-connect URL must use), not the brand default
51
+ # from brand.json. The operator's --hostname flag rewrites the system
52
+ # hostname but never touches brand.json's hostname field, so reading
53
+ # from the brand mis-routed the captive portal's success URL to a name
54
+ # that doesn't resolve. `hostname -s` is the canonical answer Avahi
55
+ # itself follows when avahi-daemon.conf has `host-name` left empty,
56
+ # so this is the same source of truth.
57
+ HOSTNAME_NAME="$(hostname -s 2>/dev/null || hostname 2>/dev/null || echo maxy)"
52
58
 
53
59
  # Determine the home directory of the installing user. The service runs as
54
60
  # root, but logs and config belong to the user who installed the platform.