diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-rest-dark.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-rest-dark.png
new file mode 100644
index 0000000000..c9745deb31
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-rest-dark.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-rest-light.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-rest-light.png
new file mode 100644
index 0000000000..39e20548f1
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-rest-light.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r2-dark.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r2-dark.png
new file mode 100644
index 0000000000..3f8c268269
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r2-dark.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r2-light.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r2-light.png
new file mode 100644
index 0000000000..5ad8593237
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r2-light.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r3-dark.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r3-dark.png
new file mode 100644
index 0000000000..4382ab2cf3
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r3-dark.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r3-light.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r3-light.png
new file mode 100644
index 0000000000..fc74462311
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r3-light.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r4-dark.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r4-dark.png
new file mode 100644
index 0000000000..4382ab2cf3
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r4-dark.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r4-light.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r4-light.png
new file mode 100644
index 0000000000..4dd9bb7e2f
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-scrolled-r4-light.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-top-edge-crop-r2.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-top-edge-crop-r2.png
new file mode 100644
index 0000000000..6073748fe6
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-top-edge-crop-r2.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-top-edge-crop-r3.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-top-edge-crop-r3.png
new file mode 100644
index 0000000000..757e75a160
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-top-edge-crop-r3.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-top-edge-crop-r4.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-top-edge-crop-r4.png
new file mode 100644
index 0000000000..38303bb4af
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-empty-composer-top-edge-crop-r4.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-dark.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-dark.png
new file mode 100644
index 0000000000..91bd1a5e39
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-dark.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-light.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-light.png
new file mode 100644
index 0000000000..4ea0984516
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-light.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r2-dark.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r2-dark.png
new file mode 100644
index 0000000000..ad9357945f
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r2-dark.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r2-light.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r2-light.png
new file mode 100644
index 0000000000..bcd36d3517
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r2-light.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r3-dark.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r3-dark.png
new file mode 100644
index 0000000000..bc352e9d9b
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r3-dark.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r3-light.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r3-light.png
new file mode 100644
index 0000000000..6cdec03232
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-closed-scrolled-r3-light.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-dark.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-dark.png
new file mode 100644
index 0000000000..312e68d8db
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-dark.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-light.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-light.png
new file mode 100644
index 0000000000..0afa55578a
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-light.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r2-dark.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r2-dark.png
new file mode 100644
index 0000000000..0467058a0b
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r2-dark.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r2-light.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r2-light.png
new file mode 100644
index 0000000000..069b1c197f
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r2-light.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r3-dark.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r3-dark.png
new file mode 100644
index 0000000000..a5fefe0e2d
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r3-dark.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r3-light.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r3-light.png
new file mode 100644
index 0000000000..7ea9d55f80
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-keyboard-open-r3-light.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-reopened-scrolled-r3-dark.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-reopened-scrolled-r3-dark.png
new file mode 100644
index 0000000000..49dea2ea96
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-reopened-scrolled-r3-dark.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-reopened-scrolled-r3-light.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-reopened-scrolled-r3-light.png
new file mode 100644
index 0000000000..33ac1c9232
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-four-line-reopened-scrolled-r3-light.png differ
diff --git a/.github/pr-screenshots/2398-composer-bottom-fade/2398-header-r3.png b/.github/pr-screenshots/2398-composer-bottom-fade/2398-header-r3.png
new file mode 100644
index 0000000000..499816d9b7
Binary files /dev/null and b/.github/pr-screenshots/2398-composer-bottom-fade/2398-header-r3.png differ
diff --git a/apps/mobile/DESIGN.md b/apps/mobile/DESIGN.md
index 28f1071885..8710b23e00 100644
--- a/apps/mobile/DESIGN.md
+++ b/apps/mobile/DESIGN.md
@@ -162,7 +162,7 @@ The shell is set by [ADR-0211](../../docs/adr/0211-the-mobile-app-has-two-tabs-w
- Android: the header floats over the messages like iOS's (`headerTransparent`, no bar fill, no shadow), with the same three shapes as Grok's chat header: a round Back, the title chip at the start (`headerTitleAlign: 'left'`) as its own capsule island, and a round computer button. Each shape uses the opaque-iOS fallback of the header buttons (`headerGlassFill`: frosted `raised` fill with a `raised` hairline), so the chip reads as an island, not a label in a bar. Back is always this round button (it replaces the native navigation icon; system and predictive back still work). The list pads its own top by the header height, and messages scroll under the header through the drawn top fade (see below). Android has no system scroll edge effect: Material 3 only tints the top app bar on scroll, and the View fading edge (`fadingEdgeLength`) fades content linearly at the scroll view's own bounds, so it cannot keep what passes under the floating chrome hidden.
- The chip holds, in one row, the Bot's avatar (28pt, round, no state ring) and its name in `body` strong; a group shows its mark and name. It is `theme.touch` tall with padding concentric with its corners. The Bot's state is read out in its accessibility label only. Pressing shows the `raised` pressed fill. Icons in the header are `fg`, never the Bot's accent.
- iOS: messages run under the transparent header and the status bar, and UIKit's scroll edge effect (left on `automatic`) softens them there. The list uses `contentInsetAdjustmentBehavior="automatic"`, so UIKit, not a manual padding, keeps the header's height free above the oldest message at rest; the edge effect needs that automatic inset. The edge effect and React Native Screens both find the content scroll view through the first-subview chain of the screen, so the message list is the first thing in that chain: a default or colour chat background is the frame's own `backgroundColor`, not a view in front of the list. An image background still needs a view behind the list, and with one the soft edge does not reach the list. UIKit also adds the home-indicator safe area to the bottom inset while the list reaches the screen bottom (keyboard closed); the list cancels it with a negative `contentInset.bottom`, because the composer's height already includes that padding. Without this, scrolling to the very end left 34pt more space below the newest message than the resting position. There is no painted top gradient. A transparent header dimmed the whole message list on iOS 26 while the list was inverted (a scaleY flip); the list now runs top to bottom, which this header depends on.
- - The list runs to the bottom of the screen, and the composer floats over it with no bar of its own; messages pass around and under its **+** button and field capsule. On iOS 26 with Reduce Transparency off both shapes are Liquid Glass, like iOS Messages; older iOS and Reduce Transparency give them an opaque `surface` fill with a `borderStrong` hairline, and Android gives the field the opaque `raised` fill, so on those nothing shows through where the Human types. The bottom of the screen fades out with the same light gradient over the composer and `edgeFade.bottom` above it. The list keeps that much space below the newest message, so at rest it sits just above the composer; scrolled up, messages pass behind the composer. Dragging the list dismisses the keyboard: interactively on iOS (the keyboard follows the finger once it reaches it), on drag on Android. On iOS 26 the bottom edge is UIKit's own scroll edge effect, like the top: the composer's container carries a `UIScrollEdgeElementContainerInteraction` for the message list (the local `scroll-edge-element` module; UIKit shapes the edge once when the interaction is added, so the container re-adds it whenever the composer's height or the keyboard changes), so UIKit softens messages under the composer the way it does under a system toolbar, and adapts it to Reduce Transparency itself. No fade is drawn there. A build without that module, older iOS and Android keep the drawn bottom fade over the composer's measured height (with the soft `EdgeMaterial` blur on iOS 26 with Reduce Transparency off). On Android the fade is a mask layer between the list and the floating chrome: nearly opaque (`edgeFade.cover`) under the composer and under the header, then the light `edgeFade` curve over `edgeFade.bottom` / `edgeFade.top` beyond them, painted in the chat's own background colour (`base` with an image background). With the keyboard open the composer's pill sits `space.x3` above it: the keyboard already covers the home indicator, so the chat frame takes the composer's safe-area padding back out of the keyboard offset instead of counting it twice.
+ - The list runs to the bottom of the screen, and the composer floats over it with no bar of its own; messages pass around and under its **+** button and field capsule. On iOS 26 with Reduce Transparency off both shapes are Liquid Glass, like iOS Messages; older iOS and Reduce Transparency give them an opaque `surface` fill with a `borderStrong` hairline, and Android gives the field the opaque `raised` fill, so on those nothing shows through where the Human types. The bottom of the screen fades out with the same light gradient over the composer and `edgeFade.bottom` above it. The list keeps that much space below the newest message, so at rest it sits just above the composer; scrolled up, messages pass behind the composer. Dragging the list dismisses the keyboard: interactively on iOS (the keyboard follows the finger once it reaches it), on drag on Android. On iOS and Android the bottom edge is a drawn mask layer between the list and the composer, like Grok's chat: nearly opaque (`edgeFade.cover`) under the composer's measured height, then the light `edgeFade` curve over `edgeFade.bottom` above it, painted in the chat's own background colour (`base` with an image background). Android uses the same mask under its floating header. iOS 26 hides UIKit's bottom scroll edge effect for the chat (`scrollEdgeEffects.bottom: 'hidden'`) and does not use a `UIScrollEdgeElementContainerInteraction` on the composer: UIKit picked the hard style there, an opaque band in a different colour from the list with a hairline across its top, at a height that did not follow a wrapped draft, and neither re-adding the interaction nor pinning the `soft` style fixed it. The top edge stays UIKit's automatic scroll edge effect. With the keyboard open the composer's pill sits `space.x3` above it: the keyboard already covers the home indicator, so the chat frame takes the composer's safe-area padding back out of the keyboard offset instead of counting it twice.
- Messages:
- Activity rows show Bot DMs, posts elsewhere, memory commits, Bot creation, departures and stopped turns as one left-aligned meta line with a kind icon and tail ellipsis. They use the same `bubbleRow(true)` inset and single `space.x4` (12pt) top gap as a new message group, with no bottom padding or vertically centred minimum-height box: bubble → activity, activity → activity and activity → new message group keep the same boundary gap. Icons and avatars match the meta line height. In groups, the actor avatar occupies the existing speaker gutter, followed by the icon at the bubble's left edge and the description. In a Human DM, omit the current Bot's avatar and redundant name; Bot-DM actions show the other Bot's avatar after the icon. Missing avatars use the person icon.
- Activity rows do not navigate on tap. Long-press (or the accessibility details action) opens the message sheet with the complete plain-text content in a scrollable, selectable block capped at `messageSheet.textHeightRatio` of the window height, then Copy/Share and an explicit Open conversation, Open memory or Open new Bot action when a destination exists; there are no reactions. Consecutive posts by the same Bot into the same Channel on the same day fold into a counted row whose menu opens the latest post. Memory opens the Bot's memory files, not a commit diff. Bot-to-Bot DMs remain read-only. Keep full actor/action/detail text in the accessibility label and menu even when the compact memory line uses only the icon and commit subject.
diff --git a/apps/mobile/modules/scroll-edge-element/README.md b/apps/mobile/modules/scroll-edge-element/README.md
deleted file mode 100644
index c548bd66f5..0000000000
--- a/apps/mobile/modules/scroll-edge-element/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# iOS scroll edge element
-
-This local Expo module lets a floating React Native view take part in UIKit's
-scroll edge effect on iOS 26, the way a system toolbar does. It wraps its
-children in a view that carries a `UIScrollEdgeElementContainerInteraction`
-for the nearest sibling scroll view, so UIKit draws the soft edge under it. UIKit shapes that edge when the
-interaction is added, so the `revision` prop re-adds it whenever the
-container's height or the keyboard changes.
-
-The chat composer uses it for the bottom edge; the native header already gives
-the top edge. Before iOS 26 the view is a plain container.
-
-The JavaScript binding lives in `src/ui/primitives/scroll-edge-element.ios.tsx`.
-Builds without this module keep the drawn `EdgeMaterial` fade. **Adding this
-module requires a native rebuild**; an OTA update alone cannot install it.
diff --git a/apps/mobile/modules/scroll-edge-element/expo-module.config.json b/apps/mobile/modules/scroll-edge-element/expo-module.config.json
deleted file mode 100644
index 4acb3d0d36..0000000000
--- a/apps/mobile/modules/scroll-edge-element/expo-module.config.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "platforms": ["apple"],
- "apple": {
- "modules": ["ScrollEdgeElementModule"]
- }
-}
diff --git a/apps/mobile/modules/scroll-edge-element/ios/ScrollEdgeElement.podspec b/apps/mobile/modules/scroll-edge-element/ios/ScrollEdgeElement.podspec
deleted file mode 100644
index c988e80b0f..0000000000
--- a/apps/mobile/modules/scroll-edge-element/ios/ScrollEdgeElement.podspec
+++ /dev/null
@@ -1,21 +0,0 @@
-Pod::Spec.new do |s|
- s.name = 'ScrollEdgeElement'
- s.version = '1.0.0'
- s.summary = 'Registers a floating React Native view as a UIKit scroll edge element.'
- s.description = 'Registers a floating React Native view as a UIKit scroll edge element.'
- s.license = 'MIT'
- s.author = 'BotHarness'
- s.homepage = 'https://github.com/BotHarness/DeepSeekBot'
- s.platforms = { :ios => '16.4' }
- s.swift_version = '5.9'
- s.source = { git: 'https://github.com/BotHarness/DeepSeekBot.git' }
- s.static_framework = true
-
- s.dependency 'ExpoModulesCore'
-
- s.source_files = '**/*.{h,m,swift}'
- s.pod_target_xcconfig = {
- 'DEFINES_MODULE' => 'YES',
- 'SWIFT_COMPILATION_MODE' => 'wholemodule'
- }
-end
diff --git a/apps/mobile/modules/scroll-edge-element/ios/ScrollEdgeElementModule.swift b/apps/mobile/modules/scroll-edge-element/ios/ScrollEdgeElementModule.swift
deleted file mode 100644
index cb83f1f142..0000000000
--- a/apps/mobile/modules/scroll-edge-element/ios/ScrollEdgeElementModule.swift
+++ /dev/null
@@ -1,85 +0,0 @@
-import ExpoModulesCore
-import UIKit
-
-public final class ScrollEdgeElementModule: Module {
- public func definition() -> ModuleDefinition {
- Name("ScrollEdgeElement")
-
- View(ScrollEdgeElementView.self) {
- Prop("edge") { (view: ScrollEdgeElementView, edge: String) in
- view.edge = edge == "top" ? .top : .bottom
- }
- Prop("revision") { (view: ScrollEdgeElementView, _: String) in
- view.refresh()
- }
- }
- }
-}
-
-final class ScrollEdgeElementView: ExpoView {
- var edge: UIRectEdge = .bottom {
- didSet { attach() }
- }
-
- private var interaction: UIInteraction?
-
- override func didMoveToWindow() {
- super.didMoveToWindow()
- attach()
- }
-
- override func layoutSubviews() {
- super.layoutSubviews()
- attach()
- }
-
- func refresh() {
- if let interaction { removeInteraction(interaction) }
- interaction = nil
- DispatchQueue.main.async { [weak self] in self?.attach() }
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) { [weak self] in
- guard let self, let interaction = self.interaction else { return }
- self.removeInteraction(interaction)
- self.interaction = nil
- self.attach()
- }
- }
-
- private func attach() {
- guard #available(iOS 26.0, *) else { return }
- guard window != nil, let scrollView = nearestScrollView() else { return }
- let current = interaction as? UIScrollEdgeElementContainerInteraction
- if let current, current.scrollView === scrollView, current.edge == edge { return }
- if let current { removeInteraction(current) }
- let next = UIScrollEdgeElementContainerInteraction()
- next.scrollView = scrollView
- next.edge = edge
- addInteraction(next)
- interaction = next
- }
-
- private func nearestScrollView() -> UIScrollView? {
- var child: UIView = self
- while let parent = child.superview {
- for sibling in parent.subviews where sibling !== child {
- if let found = largestScrollView(in: sibling) { return found }
- }
- child = parent
- }
- return nil
- }
-
- private func largestScrollView(in root: UIView) -> UIScrollView? {
- var best: UIScrollView?
- var queue: [UIView] = [root]
- while !queue.isEmpty {
- let view = queue.removeFirst()
- if let scrollView = view as? UIScrollView, !(view is UITextView) {
- if best == nil || scrollView.bounds.height > best!.bounds.height { best = scrollView }
- continue
- }
- queue.append(contentsOf: view.subviews)
- }
- return best
- }
-}
diff --git a/apps/mobile/src/ui/chat/conversation-screen.tsx b/apps/mobile/src/ui/chat/conversation-screen.tsx
index 087b3e3900..a8ea20171a 100644
--- a/apps/mobile/src/ui/chat/conversation-screen.tsx
+++ b/apps/mobile/src/ui/chat/conversation-screen.tsx
@@ -74,7 +74,6 @@ import { ChatTitle } from './chat-title';
import { Composer, type ComposerInput } from './composer';
import { ClipboardImageOffer, useClipboardImage } from './clipboard-image';
import { EdgeFade, HeaderBackButton, titleChipFill } from './header-chrome';
-import { ScrollEdgeElement, nativeScrollEdge } from '../primitives/scroll-edge-element';
import {
barLabelStyle,
floatingHeader,
@@ -812,6 +811,9 @@ function ChatConversation({
headerShadowVisible: false,
headerBackButtonDisplayMode: 'minimal',
...(ios && !glassHeader ? { headerBlurEffect: 'systemChromeMaterial' as const } : {}),
+ ...(glassHeader
+ ? { scrollEdgeEffects: { top: 'automatic' as const, bottom: 'hidden' as const } }
+ : {}),
...(ios
? {
title: '',
@@ -865,66 +867,64 @@ function ChatConversation({
}
onComposerLayout={(event) => setComposerHeight(event.nativeEvent.layout.height)}
composer={
-
- {botDm ? (
-
-
- {t.activityRow.botDm}
-
-
- ) : (
- {
- setSelection(undefined);
- setCaret(next);
- }}
- {...(candidates.length > 0
- ? { above: }
- : clipboard.offered
- ? {
- above: (
- {
- clipboard.used();
- setAttachError(false);
- setFiles((current) =>
- [...current, fromClipboardImage(data)].slice(0, MAX_PICKED),
- );
- }}
- />
- ),
- }
- : {})}
- onSend={send}
- onPick={pick}
- onRemove={(id) => setFiles((current) => current.filter((file) => file.id !== id))}
- onDictate={() => {
- setAttachError(false);
- dictation.start();
- }}
- onStopDictation={dictation.stop}
- onCancelDictation={dictation.cancel}
- inputRef={composerInput}
- onFocusChange={setTyping}
- />
- )}
-
+ botDm ? (
+
+
+ {t.activityRow.botDm}
+
+
+ ) : (
+ {
+ setSelection(undefined);
+ setCaret(next);
+ }}
+ {...(candidates.length > 0
+ ? { above: }
+ : clipboard.offered
+ ? {
+ above: (
+ {
+ clipboard.used();
+ setAttachError(false);
+ setFiles((current) =>
+ [...current, fromClipboardImage(data)].slice(0, MAX_PICKED),
+ );
+ }}
+ />
+ ),
+ }
+ : {})}
+ onSend={send}
+ onPick={pick}
+ onRemove={(id) => setFiles((current) => current.filter((file) => file.id !== id))}
+ onDictate={() => {
+ setAttachError(false);
+ dictation.start();
+ }}
+ onStopDictation={dictation.stop}
+ onCancelDictation={dictation.cancel}
+ inputRef={composerInput}
+ onFocusChange={setTyping}
+ />
+ )
}
>
{notice === undefined ? null : (
@@ -1081,13 +1081,12 @@ function ChatConversation({
color={fadeColor}
/>
) : null}
- {nativeScrollEdge ? null : (
-
- )}
+
{composable && Platform.OS === 'ios' ? (
- {glass ? (
+ {glass && cover === 0 ? (
) : (
-