-
Notifications
You must be signed in to change notification settings - Fork 17
DRAFT: feat: webview commands for listing and evaluating js #229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
9ce4f38
8dabdb1
3945a67
36729b8
cef8b30
559d39d
a6e7d1e
37687ee
d8109a6
46f452c
e6a0c33
98d936d
7808755
31386a7
4abe35b
f42b53c
581330f
b1cfde6
c6d1eea
49d63ee
c74d7b7
c0e2d01
0391621
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| package commands | ||
|
|
||
| import "fmt" | ||
|
|
||
| // ─── Request types ──────────────────────────────────────────── | ||
|
|
||
| type WebViewListRequest struct { | ||
| DeviceID string | ||
| } | ||
|
|
||
| // WebViewRequest is the base for all webview operations that target a specific webview. | ||
| type WebViewRequest struct { | ||
| DeviceID string | ||
| WebViewID string | ||
| } | ||
|
|
||
| type WebViewGotoRequest struct { | ||
| DeviceID string | ||
| WebViewID string | ||
| URL string | ||
| WaitUntil string | ||
| } | ||
|
|
||
| type WebViewReloadRequest struct { | ||
| DeviceID string | ||
| WebViewID string | ||
| WaitUntil string | ||
| } | ||
|
|
||
| type WebViewEvaluateRequest struct { | ||
| DeviceID string | ||
| WebViewID string | ||
| Expression string | ||
| Args []any | ||
| } | ||
|
|
||
| type WebViewWaitForLoadStateRequest struct { | ||
| DeviceID string | ||
| WebViewID string | ||
| State string | ||
| Timeout int | ||
| } | ||
|
|
||
| // ─── Stubs ──────────────────────────────────────────────────── | ||
|
|
||
| func WebViewListCommand(req WebViewListRequest) *CommandResponse { | ||
| return NewErrorResponse(fmt.Errorf("not implemented")) | ||
| } | ||
|
|
||
| func WebViewGotoCommand(req WebViewGotoRequest) *CommandResponse { | ||
| return NewErrorResponse(fmt.Errorf("not implemented")) | ||
| } | ||
|
|
||
| func WebViewReloadCommand(req WebViewReloadRequest) *CommandResponse { | ||
| return NewErrorResponse(fmt.Errorf("not implemented")) | ||
| } | ||
|
|
||
| func WebViewGoBackCommand(req WebViewRequest) *CommandResponse { | ||
| return NewErrorResponse(fmt.Errorf("not implemented")) | ||
| } | ||
|
|
||
| func WebViewGoForwardCommand(req WebViewRequest) *CommandResponse { | ||
| return NewErrorResponse(fmt.Errorf("not implemented")) | ||
| } | ||
|
|
||
| func WebViewEvaluateCommand(req WebViewEvaluateRequest) *CommandResponse { | ||
| return NewErrorResponse(fmt.Errorf("not implemented")) | ||
| } | ||
|
|
||
| func WebViewWaitForLoadStateCommand(req WebViewWaitForLoadStateRequest) *CommandResponse { | ||
| return NewErrorResponse(fmt.Errorf("not implemented")) | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -39,6 +39,13 @@ func GetMethodRegistry() map[string]HandlerFunc { | |||||||||||||||
| "device.screenrecord.stop": handleScreenRecordStop, | ||||||||||||||||
| "device.crashes.list": handleCrashesList, | ||||||||||||||||
| "device.crashes.get": handleCrashesGet, | ||||||||||||||||
| "device.webview.list": handleWebViewList, | ||||||||||||||||
| "device.webview.goto": handleWebViewGoto, | ||||||||||||||||
| "device.webview.reload": handleWebViewReload, | ||||||||||||||||
| "device.webview.goBack": handleWebViewGoBack, | ||||||||||||||||
| "device.webview.goForward": handleWebViewGoForward, | ||||||||||||||||
|
Comment on lines
+45
to
+46
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dispatch key naming breaks the existing convention. Every other key uses lowercase ( Suggest renaming to match the CLI subcommand names: or |
||||||||||||||||
| "device.webview.evaluate": handleWebViewEvaluate, | ||||||||||||||||
| "device.webview.waitForLoadState": handleWebViewWaitForLoadState, | ||||||||||||||||
|
Comment on lines
+42
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don’t register webview RPC methods until command implementations exist. These methods are discoverable now but all currently resolve to stubbed command errors, so clients get guaranteed runtime failures instead of clear method unavailability. Minimal safe change- "device.webview.list": handleWebViewList,
- "device.webview.goto": handleWebViewGoto,
- "device.webview.reload": handleWebViewReload,
- "device.webview.goBack": handleWebViewGoBack,
- "device.webview.goForward": handleWebViewGoForward,
- "device.webview.evaluate": handleWebViewEvaluate,
- "device.webview.waitForLoadState": handleWebViewWaitForLoadState,📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||
| "server.info": handleServerInfo, | ||||||||||||||||
| "server.shutdown": handleServerShutdown, | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,192 @@ | ||
| package server | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
|
|
||
| "github.com/mobile-next/mobilecli/commands" | ||
| ) | ||
|
|
||
| // ─── Params structs ─────────────────────────────────────────── | ||
|
|
||
| type WebViewListParams struct { | ||
| DeviceID string `json:"deviceId"` | ||
| } | ||
|
|
||
| type WebViewParams struct { | ||
| DeviceID string `json:"deviceId"` | ||
| WebViewID string `json:"id"` | ||
| } | ||
|
|
||
| type WebViewGotoParams struct { | ||
| DeviceID string `json:"deviceId"` | ||
| WebViewID string `json:"id"` | ||
| URL string `json:"url"` | ||
| WaitUntil string `json:"waitUntil,omitempty"` | ||
| } | ||
|
|
||
| type WebViewReloadParams struct { | ||
| DeviceID string `json:"deviceId"` | ||
| WebViewID string `json:"id"` | ||
| WaitUntil string `json:"waitUntil,omitempty"` | ||
| } | ||
|
|
||
| type WebViewEvaluateParams struct { | ||
| DeviceID string `json:"deviceId"` | ||
| WebViewID string `json:"id"` | ||
| Expression string `json:"expression"` | ||
| Args []any `json:"args,omitempty"` | ||
| } | ||
|
|
||
| type WebViewWaitForLoadStateParams struct { | ||
| DeviceID string `json:"deviceId"` | ||
| WebViewID string `json:"id"` | ||
| State string `json:"state,omitempty"` | ||
| Timeout int `json:"timeout,omitempty"` | ||
| } | ||
|
Comment on lines
+41
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Using Suggested fix type WebViewWaitForLoadStateParams struct {
DeviceID string `json:"deviceId"`
WebViewID string `json:"id"`
State string `json:"state,omitempty"`
- Timeout int `json:"timeout,omitempty"`
+ Timeout *int `json:"timeout,omitempty"`
} return voidOf(commands.WebViewWaitForLoadStateCommand(commands.WebViewWaitForLoadStateRequest{
DeviceID: p.DeviceID,
WebViewID: p.WebViewID,
State: p.State,
Timeout: p.Timeout,
}))And align Also applies to: 186-191 🤖 Prompt for AI Agents |
||
|
|
||
| // ─── Shared helpers ─────────────────────────────────────────── | ||
|
|
||
| func unmarshal[T any](params json.RawMessage) (T, error) { | ||
| var p T | ||
| if err := json.Unmarshal(params, &p); err != nil { | ||
| return p, fmt.Errorf("invalid parameters: %w", err) | ||
| } | ||
| return p, nil | ||
| } | ||
|
|
||
| func resultOf(resp *commands.CommandResponse) (any, error) { | ||
| if resp.Status == "error" { | ||
| return nil, fmt.Errorf("%s", resp.Error) | ||
| } | ||
| return resp.Data, nil | ||
| } | ||
|
|
||
| func voidOf(resp *commands.CommandResponse) (any, error) { | ||
| if resp.Status == "error" { | ||
| return nil, fmt.Errorf("%s", resp.Error) | ||
| } | ||
| return okResponse, nil | ||
| } | ||
|
Comment on lines
+50
to
+70
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Either move these helpers to a shared file (e.g. |
||
|
|
||
| func requireWebViewParams(deviceID, webViewID string) error { | ||
| if deviceID == "" { | ||
| return fmt.Errorf("deviceId is required") | ||
| } | ||
| if webViewID == "" { | ||
| return fmt.Errorf("id is required") | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| // ─── Handlers ───────────────────────────────────────────────── | ||
|
|
||
| func handleWebViewList(params json.RawMessage) (any, error) { | ||
| p, err := unmarshal[WebViewListParams](params) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if p.DeviceID == "" { | ||
| return nil, fmt.Errorf("deviceId is required") | ||
| } | ||
| return resultOf(commands.WebViewListCommand(commands.WebViewListRequest{ | ||
| DeviceID: p.DeviceID, | ||
| })) | ||
| } | ||
|
|
||
| func handleWebViewGoto(params json.RawMessage) (any, error) { | ||
| p, err := unmarshal[WebViewGotoParams](params) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if err := requireWebViewParams(p.DeviceID, p.WebViewID); err != nil { | ||
| return nil, err | ||
| } | ||
| if p.URL == "" { | ||
| return nil, fmt.Errorf("url is required") | ||
| } | ||
| return voidOf(commands.WebViewGotoCommand(commands.WebViewGotoRequest{ | ||
| DeviceID: p.DeviceID, | ||
| WebViewID: p.WebViewID, | ||
| URL: p.URL, | ||
| WaitUntil: p.WaitUntil, | ||
| })) | ||
| } | ||
|
|
||
| func handleWebViewReload(params json.RawMessage) (any, error) { | ||
| p, err := unmarshal[WebViewReloadParams](params) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if err := requireWebViewParams(p.DeviceID, p.WebViewID); err != nil { | ||
| return nil, err | ||
| } | ||
| return voidOf(commands.WebViewReloadCommand(commands.WebViewReloadRequest{ | ||
| DeviceID: p.DeviceID, | ||
| WebViewID: p.WebViewID, | ||
| WaitUntil: p.WaitUntil, | ||
| })) | ||
| } | ||
|
|
||
| func handleWebViewGoBack(params json.RawMessage) (any, error) { | ||
| p, err := unmarshal[WebViewParams](params) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if err := requireWebViewParams(p.DeviceID, p.WebViewID); err != nil { | ||
| return nil, err | ||
| } | ||
| return voidOf(commands.WebViewGoBackCommand(commands.WebViewRequest{ | ||
| DeviceID: p.DeviceID, | ||
| WebViewID: p.WebViewID, | ||
| })) | ||
| } | ||
|
|
||
| func handleWebViewGoForward(params json.RawMessage) (any, error) { | ||
| p, err := unmarshal[WebViewParams](params) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if err := requireWebViewParams(p.DeviceID, p.WebViewID); err != nil { | ||
| return nil, err | ||
| } | ||
| return voidOf(commands.WebViewGoForwardCommand(commands.WebViewRequest{ | ||
| DeviceID: p.DeviceID, | ||
| WebViewID: p.WebViewID, | ||
| })) | ||
| } | ||
|
|
||
| func handleWebViewEvaluate(params json.RawMessage) (any, error) { | ||
| p, err := unmarshal[WebViewEvaluateParams](params) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if err := requireWebViewParams(p.DeviceID, p.WebViewID); err != nil { | ||
| return nil, err | ||
| } | ||
| if p.Expression == "" { | ||
| return nil, fmt.Errorf("expression is required") | ||
| } | ||
| return resultOf(commands.WebViewEvaluateCommand(commands.WebViewEvaluateRequest{ | ||
| DeviceID: p.DeviceID, | ||
| WebViewID: p.WebViewID, | ||
| Expression: p.Expression, | ||
| Args: p.Args, | ||
| })) | ||
| } | ||
|
|
||
| func handleWebViewWaitForLoadState(params json.RawMessage) (any, error) { | ||
| p, err := unmarshal[WebViewWaitForLoadStateParams](params) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if err := requireWebViewParams(p.DeviceID, p.WebViewID); err != nil { | ||
| return nil, err | ||
| } | ||
| return voidOf(commands.WebViewWaitForLoadStateCommand(commands.WebViewWaitForLoadStateRequest{ | ||
| DeviceID: p.DeviceID, | ||
| WebViewID: p.WebViewID, | ||
| State: p.State, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When if p.State == "" {
p.State = "load"
}The CLI defaults |
||
| Timeout: p.Timeout, | ||
| })) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both
WaitUntilfields (here and inWebViewReloadRequest) and theArgsfield here are dead from the CLI layer —cli/webview.goregisters no--wait-untilor--argflags, so they will always be zero-value when called from the CLI.Either add the flags, or remove the fields from these command-layer structs and keep them only in the server-layer params structs (
WebViewGotoParams, etc.), which already carry them correctly.