@trusty-squire/mcp 0.5.4 → 0.5.5

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.
@@ -38,30 +38,44 @@
38
38
  can't tell there's a typeable field, so a normal tap inside the
39
39
  remote Chrome doesn't pop the soft keyboard. This button focuses
40
40
  the hidden #kbInput element below; the OS sees an actual editable
41
- input gain focus and pops the keyboard. Each character the user
42
- types into #kbInput is forwarded to the VNC stream via
43
- rfb.sendKey() and the input is cleared, so the local input
44
- never accumulates the user's password. */
45
- #kb { position: absolute; right: 16px; bottom: 16px; width: 52px; height: 52px;
41
+ input gain focus and pops the keyboard. Each character typed
42
+ into #kbInput is forwarded to the VNC stream via rfb.sendKey()
43
+ and the input is cleared, so the local input never accumulates
44
+ the user's password.
45
+
46
+ Button is positioned 88px above the bottom edge to clear Android
47
+ gesture-navigation zones and iOS home indicators (bottom: 16px
48
+ used to fail on some phones because the tap landed on the OS
49
+ nav instead of the button). 64px target is comfortably above the
50
+ 44pt minimum tap-target size both platforms recommend. */
51
+ #kb { position: absolute; right: 16px; bottom: max(88px, env(safe-area-inset-bottom, 16px));
52
+ width: 64px; height: 64px;
46
53
  border-radius: 50%; border: none; background: #4f46e5; color: #fff;
47
- font-size: 24px; line-height: 1; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
54
+ font-size: 28px; line-height: 1; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
48
55
  cursor: pointer; z-index: 10; display: none;
49
56
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
50
57
  }
51
- #kb:active { transform: scale(0.96); }
58
+ #kb:active { transform: scale(0.94); }
52
59
  /* Only show the button on touch-capable devices — desktops already
53
- have a hardware keyboard and the button just clutters the view. */
60
+ have a hardware keyboard and the button just clutters the view.
61
+ Always-on once the page loads; previously gated on RFB's connect
62
+ event, but if connect fired before the listener attached (or if
63
+ the user was reconnecting), the button stayed hidden forever. */
54
64
  @media (hover: none) and (pointer: coarse) {
55
- #kb.ready { display: flex; align-items: center; justify-content: center; }
65
+ #kb { display: flex; align-items: center; justify-content: center; }
56
66
  }
57
- /* The hidden input the button focuses. Positioned in the viewport
58
- so iOS scrolls to it on focus (off-screen positioning is known to
59
- break focus() on iOS Safari), but visually neutered. */
67
+ /* Hidden input the button focuses. The noVNC-canonical pattern:
68
+ 1×1 px, positioned off-screen, matching foreground+background so
69
+ any flicker is invisible, z-index: -1 so it can't intercept any
70
+ tap. iOS Safari refuses to pop the soft keyboard for an element
71
+ it considers "invisible" — opacity:0 is one of those triggers —
72
+ but a 1px element positioned off-screen counts as visible enough. */
60
73
  #kbInput {
61
- position: absolute; right: 16px; bottom: 16px; width: 52px; height: 52px;
62
- opacity: 0; pointer-events: none; border: none; padding: 0; margin: 0;
63
- caret-color: transparent; background: transparent; color: transparent;
64
- z-index: 5;
74
+ position: absolute; left: -40px; top: 0;
75
+ width: 1px; height: 1px;
76
+ background: #fff; color: #fff; caret-color: transparent;
77
+ border: 0; padding: 0; margin: 0;
78
+ z-index: -1;
65
79
  }
66
80
  </style>
67
81
  </head>
@@ -114,11 +128,6 @@
114
128
  rfb.addEventListener("connect", () => {
115
129
  dot.className = "ok";
116
130
  msg.style.display = "none";
117
- // Reveal the soft-keyboard button (CSS gates it to touch
118
- // devices via the pointer:coarse media query). Connection
119
- // success is the right moment — earlier and the button would
120
- // suggest a typing target that isn't connected yet.
121
- kbBtn.classList.add("ready");
122
131
  });
123
132
  rfb.addEventListener("disconnect", () => {
124
133
  dot.className = "err";
@@ -126,7 +135,6 @@
126
135
  msg.textContent =
127
136
  "Login window closed. If you finished signing in, return to " +
128
137
  "your terminal — you can close this tab.";
129
- kbBtn.classList.remove("ready");
130
138
  });
131
139
  rfb.addEventListener("securityfailure", () => {
132
140
  dot.className = "err";
@@ -134,14 +142,17 @@
134
142
  msg.textContent = "Could not authenticate to the login window.";
135
143
  });
136
144
 
137
- // Tap → kbInput.focus() inside the click handler so the focus
138
- // happens synchronously in response to a user gesture. iOS /
139
- // Android browsers won't pop the soft keyboard for a programmatic
140
- // focus outside a gesture, so this MUST stay inline. Focusing
141
- // a real <input> is what triggers the OS keyboard — focusing
142
- // the RFB div (rfb.focus() in noVNC 1.x) wouldn't.
145
+ // Tap → soft keyboard pop. The blur+focus dance is the load-
146
+ // bearing trick: focus() on an already-focused element is a
147
+ // no-op and the OS won't re-trigger the keyboard, but blur first
148
+ // forces a fresh focus event. The whole sequence stays inside
149
+ // the click handler so iOS Safari and Android Chrome both
150
+ // accept the focus() as gesture-bound. Focusing a real <input>
151
+ // is what triggers the OS keyboard — focusing the RFB div
152
+ // (rfb.focus() in noVNC 1.x) wouldn't.
143
153
  kbBtn.addEventListener("click", (e) => {
144
154
  e.preventDefault();
155
+ kbInput.blur();
145
156
  kbInput.value = "";
146
157
  kbInput.focus();
147
158
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trusty-squire/mcp",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "type": "module",
5
5
  "description": "Local MCP server vibe coding agents install. Thin relay to the Trusty Squire API, with the bundled universal signup bot.",
6
6
  "main": "./dist/server.js",