Files
ai-app/app/androidApp/src/main/AndroidManifest.xml
T
irisandClaude Fable 5.1 6180663f14 Attach any file, take shares from other apps, and survive a backwards highlight
Attachments were images only. Now any file can be attached: from the file
chooser behind the "+" menu, or from Android's share sheet, which the app
is now in. An image still goes to the model as a picture; anything else is
stored under its own name (`<hex>-<name>`, cleaned by `safe_file_name`)
and the Claude driver ends the message with `Attached file: /abs/path`,
since the CLI reads files by path and a model cannot be shown a trace. The
user-message field is renamed `images` -> `attachments` on both sides,
with a serde alias reading the rows written before. A share arrives before
anyone has said which session it is for, so it is held in AppRoot with a
banner on the list until a session takes it; an open session takes it at
once. Unreadable shares are reported beside the composer, not thrown.

The tool card crashed the app when opened on a command holding a quoted
glob such as `-path '*/.git/*'`: highlights 1.1.0's shell lexer answers
`x '*/a/*'` with a span whose end is before its start, and AnnotatedString
refuses the range. Such spans are dropped; the library is the place for
the fix. The echo driver gains `/bash <command>` so a card with a given
command can be produced on the emulator.

ui-sandbox.sh's token salvage read the tokens block's close only at a line
start, ran past the compact `),],` the server writes, and copied `setups`
into the new config twice, which the server then refused.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 08:15:10 -04:00

116 lines
6.6 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<!-- Android 17 (API 37) made Local Network Protection mandatory: an app
targeting 37+ needs this runtime permission to reach *any* local
network address, including a plain socket to a LAN IP literal.
Without it the traffic is silently dropped, surfacing only as a
connect timeout. See MainActivity.kt's runtime request, and
dev-updater's manifest for the full story. -->
<uses-permission android:name="android.permission.ACCESS_LOCAL_NETWORK" />
<!-- Telling somebody a session wants them. POST_NOTIFICATIONS is a
runtime permission from Android 13; the foreground-service pair
below is what lets the connection outlive the app being closed,
which is the entire point (see Notifications.kt). -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<!-- tools:ignore MissingApplicationIcon: there is no icon yet, and
that is a decision rather than an oversight. An app with no icon
of its own is obvious to anyone who opens a launcher, so the
warning tells nobody here anything they cannot already see, and
the fix is a judgement about how this app should look. Drop this
suppression when a real icon lands. -->
<application
android:label="AI Sessions"
android:allowBackup="true"
android:theme="@android:style/Theme.Material.Light.NoActionBar"
tools:ignore="MissingApplicationIcon">
<!-- Lets the phone's own System Tracing see this app's trace sections
(Compose's phases, and the composable names runtime-tracing
adds) in a release build, so a frame cost measured on the real
device can be attributed. shell="true" limits it to profilers
run from the shell; it grants nothing to other apps. -->
<profileable android:shell="true" tools:targetApi="q" />
<!-- adjustResize (not the system's default pan): the layout handles
the keyboard itself via imePadding(), so the window must resize
rather than slide the top bar off screen. -->
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize"
android:theme="@android:style/Theme.Material.Light.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- Enrollment: the server prints its aiapp://enroll QR to the
terminal. This intent filter is the fallback path for a
camera app that redirects a scanned aiapp:// URI here
directly; the Settings screen's own "Scan QR code" button
(zxing-android-embedded) is the primary path and needs no
filter, since it decodes the QR itself and hands the URI
to parseEnrollmentUri in-process. -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="aiapp" android:host="enroll" />
</intent-filter>
<!-- The share sheet: a file, a photo or some text from another app
lands here and is attached to a session (see Share.kt). Any
type, because what a session can be handed is the server's
decision rather than the sheet's. -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
<!-- specialUse rather than dataSync, which is the type this looks
like: Android 15 caps dataSync at six hours a day, and a
connection that stops listening after six hours is one that
misses the overnight run it exists for. The subtype below is
the reason string that type requires. -->
<service
android:name=".NotificationService"
android:exported="false"
android:foregroundServiceType="specialUse">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="Holds one connection to the user's own backend so a session
that needs an answer can be reported while the app is closed. There is no
push service: the backend is reachable only over the user's WireGuard
tunnel and never talks to a third party." />
</service>
<!-- The scanner behind Settings' "Scan QR code". Declared here so
it can drop the library CaptureActivity's landscape pin: the
code being scanned is usually on a monitor in front of someone
holding the phone upright. zxing_CaptureTheme is the library's
own fullscreen theme, which is all the activity needs. -->
<!-- tools:ignore DiscouragedApi: lint flags every fixed
screenOrientation, because Android 16 ignores most of them.
This one is not a pin but its removal. fullSensor is what
drops the library's landscape lock, so the activity follows
the phone rather than asking anyone to turn it, and where the
platform ignores the attribute the behaviour is the one this
asked for anyway. Scoped to this activity, so a genuine pin
elsewhere would still be reported. -->
<activity
android:name="com.example.wgapplink.EnrollmentScanActivity"
android:clearTaskOnLaunch="true"
android:screenOrientation="fullSensor"
android:stateNotNeeded="true"
android:theme="@style/zxing_CaptureTheme"
android:windowSoftInputMode="stateAlwaysHidden"
tools:ignore="DiscouragedApi" />
</application>
</manifest>