Sending an image was broken in the way that is hardest to see from the phone: a camera photo is twelve megapixels and several megabytes, the Claude API resizes anything past 1568px on its long edge before looking at it and refuses far larger outright, so the picture was uploaded whole over the tunnel to be thrown away or rejected at the other end. Shrunk on the phone, to a limit the server states. Which number it is comes from the provider's *kind* -- `DriverKind::max_image_edge`, reported on the session row -- because that is where a provider's requirements are known, and a phone carrying its own copy of them would be a second place to update when one changes. `None` where nothing cares, rather than a large number: "no limit" and "a limit that happens to be big" are different answers and only one of them stays true. Doing it before the upload rather than after is the point -- the expensive part on a phone is the tunnel, not the decode -- and an image already inside the limit is uploaded byte for byte rather than being round-tripped through JPEG for nothing. EXIF orientation is applied while scaling. The camera writes which way up the picture is into a tag rather than into the pixels, and re-encoding drops it, so a portrait photo would have arrived at the model on its side with nothing anywhere saying so. **What is attached is now visible before it is sent**, in a row directly above the box it will be sent from: the count on the "+" button said how many and never which, so the only way to find out what you had picked was to send it. It scrolls sideways rather than shrinking, and tapping one takes it back off -- an image picked by mistake could otherwise only be dealt with by sending it. The tile is outlined as well as filled, because most of what gets attached here is a screenshot of a dark app and a cropped one is near-black: without an edge the only thing on screen saying an image was attached was the cross drawn on top of nothing. **And the picture is inside the bubble that sent it.** Attachments used to be their own `Image` events emitted just before the message, which drew somebody's screenshot as a row floating above the bubble and left the phone deciding from adjacency alone which message an image belonged to -- a thing the sender knew and could simply say. `UserMessage`, `MessageQueued` and `MessageTaken` carry the refs now, so a waiting message keeps its picture for as long as the turn runs, and a replay puts it back in the same place. Verified on a real claude-cli session rather than an echo one, since the limit only exists for that kind: a 3000x4000 image arrived as 1176x1568 JPEG -- long edge exactly the limit, aspect ratio intact -- and haiku answered "AI Sessions displays idle Photo", which is what the picture was. No error, and the transcript records the message with `images` on it.
64 lines
2.6 KiB
Bash
Executable File
64 lines
2.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Rebuilds androidApp/src/main/res/font/nerd_icons.ttf.
|
|
#
|
|
# The app draws a handful of icons -- a cog, a refresh arrow, send, stop --
|
|
# as text in a Nerd Fonts glyph rather than as vector assets or as ordinary
|
|
# Unicode. Unicode has no character for most of these, and the ones it does
|
|
# have are not reliably in an Android system font, so they land as tofu
|
|
# boxes on somebody's phone. Shipping the subset removes the hope: the
|
|
# glyph is in the APK.
|
|
#
|
|
# The whole symbols font is 3 MB for the handful below, so what is
|
|
# committed is a subset. Add a codepoint to GLYPHS below and to NerdIcons.kt
|
|
# (the two lists have to agree -- a codepoint in the Kotlin but not here is
|
|
# a glyph that silently doesn't exist), then run this and commit the result.
|
|
#
|
|
# Needs python3 and network access; fontTools is fetched into a temporary
|
|
# venv, so nothing has to be installed on the machine.
|
|
#
|
|
# Copied from dev-updater's script of the same name rather than shared
|
|
# through wg-app-link, for the reason Theme.kt gives about the palette: the
|
|
# link is the tunnel, the pinned CA and enrollment, and an icon set is a
|
|
# preference rather than part of that contract.
|
|
set -euo pipefail
|
|
|
|
# Codepoint, then the Nerd Fonts glyph name it came from. Material Design
|
|
# Icons bar one, so they read as one family -- and the first two are
|
|
# deliberately the same two dev-updater uses, since a cog and a refresh
|
|
# arrow mean the same thing in both apps. The exception is noted on its
|
|
# own line, as dev-updater's script does with its two.
|
|
GLYPHS=(
|
|
U+F0493 # md-cog
|
|
U+F0450 # md-refresh
|
|
U+F048A # md-send
|
|
U+F04DB # md-stop
|
|
U+F1163 # md-send_clock
|
|
U+F0156 # md-close
|
|
U+F004D # md-arrow_left
|
|
U+F201 # fa-line_chart -- Font Awesome's, asked for by name
|
|
)
|
|
|
|
url=https://github.com/ryanoasis/nerd-fonts/releases/latest/download/NerdFontsSymbolsOnly.zip
|
|
out="$(cd "$(dirname "$0")" && pwd)/androidApp/src/main/res/font/nerd_icons.ttf"
|
|
work="$(mktemp -d)"
|
|
trap 'rm -rf "$work"' EXIT
|
|
|
|
echo "Fetching $url"
|
|
curl -fsSL -o "$work/nf.zip" "$url"
|
|
python3 -c 'import sys,zipfile; zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])' "$work/nf.zip" "$work"
|
|
|
|
python3 -m venv "$work/venv"
|
|
"$work/venv/bin/pip" -q install fonttools
|
|
|
|
unicodes="$(IFS=,; echo "${GLYPHS[*]}")"
|
|
mkdir -p "$(dirname "$out")"
|
|
# The proportional face rather than the Mono one: these are drawn inline
|
|
# beside text, where a fixed advance would pad each icon out to a cell.
|
|
"$work/venv/bin/pyftsubset" "$work/SymbolsNerdFont-Regular.ttf" \
|
|
--unicodes="$unicodes" \
|
|
--layout-features= \
|
|
--drop-tables+=DSIG \
|
|
--output-file="$out"
|
|
|
|
echo "Wrote $out ($(stat -c %s "$out") bytes) with ${#GLYPHS[@]} glyphs"
|