personal memory agent
0

Configure Feed

Select the types of activity you want to include in your feed.

fix(network): unpin the pair modal from the chat bar and cap the glasses QR

Constrain `.link-modal` to the band between the facet bar and chat bar and let `.link-modal-box` scroll internally, so `#link-pair-cancel` is no longer painted under the fixed chat bar.

Cap the `is-glasses` QR at `min(100%, 360px)` instead of `100%`, so the modal no longer overflows the viewport.

Add `DEVICE_LABEL_PLACEHOLDER_COMPUTER` and set the `#link-device-label` placeholder from the selected presentation mode in `setPairCopy()`. The placeholder seam runs before a pair request exists because `setPresentationMode()` calls `setPairCopy()` ahead of `renderPairPresentation()` and its `!currentPair` guard.

Co-Authored-By: OpenAI Codex <codex@openai.com>

+73 -5
+1
solstone/apps/network/copy.py
··· 27 27 ) 28 28 DEVICE_LABEL_FIELD_LABEL = "name this device" 29 29 DEVICE_LABEL_PLACEHOLDER = "e.g. my iPhone" 30 + DEVICE_LABEL_PLACEHOLDER_COMPUTER = "e.g. my laptop" 30 31 DEVICE_LABEL_DEFAULT_FORMAT = "device — added {month} {day}" 31 32 PAIR_LINK_FIELD_LABEL = "pairing link" 32 33 PAIR_LINK_COPY_LABEL = "copy link"
+1
solstone/apps/network/tests/test_copy.py
··· 27 27 ) 28 28 assert copy.DEVICE_LABEL_FIELD_LABEL == "name this device" 29 29 assert copy.DEVICE_LABEL_PLACEHOLDER == "e.g. my iPhone" 30 + assert copy.DEVICE_LABEL_PLACEHOLDER_COMPUTER == "e.g. my laptop" 30 31 assert copy.DEVICE_LABEL_DEFAULT_FORMAT == "device — added {month} {day}" 31 32 assert copy.EXPIRED_BUTTON == "this code expired — show a new one" 32 33 assert copy.WINDOW_CLOSED_BUTTON == "pairing window closed — open a new one"
+2
solstone/apps/network/tests/test_pair_copy.py
··· 27 27 "SUCCESS_VERIFY_NOTE", 28 28 "SUCCESS_REMOVE_LABEL", 29 29 "DEVICE_LABEL_PLACEHOLDER", 30 + "DEVICE_LABEL_PLACEHOLDER_COMPUTER", 30 31 "HERO_TITLE", 31 32 "HERO_BODY", 32 33 "HERO_HOW_REACH_LABEL", ··· 93 94 ) 94 95 assert copy.SUCCESS_REMOVE_LABEL == "that wasn't me — remove" 95 96 assert copy.DEVICE_LABEL_PLACEHOLDER == "e.g. my iPhone" 97 + assert copy.DEVICE_LABEL_PLACEHOLDER_COMPUTER == "e.g. my laptop" 96 98 assert copy.HERO_TITLE == "let's connect a device" 97 99 assert copy.HERO_BODY == ( 98 100 "your journal lives here, on this device. to read it from your phone or "
+37 -2
solstone/apps/network/tests/test_pair_presentation.py
··· 23 23 return body[start:end] 24 24 25 25 26 + def _rule_body(body: str, start_marker: str) -> str: 27 + start = body.index(start_marker) 28 + end = body.index("}", start) 29 + return body[start:end] 30 + 31 + 26 32 def _link_copy(env) -> dict[str, object]: 27 33 response = env.client.get("/app/network/api/state") 28 34 assert response.status_code == 200 ··· 98 104 ".link-pair-grid.is-glasses .link-pair-qr-cell { grid-row: auto; width: 100%; }" 99 105 in body 100 106 ) 101 - assert ".link-pair-grid.is-glasses .link-qr-container svg," in body 102 - assert "max-width: 100%" in body 107 + base_qr_rule = _rule_body(body, ".link-qr-container svg, .link-qr-container img") 108 + assert "max-width: 260px;" in base_qr_rule 109 + assert "height: auto;" in base_qr_rule 110 + 111 + glasses_svg_selector = ".link-pair-grid.is-glasses .link-qr-container svg," 112 + glasses_img_selector = ".link-pair-grid.is-glasses .link-qr-container img" 113 + assert body.count(glasses_svg_selector) == 1 114 + assert body.count(glasses_img_selector) == 1 115 + glasses_qr_rule = _rule_body(body, glasses_svg_selector) 116 + assert glasses_img_selector in glasses_qr_rule 117 + assert "width: 100%;" in glasses_qr_rule 118 + assert "max-width: min(100%, 360px);" in glasses_qr_rule 119 + assert "height: auto;" in glasses_qr_rule 120 + assert "max-width: 100%;" not in glasses_qr_rule 103 121 assert ".link-pair-grid.is-glasses .link-pair-label-edit" in body 104 122 assert ".link-pair-grid.is-glasses .link-pair-details" in body 105 123 ··· 149 167 assert body.count("deviceLabelInput.value = data.device_label;") == 1 150 168 151 169 170 + def test_pair_copy_seam_sets_mode_aware_device_placeholder(link_env) -> None: 171 + body = _body(link_env) 172 + 173 + set_copy_body = _function_body( 174 + body, 175 + "function setPairCopy()", 176 + "function relativeTime(iso)", 177 + ) 178 + assert "const linkCopy = window.LinkCopy || {};" in set_copy_body 179 + assert "presentationMode === 'computer'" in set_copy_body 180 + assert "linkCopy.DEVICE_LABEL_PLACEHOLDER_COMPUTER" in set_copy_body 181 + assert "linkCopy.DEVICE_LABEL_PLACEHOLDER" in set_copy_body 182 + assert "deviceLabelInput.placeholder = placeholder;" in set_copy_body 183 + assert "deviceLabelInput.value" not in set_copy_body 184 + 185 + 152 186 def test_pair_mode_switch_does_not_request_new_pair_code(link_env) -> None: 153 187 body = _body(link_env) 154 188 ··· 158 192 "function selectedPresentationIndex", 159 193 ) 160 194 assert "presentationMode = mode;" in set_mode_body 195 + assert "setPairCopy();" in set_mode_body 161 196 assert "renderPairPresentation();" in set_mode_body 162 197 assert "requestPairCode" not in set_mode_body 163 198
+1
solstone/apps/network/tests/test_workspace_copy.py
··· 20 20 "CA_FP_LABEL", 21 21 "CA_FP_NOTE", 22 22 "DEVICE_LABEL_PLACEHOLDER", 23 + "DEVICE_LABEL_PLACEHOLDER_COMPUTER", 23 24 "EXPIRED_BUTTON", 24 25 "PAIR_ERROR_BODY", 25 26 "SUCCESS_HEADING",
+20
solstone/apps/network/tests/test_workspace_modals.py
··· 8 8 import re 9 9 10 10 11 + def _rule_body(body: str, start_marker: str) -> str: 12 + start = body.index(start_marker) 13 + end = body.index("}", start) 14 + return body[start:end] 15 + 16 + 11 17 def test_workspace_modals_are_hidden_by_attribute_and_css(link_env): 12 18 env = link_env() 13 19 response = env.client.get("/app/network/workspace") ··· 19 25 assert 'id="link-unpair-modal"' in body 20 26 assert re.search(r'<div id="link-unpair-modal"[^>]{0,200}\bhidden\b', body) 21 27 assert ".link-modal[hidden]" in body 28 + assert body.count(".link-modal-box {") == 2 29 + 30 + modal_rule = _rule_body(body, ".link-modal { position: fixed;") 31 + padding_start = modal_rule.index("padding:") 32 + padding_end = modal_rule.index(";", padding_start) 33 + padding_declaration = modal_rule[padding_start:padding_end] 34 + assert "--facet-bar-height" in padding_declaration 35 + assert "--app-bar-height" in padding_declaration 36 + 37 + full_modal_box_rule = _rule_body(body, ".link-modal-box { background:") 38 + assert "max-height: 100%;" in full_modal_box_rule 39 + assert "overflow-y: auto;" in full_modal_box_rule 40 + 41 + assert ".link-modal-box { max-width: 620px; }" in body
+11 -3
solstone/apps/network/workspace.html
··· 450 450 display: none; 451 451 } 452 452 453 - .link-modal { position: fixed; inset: 0; background: rgba(0,0,0,0.45); display: flex; align-items: center; justify-content: center; z-index: 1000; } 454 - .link-modal-box { background: #fff; border-radius: 10px; padding: 1.5em; max-width: 480px; width: 92%; box-shadow: 0 10px 40px rgba(0,0,0,0.2); } 453 + .link-modal { position: fixed; inset: 0; padding: calc(var(--facet-bar-height) + 12px) 12px calc(var(--app-bar-height) + 80px); background: rgba(0,0,0,0.45); display: flex; align-items: center; justify-content: center; z-index: 1000; } 454 + .link-modal-box { background: #fff; border-radius: 10px; padding: 1.5em; max-width: 480px; max-height: 100%; overflow-y: auto; width: 92%; box-shadow: 0 10px 40px rgba(0,0,0,0.2); } 455 455 .link-modal-box h3 { margin-top: 0; margin-bottom: 1em; } 456 456 .link-present-selector { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin: 0 0 1em; } 457 457 .link-present-selector[hidden] { display: none; } ··· 505 505 .link-pair-grid.is-glasses .link-pair-qr-cell { grid-row: auto; width: 100%; } 506 506 .link-pair-grid.is-glasses .link-qr-container { box-sizing: border-box; width: 100%; justify-content: center; } 507 507 .link-pair-grid.is-glasses .link-qr-container svg, 508 - .link-pair-grid.is-glasses .link-qr-container img { width: 100%; max-width: 100%; height: auto; } 508 + .link-pair-grid.is-glasses .link-qr-container img { width: 100%; max-width: min(100%, 360px); height: auto; } 509 509 .link-pair-grid.is-glasses .link-pair-steps, 510 510 .link-pair-grid.is-glasses #link-pair-network, 511 511 .link-pair-grid.is-glasses .link-pair-label-edit, ··· 708 708 709 709 function setPairCopy() { 710 710 if (pairNetwork) pairNetwork.hidden = false; 711 + if (deviceLabelInput) { 712 + const linkCopy = window.LinkCopy || {}; 713 + const placeholder = presentationMode === 'computer' 714 + ? linkCopy.DEVICE_LABEL_PLACEHOLDER_COMPUTER 715 + : linkCopy.DEVICE_LABEL_PLACEHOLDER; 716 + if (placeholder) deviceLabelInput.placeholder = placeholder; 717 + } 711 718 } 712 719 713 720 function relativeTime(iso) { ··· 1752 1759 1753 1760 function setPresentationMode(mode) { 1754 1761 presentationMode = mode; 1762 + setPairCopy(); 1755 1763 renderPairPresentation(); 1756 1764 } 1757 1765