Files
Rocky 9f308fadd2 feat(keyboard): ship AI hint carousel, home library cards, and clipboard polish
Rotate AI idle suggestions with optional remote packs, move history/dictionary onto self-sizing Home preview cards, harden clipboard capture/prompting, and simplify keyboard chrome by dropping most liquid-glass shadows.
2026-08-13 01:00:51 +08:00

94 lines
3.4 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// EditTextPager.swift
// OSGKeyboard · Shared
import SwiftUI
public struct EditTextPager: View {
@Environment(\.themePalette) private var palette
private let originalTitle: String
private let originalText: String
private let editedTitle: String
private let editedText: String?
private let contentBottomInset: CGFloat
@Binding private var selectedPage: Int?
public init(
originalTitle: String,
originalText: String,
editedTitle: String,
editedText: String?,
contentBottomInset: CGFloat = 0,
selectedPage: Binding<Int?>
) {
self.originalTitle = originalTitle
self.originalText = originalText
self.editedTitle = editedTitle
self.editedText = editedText
self.contentBottomInset = contentBottomInset
self._selectedPage = selectedPage
}
public var body: some View {
GeometryReader { proxy in
ScrollView(.horizontal) {
// Two pages only — prefer HStack so page `1` is laid out in the
// same update that sets `scrollPosition`, avoiding a stuck
// LazyHStack that leaves the indicator on “edited” while still
// showing the original text.
HStack(spacing: 0) {
textPage(title: originalTitle, text: originalText)
.frame(
width: proxy.size.width,
height: proxy.size.height,
alignment: .topLeading
)
.id(0)
if let editedText {
textPage(title: editedTitle, text: editedText)
.frame(
width: proxy.size.width,
height: proxy.size.height,
alignment: .topLeading
)
.id(1)
}
}
.frame(height: proxy.size.height, alignment: .top)
.scrollTargetLayout()
}
.scrollIndicators(.hidden)
.scrollTargetBehavior(.paging)
.scrollPosition(id: $selectedPage)
.clipped()
.accessibilityIdentifier("edit.textPager")
}
}
private func textPage(title: String, text: String) -> some View {
VStack(alignment: .leading, spacing: 3) {
Text(title)
.font(TypeStyle.caption2)
.foregroundStyle(palette.textTertiary)
ScrollView(.vertical) {
Text(text)
.font(TypeStyle.body)
.foregroundStyle(palette.textPrimary)
.frame(maxWidth: .infinity, alignment: .leading)
.textSelection(.disabled)
}
}
.padding(.horizontal, Spacing.md)
.padding(.bottom, contentBottomInset)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
// A fully clear expanded frame is not a reliable UIKit ScrollView hit
// target inside keyboard extensions. This imperceptible rendered layer
// makes the complete page participate in native pan hit testing.
.background(Color.black.opacity(0.001))
.contentShape(Rectangle())
.accessibilityElement(children: .combine)
.accessibilityLabel("\(title)\(text)")
}
}