You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Console: use the mobile shell's pickImage(), openFile() and share() for photo capture, attachments and sharing #29735
Filing category ③: a direct task from a maintainer ruling. objectstack-ai/mobile#147, ruling comment 6593858903: Ruling: batch #1 item 3 · letter A · maintainer 「同意」. Under option A, the Console fetches files with its own session, and the shell never touches the session.
pickImage(opts?: { camera?, maxWidth?, quality? }) resolves { base64, name, mime }, or null on cancel. The image is downscaled before transfer.
openFile({ base64, name, mime }):
The Console downloads the attachment itself, with its own session, and hands over the bytes.
The shell previews or opens the file with the OS.
Limit is 8 MiB. Over the limit, the call is refused with bad_args.
share({ url?, text? }) opens the OS share sheet.
Each method is feature-detected with has('<name>'). Only pages on the configured server's origin can call them.
Ask (Console, ui/)
When the shell exposes pickImage, file and image fields offer a "take photo / choose from library" action through it. <input type=file> stays the fallback.
When the shell exposes openFile, an attachment tap fetches the file with the Console's session, then calls openFile with the bytes. Over 8 MiB, the Console falls back to its current behaviour.
When the shell exposes share, a record or attachment "share" action calls it.
Plain browsers and older shells behave as today.
Business reason
Who benefits: field users who attach photos, open PDFs and share records from a phone.
If not done: the shell methods ship with no caller, which is a declared-but-unused capability.
Read fresh. The Console uses the mobile shell's pickImage / openFile / share when they are present, falling back to the browser path. Maintainer-ruled A (mobile#147). A mobile capability, so p2.
The shell contract is mobile docs/HYBRID-SHELL.md (mobile#180).
Claim: PM loop round 31 · 2026-11-03T04:06Z
Session: session_01QsR2jSqiKZMCzGXQK5xzUq (card thread, os-dev); dispatched by seat session session_01QsR2jV4dWohojjbTJTQq5m
Account: zhuangjianguo
Branch: claude/project-thread-6oh3sk (platform-assigned to the card thread; it can push only this branch)
Worktree: objectstack-issue-29735
Domain: domain:ui
Seat: domain:ui#3
File surface:
The bridge: ui/packages/mobile/src/nativeHost.ts (three optional ObjectStackNative members, pickImage? / openFile? / share?, and their wrappers), its index export and test fake.
The Console call sites: the file / image field components (pickImage), the attachment tap site (openFile), and the record / attachment share action site (share).
Their tests, and one changeset with patches for the touched packages.
The exact files are named in the thread before the first edit, with a split into two PRs proposed if the four legs exceed the size budget (stop on breach; explain in the report).
Container & model: M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
Clause-②: yes
Metadata-protocol: none
Responsibility: open — recorded at review
Thread-read: none
Premise: holds per the card. The shell side is objectstack-ai/mobile#180 (contract in mobile docs/HYBRID-SHELL.md), under the maintainer ruling mobile#147 6593858903, letter A: the Console fetches files with its own session. ObjectStackNative on main carries none of the three methods.
Serial constraints cleared: none in flight on these sites. Seat 2 may take #29750 (native push route), which also edits nativeHost.ts; union-line merges are expected and are no overlap of behaviour.
Claim amended · 2026-11-03T04:11Z · first amendment, on the os-dev's pre-edit site report. This adds to claim 6595193307; session, branch and seat are unchanged.
Clause-②: yes
Metadata-protocol: none
Exact files, one PR (no split):
Bridge: ui/packages/mobile/src/nativeHost.ts (optional pickImage? / openFile? / share?, the method union, the nativePickImage / nativeOpenFile / nativeShare wrappers, the 8 MiB constant), src/index.ts, and the __tests__/nativeHost.test.tsx fake.
pickImage: ui/packages/fields/src/widgets/FileField.tsx and ImageField.tsx, plus a new helper widgets/nativeImagePick.ts. A picked image becomes a File that enters the same upload loop. Two keys (fields.file.choosePhoto, fields.file.photoFailed) go in the ten @object-ui/i18n locale packs.
openFile: ui/packages/app-shell/src/views/RecordAttachmentsPanel.tsx (handleDownload). In the shell, under 8 MiB, it fetches the bytes with the Console's session and calls openFile. Over the cap, on a fetch failure or on bad_args, it keeps today's window.open.
share: ui/packages/app-shell/src/views/RecordDetailView.tsx (the sys_share action). In the shell it calls share({ url, text }); otherwise it keeps today's path.
Their tests and one changeset.
Attachment share: out (option A). No attachment share action exists today. A stable file link needs the Bearer session, and the signed URL is a credential-free download link, so neither may be handed to the OS share sheet. The shell contract names only record links.
Out, noted: the AvatarField and grid FileCell pickers, and the file-field download anchors, keep today's behaviour.
{
"issue": 29735,
"status": "done",
"branch": "claude/project-thread-6oh3sk",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29803",
"head": "b37e3124",
"session": "session_01QsR2jSqiKZMCzGXQK5xzUq",
"premise_still_valid": true,
"summary": "All four legs in one draft PR. @object-ui/mobile gains optional pickImage?/openFile?/share? on ObjectStackNative with nativePickImage/nativeOpenFile/nativeShare wrappers (scan precedent), NATIVE_FILE_MAX_BYTES and two base64 file helpers. FileField and ImageField offer Take photo / Choose photo through the shell when has('pickImage'); the picked File enters the existing upload pipeline (FileField processFiles, ImageField uploadPicked lifted from the input handler). RecordAttachmentsPanel's Download hands fetched bytes (never the signed URL) to openFile in the shell, falling back to window.open over 8 MiB, on fetch failure or any non-ok answer. RecordDetailView sys_share calls share({url, text}) in the shell, else today's path. Attachment share left out per seat ruling A.",
"clause_2": "yes",
"metadata_protocol": "none",
"widening_exports": "@object-ui/mobile entry: nativePickImage, nativeOpenFile, nativeShare, fileFromNativeFile, nativeFileFromBlob, NATIVE_FILE_MAX_BYTES, types NativePickImageOptions, NativeFile, NativeShareContent; ObjectStackNative gains optional pickImage?, openFile?, share?; NativeHostMethod gains three names. @object-ui/i18n: fields.file.choosePhoto, fields.file.photoFailed. Contract review owed (seat routes to director).",
"files_changed": [
".changeset/29735-mobile-shell-files.md",
"ui/packages/app-shell/src/views/RecordAttachmentsPanel.tsx",
"ui/packages/app-shell/src/views/RecordDetailView.favoritesEntry-12427.test.tsx",
"ui/packages/app-shell/src/views/RecordDetailView.tsx",
"ui/packages/app-shell/src/views/__tests__/RecordAttachmentsPanel.test.tsx",
"ui/packages/fields/src/widgets/FileField.tsx",
"ui/packages/fields/src/widgets/ImageField.tsx",
"ui/packages/fields/src/widgets/nativeImagePick.shellPhoto.test.tsx",
"ui/packages/fields/src/widgets/nativeImagePick.ts",
"ui/packages/i18n/src/locales/ar.ts",
"ui/packages/i18n/src/locales/de.ts",
"ui/packages/i18n/src/locales/en.ts",
"ui/packages/i18n/src/locales/es.ts",
"ui/packages/i18n/src/locales/fr.ts",
"ui/packages/i18n/src/locales/ja.ts",
"ui/packages/i18n/src/locales/ko.ts",
"ui/packages/i18n/src/locales/pt.ts",
"ui/packages/i18n/src/locales/ru.ts",
"ui/packages/i18n/src/locales/zh.ts",
"ui/packages/mobile/README.md",
"ui/packages/mobile/src/__tests__/nativeHost.test.tsx",
"ui/packages/mobile/src/index.ts",
"ui/packages/mobile/src/nativeHost.ts"
],
"line_budget": "23 files, +871 / -15 vs origin/main 25450217 at b37e3124, under 3000",
"tests": "New/touched at b37e3124: nativeHost.test.tsx 79, nativeImagePick.shellPhoto.test.tsx 12 (new), RecordAttachmentsPanel.test.tsx 37 (6 new in a top-level describe), RecordDetailView.favoritesEntry-12427.test.tsx 7 (4 new in a top-level describe): 135 pass. Sweep at b37e3124 locked, 2 workers: native-shell set + every test naming FileField/ImageField/RecordAttachmentsPanel + packages/i18n/: 153 files, 2831 passed, 13 skipped, 0 failed. Other 99 RecordDetailView*.test.tsx at 3d7a69ca: 619 passed. Ablations at c413ef3c via scripts/ablation-replace.mjs, each restored (blob == HEAD, git diff HEAD empty): bridge share forwards {} 1 red; FileField drops picked files 2 red; ImageField drops picked files 2 red; panel skips openInNativeShell 2 red; Share ignores shell ok 1 red. ui vitest aliases @object-ui/* to src, so no rebuild per leg.",
"gates": "dispatch-gates --commands at b37e3124: 35 derived, all exit 0 (incl. pnpm --dir ui exec vitest run scripts/, check:type-check-debt, check:published-files, check:nul-bytes, check-sdui-manifest, check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity with the PR body as GITHUB_EVENT_PATH); --ran: 35 run, 0 NOT-MEASURED, 0 UNRUN. Same 35 also all exit 0 at 3d7a69ca before the main merge. type-check (turbo) mobile/fields/app-shell/i18n 68/68 exit 0 at b37e3124. eslint on 11 touched files: 0 errors. check-partof-closing-keyword exit 0. CI check-runs: in_progress at report time.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"deviations": [
"ui/packages/mobile/README.md added to the file surface on the seat's word (doc follows export).",
"Shots not taken: the fields harness is cheap but the record Share sheet is native and the record page needs a full backend boot; every leg is driven through the shell fake instead.",
"Session-context asks to assign the PR and request review via GitHub MCP; skipped per common rule 3/10 and os-dev (no MCP writes, no assignees)."
],
"mcp_calls": "0",
"api_writes": "2 — fleet-write relay pr_create (objectstack-ai/objectstack#29803); post-stamped comment on #29735 (this report). Plus git push (not a REST write).",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · noted in PR Acceptance notes, not filed: AvatarField and grid FileCell have no shell picker; file-field download anchors (FileValueAffordance) keep the browser link; plugin-detail DetailView sys_share (not on the Console record page) unchanged."
]
}
{
"issue": 29735,
"status": "done",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29803",
"head": "09666e32",
"previous_head": "b37e3124",
"session": "session_01QsR2jSqiKZMCzGXQK5xzUq",
"summary": "Merged origin/main b62463f1 (PR #29798 app-lock bridge members) into the branch, no rebase, no force-push. Conflicts in nativeHost.ts (method union, interface, wrappers), index.ts, the nativeHost.test.tsx fake and mobile README resolved as a union: getAppLock/openAppLockSettings and pickImage/openFile/share all kept with their wrappers, exports and test rows; en.ts auto-merged with both key sets. No line of this PR's own diff changed.",
"tests": "At 09666e32, locked, 2 workers: native-shell set (now incl. app-lock tests) + every test naming FileField/ImageField/RecordAttachmentsPanel + the four new/touched files + packages/i18n/: 150 files, 2825 passed, 13 skipped, 0 failed.",
"gates": "At 09666e32: rebuild app-shell closure + formula/sdui-parser/lint/client/client-react 66/66 exit 0; type-check mobile/fields/app-shell/i18n 68/68 exit 0; dispatch-gates --commands 35 derived, 35 exit 0; --ran 35 run, 0 NOT-MEASURED. Body gates on pr-body-v2 (changeset-no-major, adr-0087-registration, closing-keyword-parity, partof-closing-keyword) exit 0. CI at 09666e32: in_progress at report time.",
"pr_body": "v2 with seat signature line first: /mnt/project-files/issue-29735/pr-body-v2.md (Verification names 09666e32); the dev cannot PATCH the body.",
"api_writes": "1 — post-stamped comment on #29735 (this addendum). Plus git push (not a REST write).",
"mcp_calls": "0"
}
closed completed by Fixes. Labels read back: enhancement, priority:p2, domain:ui
State: pm:dispatched removed, and the card is closed. Delivered: inside the mobile shell, file and image fields take photos through pickImage(), a record attachment opens through openFile() with the bytes the Console fetched, and record Share uses share(). A plain browser and an older shell are unchanged. Nothing is left on this card.
Activity
objectstack-fleet commentedon Nov 3, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p2 ·
domain:ui·pm:queue· 2026-11-03T03:56Z⛔ Not a claim.
pickImage/openFile/sharewhen they are present, falling back to the browser path. Maintainer-ruled A (mobile#147). A mobile capability, so p2.docs/HYBRID-SHELL.md(mobile#180).Generated by Claude Code
objectstack-fleet commentedon Nov 3, 2026
domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m
Claim: PM loop round 31 · 2026-11-03T04:06Z
Session:
session_01QsR2jSqiKZMCzGXQK5xzUq(card thread, os-dev); dispatched by seat sessionsession_01QsR2jV4dWohojjbTJTQq5mAccount:
zhuangjianguoBranch:
claude/project-thread-6oh3sk(platform-assigned to the card thread; it can push only this branch)Worktree:
objectstack-issue-29735Domain:
domain:uiSeat:
domain:ui#3File surface:
ui/packages/mobile/src/nativeHost.ts(three optionalObjectStackNativemembers,pickImage?/openFile?/share?, and their wrappers), its index export and test fake.The exact files are named in the thread before the first edit, with a split into two PRs proposed if the four legs exceed the size budget (stop on breach; explain in the report).
Container & model: M,
mode:thread,model: default tier (dispatch-gates --tier: no path-derived mandate),effort: highClause-②: yes
Metadata-protocol: none
Responsibility:
open — recorded at reviewThread-read: none
Premise: holds per the card. The shell side is objectstack-ai/mobile#180 (contract in mobile
docs/HYBRID-SHELL.md), under the maintainer ruling mobile#147 6593858903, letter A: the Console fetches files with its own session.ObjectStackNativeon main carries none of the three methods.Serial constraints cleared: none in flight on these sites. Seat 2 may take #29750 (native push route), which also edits
nativeHost.ts; union-line merges are expected and are no overlap of behaviour.objectstack-fleet commentedon Nov 3, 2026
domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m
Claim amended · 2026-11-03T04:11Z · first amendment, on the os-dev's pre-edit site report. This adds to claim 6595193307; session, branch and seat are unchanged.
Clause-②: yes
Metadata-protocol: none
ui/packages/mobile/src/nativeHost.ts(optionalpickImage?/openFile?/share?, the method union, thenativePickImage/nativeOpenFile/nativeSharewrappers, the 8 MiB constant),src/index.ts, and the__tests__/nativeHost.test.tsxfake.ui/packages/fields/src/widgets/FileField.tsxandImageField.tsx, plus a new helperwidgets/nativeImagePick.ts. A picked image becomes aFilethat enters the same upload loop. Two keys (fields.file.choosePhoto,fields.file.photoFailed) go in the ten@object-ui/i18nlocale packs.ui/packages/app-shell/src/views/RecordAttachmentsPanel.tsx(handleDownload). In the shell, under 8 MiB, it fetches the bytes with the Console's session and callsopenFile. Over the cap, on a fetch failure or onbad_args, it keeps today'swindow.open.ui/packages/app-shell/src/views/RecordDetailView.tsx(thesys_shareaction). In the shell it callsshare({ url, text }); otherwise it keeps today's path.AvatarFieldand gridFileCellpickers, and the file-field download anchors, keep today's behaviour.objectstack-fleet commentedon Nov 3, 2026
domain:ui#3 · zhuangjianguo · session_01QsR2jSqiKZMCzGXQK5xzUq
os-dev-report
{ "issue": 29735, "status": "done", "branch": "claude/project-thread-6oh3sk", "pr": "https://github.com/objectstack-ai/objectstack/pull/29803", "head": "b37e3124", "session": "session_01QsR2jSqiKZMCzGXQK5xzUq", "premise_still_valid": true, "summary": "All four legs in one draft PR. @object-ui/mobile gains optional pickImage?/openFile?/share? on ObjectStackNative with nativePickImage/nativeOpenFile/nativeShare wrappers (scan precedent), NATIVE_FILE_MAX_BYTES and two base64 file helpers. FileField and ImageField offer Take photo / Choose photo through the shell when has('pickImage'); the picked File enters the existing upload pipeline (FileField processFiles, ImageField uploadPicked lifted from the input handler). RecordAttachmentsPanel's Download hands fetched bytes (never the signed URL) to openFile in the shell, falling back to window.open over 8 MiB, on fetch failure or any non-ok answer. RecordDetailView sys_share calls share({url, text}) in the shell, else today's path. Attachment share left out per seat ruling A.", "clause_2": "yes", "metadata_protocol": "none", "widening_exports": "@object-ui/mobile entry: nativePickImage, nativeOpenFile, nativeShare, fileFromNativeFile, nativeFileFromBlob, NATIVE_FILE_MAX_BYTES, types NativePickImageOptions, NativeFile, NativeShareContent; ObjectStackNative gains optional pickImage?, openFile?, share?; NativeHostMethod gains three names. @object-ui/i18n: fields.file.choosePhoto, fields.file.photoFailed. Contract review owed (seat routes to director).", "files_changed": [ ".changeset/29735-mobile-shell-files.md", "ui/packages/app-shell/src/views/RecordAttachmentsPanel.tsx", "ui/packages/app-shell/src/views/RecordDetailView.favoritesEntry-12427.test.tsx", "ui/packages/app-shell/src/views/RecordDetailView.tsx", "ui/packages/app-shell/src/views/__tests__/RecordAttachmentsPanel.test.tsx", "ui/packages/fields/src/widgets/FileField.tsx", "ui/packages/fields/src/widgets/ImageField.tsx", "ui/packages/fields/src/widgets/nativeImagePick.shellPhoto.test.tsx", "ui/packages/fields/src/widgets/nativeImagePick.ts", "ui/packages/i18n/src/locales/ar.ts", "ui/packages/i18n/src/locales/de.ts", "ui/packages/i18n/src/locales/en.ts", "ui/packages/i18n/src/locales/es.ts", "ui/packages/i18n/src/locales/fr.ts", "ui/packages/i18n/src/locales/ja.ts", "ui/packages/i18n/src/locales/ko.ts", "ui/packages/i18n/src/locales/pt.ts", "ui/packages/i18n/src/locales/ru.ts", "ui/packages/i18n/src/locales/zh.ts", "ui/packages/mobile/README.md", "ui/packages/mobile/src/__tests__/nativeHost.test.tsx", "ui/packages/mobile/src/index.ts", "ui/packages/mobile/src/nativeHost.ts" ], "line_budget": "23 files, +871 / -15 vs origin/main 25450217 at b37e3124, under 3000", "tests": "New/touched at b37e3124: nativeHost.test.tsx 79, nativeImagePick.shellPhoto.test.tsx 12 (new), RecordAttachmentsPanel.test.tsx 37 (6 new in a top-level describe), RecordDetailView.favoritesEntry-12427.test.tsx 7 (4 new in a top-level describe): 135 pass. Sweep at b37e3124 locked, 2 workers: native-shell set + every test naming FileField/ImageField/RecordAttachmentsPanel + packages/i18n/: 153 files, 2831 passed, 13 skipped, 0 failed. Other 99 RecordDetailView*.test.tsx at 3d7a69ca: 619 passed. Ablations at c413ef3c via scripts/ablation-replace.mjs, each restored (blob == HEAD, git diff HEAD empty): bridge share forwards {} 1 red; FileField drops picked files 2 red; ImageField drops picked files 2 red; panel skips openInNativeShell 2 red; Share ignores shell ok 1 red. ui vitest aliases @object-ui/* to src, so no rebuild per leg.", "gates": "dispatch-gates --commands at b37e3124: 35 derived, all exit 0 (incl. pnpm --dir ui exec vitest run scripts/, check:type-check-debt, check:published-files, check:nul-bytes, check-sdui-manifest, check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity with the PR body as GITHUB_EVENT_PATH); --ran: 35 run, 0 NOT-MEASURED, 0 UNRUN. Same 35 also all exit 0 at 3d7a69ca before the main merge. type-check (turbo) mobile/fields/app-shell/i18n 68/68 exit 0 at b37e3124. eslint on 11 touched files: 0 errors. check-partof-closing-keyword exit 0. CI check-runs: in_progress at report time.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "deviations": [ "ui/packages/mobile/README.md added to the file surface on the seat's word (doc follows export).", "Shots not taken: the fields harness is cheap but the record Share sheet is native and the record page needs a full backend boot; every leg is driven through the shell fake instead.", "Session-context asks to assign the PR and request review via GitHub MCP; skipped per common rule 3/10 and os-dev (no MCP writes, no assignees)." ], "mcp_calls": "0", "api_writes": "2 — fleet-write relay pr_create (objectstack-ai/objectstack#29803); post-stamped comment on #29735 (this report). Plus git push (not a REST write).", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: none · noted in PR Acceptance notes, not filed: AvatarField and grid FileCell have no shell picker; file-field download anchors (FileValueAffordance) keep the browser link; plugin-detail DetailView sys_share (not on the Console record page) unchanged." ] }objectstack-fleet commentedon Nov 3, 2026
domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m
ACCEPT → PR #29803 comment 6596898067 · 2026-11-03T06:19Z (contract review PASS 6596881196 at the same head; landing: ready + auto-merge)
objectstack-fleet commentedon Nov 3, 2026
domain:ui#3 · zhuangjianguo · session_01QsR2jSqiKZMCzGXQK5xzUq
os-dev-report
{ "issue": 29735, "status": "done", "pr": "https://github.com/objectstack-ai/objectstack/pull/29803", "head": "09666e32", "previous_head": "b37e3124", "session": "session_01QsR2jSqiKZMCzGXQK5xzUq", "summary": "Merged origin/main b62463f1 (PR #29798 app-lock bridge members) into the branch, no rebase, no force-push. Conflicts in nativeHost.ts (method union, interface, wrappers), index.ts, the nativeHost.test.tsx fake and mobile README resolved as a union: getAppLock/openAppLockSettings and pickImage/openFile/share all kept with their wrappers, exports and test rows; en.ts auto-merged with both key sets. No line of this PR's own diff changed.", "tests": "At 09666e32, locked, 2 workers: native-shell set (now incl. app-lock tests) + every test naming FileField/ImageField/RecordAttachmentsPanel + the four new/touched files + packages/i18n/: 150 files, 2825 passed, 13 skipped, 0 failed.", "gates": "At 09666e32: rebuild app-shell closure + formula/sdui-parser/lint/client/client-react 66/66 exit 0; type-check mobile/fields/app-shell/i18n 68/68 exit 0; dispatch-gates --commands 35 derived, 35 exit 0; --ran 35 run, 0 NOT-MEASURED. Body gates on pr-body-v2 (changeset-no-major, adr-0087-registration, closing-keyword-parity, partof-closing-keyword) exit 0. CI at 09666e32: in_progress at report time.", "pr_body": "v2 with seat signature line first: /mnt/project-files/issue-29735/pr-body-v2.md (Verification names 09666e32); the dev cannot PATCH the body.", "api_writes": "1 — post-stamped comment on #29735 (this addendum). Plus git push (not a REST write).", "mcp_calls": "0" }objectstack-fleet commentedon Nov 3, 2026
domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m
Landed · 2026-11-03T06:39Z
a7e6e07f, at head09666e32(ACCEPT 6596898067, contract PASS 6596881196)completedbyFixes. Labels read back:enhancement,priority:p2,domain:uiState:
pm:dispatchedremoved, and the card is closed. Delivered: inside the mobile shell, file and image fields take photos throughpickImage(), a record attachment opens throughopenFile()with the bytes the Console fetched, and record Share usesshare(). A plain browser and an older shell are unchanged. Nothing is left on this card.