fix: enable canvas webview scrolling on mobile nodes
This commit is contained in:
@@ -41,6 +41,8 @@
|
|||||||
- Also read the shared guardrails at `~/Projects/oracle/AGENTS.md` and `~/Projects/agent-scripts/AGENTS.MD` before making changes; align with any cross-repo rules noted there.
|
- Also read the shared guardrails at `~/Projects/oracle/AGENTS.md` and `~/Projects/agent-scripts/AGENTS.MD` before making changes; align with any cross-repo rules noted there.
|
||||||
- SwiftUI state management (iOS/macOS): prefer the `Observation` framework (`@Observable`, `@Bindable`) over `ObservableObject`/`@StateObject`; don’t introduce new `ObservableObject` unless required for compatibility, and migrate existing usages when touching related code.
|
- SwiftUI state management (iOS/macOS): prefer the `Observation` framework (`@Observable`, `@Bindable`) over `ObservableObject`/`@StateObject`; don’t introduce new `ObservableObject` unless required for compatibility, and migrate existing usages when touching related code.
|
||||||
- **Restart apps:** “restart iOS/Android apps” means rebuild (recompile/install) and relaunch, not just kill/launch.
|
- **Restart apps:** “restart iOS/Android apps” means rebuild (recompile/install) and relaunch, not just kill/launch.
|
||||||
|
- iOS Team ID lookup: `security find-identity -p codesigning -v` → use Apple Development (…) TEAMID. Fallback: `defaults read com.apple.dt.Xcode IDEProvisioningTeamIdentifiers`.
|
||||||
|
- A2UI bundle hash: `src/canvas-host/a2ui/.bundle.hash` is auto-generated; regenerate via `pnpm canvas:a2ui:bundle` (or `scripts/bundle-a2ui.sh`) instead of manual conflict resolution.
|
||||||
- Notary key file lives at `~/Library/CloudStorage/Dropbox/Backup/AppStore/AuthKey_NJF3NFGTS3.p8` (Sparkle keys live under `~/Library/CloudStorage/Dropbox/Backup/Sparkle`).
|
- Notary key file lives at `~/Library/CloudStorage/Dropbox/Backup/AppStore/AuthKey_NJF3NFGTS3.p8` (Sparkle keys live under `~/Library/CloudStorage/Dropbox/Backup/Sparkle`).
|
||||||
- **Multi-agent safety:** do **not** create/apply/drop `git stash` entries unless Peter explicitly asks (this includes `git pull --rebase --autostash`). Assume other agents may be working; keep unrelated WIP untouched and avoid cross-cutting state changes.
|
- **Multi-agent safety:** do **not** create/apply/drop `git stash` entries unless Peter explicitly asks (this includes `git pull --rebase --autostash`). Assume other agents may be working; keep unrelated WIP untouched and avoid cross-cutting state changes.
|
||||||
- **Multi-agent safety:** when Peter says "push", you may `git pull --rebase` to integrate latest changes (never discard other agents' work). When Peter says "commit", scope to your changes only. When Peter says "commit all", commit everything in grouped chunks.
|
- **Multi-agent safety:** when Peter says "push", you may `git pull --rebase` to integrate latest changes (never discard other agents' work). When Peter says "commit", scope to your changes only. When Peter says "commit all", commit everything in grouped chunks.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- macOS: Voice Wake now fully tears down the Speech pipeline when disabled (cancel pending restarts, drop stale callbacks) to avoid high CPU in the background.
|
- macOS: Voice Wake now fully tears down the Speech pipeline when disabled (cancel pending restarts, drop stale callbacks) to avoid high CPU in the background.
|
||||||
|
- iOS/Android nodes: enable scrolling for loaded web pages in the Canvas WebView (default scaffold stays touch-first).
|
||||||
|
|
||||||
## 2.0.0-beta4 — 2025-12-27
|
## 2.0.0-beta4 — 2025-12-27
|
||||||
|
|
||||||
|
|||||||
@@ -163,6 +163,10 @@ private fun CanvasView(viewModel: MainViewModel, modifier: Modifier = Modifier)
|
|||||||
// Some embedded web UIs (incl. the "background website") use localStorage/sessionStorage.
|
// Some embedded web UIs (incl. the "background website") use localStorage/sessionStorage.
|
||||||
settings.domStorageEnabled = true
|
settings.domStorageEnabled = true
|
||||||
settings.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
|
settings.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
|
||||||
|
isScrollContainer = true
|
||||||
|
overScrollMode = View.OVER_SCROLL_IF_CONTENT_SCROLLS
|
||||||
|
isVerticalScrollBarEnabled = true
|
||||||
|
isHorizontalScrollBarEnabled = true
|
||||||
webViewClient =
|
webViewClient =
|
||||||
object : WebViewClient() {
|
object : WebViewClient() {
|
||||||
override fun onReceivedError(
|
override fun onReceivedError(
|
||||||
|
|||||||
@@ -43,9 +43,7 @@ final class ScreenController {
|
|||||||
self.webView.scrollView.contentInset = .zero
|
self.webView.scrollView.contentInset = .zero
|
||||||
self.webView.scrollView.scrollIndicatorInsets = .zero
|
self.webView.scrollView.scrollIndicatorInsets = .zero
|
||||||
self.webView.scrollView.automaticallyAdjustsScrollIndicatorInsets = false
|
self.webView.scrollView.automaticallyAdjustsScrollIndicatorInsets = false
|
||||||
// Disable scroll to allow touch events to pass through to canvas
|
self.applyScrollBehavior()
|
||||||
self.webView.scrollView.isScrollEnabled = false
|
|
||||||
self.webView.scrollView.bounces = false
|
|
||||||
self.webView.navigationDelegate = self.navigationDelegate
|
self.webView.navigationDelegate = self.navigationDelegate
|
||||||
self.navigationDelegate.controller = self
|
self.navigationDelegate.controller = self
|
||||||
a2uiActionHandler.controller = self
|
a2uiActionHandler.controller = self
|
||||||
@@ -60,6 +58,7 @@ final class ScreenController {
|
|||||||
|
|
||||||
func reload() {
|
func reload() {
|
||||||
let trimmed = self.urlString.trimmingCharacters(in: .whitespacesAndNewlines)
|
let trimmed = self.urlString.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
self.applyScrollBehavior()
|
||||||
if trimmed.isEmpty {
|
if trimmed.isEmpty {
|
||||||
guard let url = Self.canvasScaffoldURL else { return }
|
guard let url = Self.canvasScaffoldURL else { return }
|
||||||
self.errorText = nil
|
self.errorText = nil
|
||||||
@@ -250,6 +249,15 @@ final class ScreenController {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func applyScrollBehavior() {
|
||||||
|
let trimmed = self.urlString.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
let allowScroll = !trimmed.isEmpty
|
||||||
|
let scrollView = self.webView.scrollView
|
||||||
|
// Default canvas needs raw touch events; external pages should scroll.
|
||||||
|
scrollView.isScrollEnabled = allowScroll
|
||||||
|
scrollView.bounces = allowScroll
|
||||||
|
}
|
||||||
|
|
||||||
private static func jsValue(_ value: String?) -> String {
|
private static func jsValue(_ value: String?) -> String {
|
||||||
guard let value else { return "null" }
|
guard let value else { return "null" }
|
||||||
if let data = try? JSONSerialization.data(withJSONObject: [value]),
|
if let data = try? JSONSerialization.data(withJSONObject: [value]),
|
||||||
|
|||||||
@@ -16,6 +16,15 @@ import WebKit
|
|||||||
#expect(scrollView.bounces == false)
|
#expect(scrollView.bounces == false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test @MainActor func navigateEnablesScrollForWebPages() {
|
||||||
|
let screen = ScreenController()
|
||||||
|
screen.navigate(to: "https://example.com")
|
||||||
|
|
||||||
|
let scrollView = screen.webView.scrollView
|
||||||
|
#expect(scrollView.isScrollEnabled == true)
|
||||||
|
#expect(scrollView.bounces == true)
|
||||||
|
}
|
||||||
|
|
||||||
@Test @MainActor func navigateSlashShowsDefaultCanvas() {
|
@Test @MainActor func navigateSlashShowsDefaultCanvas() {
|
||||||
let screen = ScreenController()
|
let screen = ScreenController()
|
||||||
screen.navigate(to: "/")
|
screen.navigate(to: "/")
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
8c6030afb0b9f264b0bb9dcfb738b67d361fc5acac7967b4e056169a44f95184
|
401ee2e7aa55e8abfd5e8ee94810a75629253b88371dc70f5b04c4830cdcce8d
|
||||||
|
|||||||
Reference in New Issue
Block a user