Skip to content

Commit

Permalink
feat(prompt): add prompt support (#250)
Browse files Browse the repository at this point in the history
* feat(context-menu): create webview on wayland

* dynamic generate menu items on html

* add context_menu.html

* add check mouse hit on context-menu webview

* fix: context menu prompt back to verso

* feat(context-menu): on linux, handle selection

* fix: disble right click on context menu

* organize code

* adding cfg target linux

* fix(linux): shift context menu to avoid overflow, best effort

* prompt temp

* add alert prompt

* refactor: move prompt and context menu to components

* remove redundant import

* feat(prompt): add ok/cancel, yes/no prompt

* feat(prompt): add input prompt dialog

* fix: add serde to all platform's dep

* refactor: organize verso html files

* update gitignore

* refactor: remove dialog show method depends on Window

* refactor: code clean

* fix: don't show context menu when prompt exist

* update css

* fix(prompt): handle resize when prompt exists

* fix(prompt): close prompt when navigate to new url

* chore: restore default home page

* chore: fix linux mod path, remove unused pipeline fn

* feat: handle EmbedderMsg::PromptPermission

* refactor: rename components to webview and move WebView into it
  • Loading branch information
pewsheen authored Dec 4, 2024
1 parent 0bcade2 commit 6ca28dd
Show file tree
Hide file tree
Showing 17 changed files with 741 additions and 32 deletions.
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ Cargo.lock
libmozjs*
cargo-sources.json

resources/
!resources/panel.html
!resources/context-menu.html
resources/*
!resources/components/
!resources/prefs.json
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,6 @@ cargo-packager-resource-resolver = { version = "0.1.1", features = [
url = { workspace = true }
headers = "0.3"
versoview_messages = { path = "./versoview_messages" }

[target.'cfg(all(unix, not(apple), not(android)))'.dependencies]
serde_json = "1.0"
serde = { workspace = true }

Expand Down
File renamed without changes.
File renamed without changes.
54 changes: 54 additions & 0 deletions resources/components/prompt/alert.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<html>
<head>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
margin: 0;
background-color: #7d818644;
}
.dialog {
display: flex;
background: #ffffff;
width: 400px;
min-height: 110px;
max-height: 300px;
flex-direction: column;
align-items: center;
border-radius: 10px;
box-shadow: 0 0 50px #ccc;
box-sizing: border-box;
padding: 8px;
gap: 8px;
}
.msg {
display: inline-block;
width: 100%;
min-height: 90px;
text-align: center;
}
</style>
</head>
<body>
<div class="dialog">
<div id="msg" class="msg"></div>
<button onclick="sendToVersoAndClose()">Ok</button>
</div>
</body>
<script>
let url = URL.parse(window.location.href);
let msg = url.searchParams.get('msg');

// Set dialog message
const msgEl = document.getElementById('msg');
msgEl.textContent = msg ?? '';

function sendToVersoAndClose() {
window.alert(''); // Use as an IPC between Verso and WebView
window.close();
}
</script>
</html>
57 changes: 57 additions & 0 deletions resources/components/prompt/ok_cancel.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<html>
<head>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
margin: 0;
background-color: #7d818644;
}
.dialog {
display: flex;
background: #ffffff;
width: 400px;
min-height: 110px;
max-height: 300px;
flex-direction: column;
align-items: center;
border-radius: 10px;
box-shadow: 0 0 50px #ccc;
box-sizing: border-box;
padding: 8px;
gap: 8px;
}
.msg {
display: inline-block;
width: 100%;
min-height: 90px;
text-align: center;
}
</style>
</head>
<body>
<div class="dialog">
<div id="msg" class="msg"></div>
<div class="btn-group">
<button onclick="sendToVersoAndClose('cancel')">Cancel</button>
<button onclick="sendToVersoAndClose('ok')">Ok</button>
</div>
</div>
</body>
<script>
let url = URL.parse(window.location.href);
let msg = url.searchParams.get('msg');

// Set dialog message
const msgEl = document.getElementById('msg');
msgEl.textContent = msg ?? '';

function sendToVersoAndClose(action) {
window.alert(action); // Use as an IPC between Verso and WebView
window.close();
}
</script>
</html>
72 changes: 72 additions & 0 deletions resources/components/prompt/prompt.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<html>
<head>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
margin: 0;
background-color: #7d818644;
}
.dialog {
display: flex;
background: #ffffff;
width: 400px;
min-height: 110px;
max-height: 300px;
flex-direction: column;
align-items: center;
border-radius: 10px;
box-shadow: 0 0 50px #ccc;
box-sizing: border-box;
padding: 8px;
gap: 8px;
}
.msg {
display: inline-block;
width: 100%;
min-height: 90px;
text-align: center;
}
</style>
</head>
<body>
<div class="dialog">
<div id="msg" class="msg"></div>
<input type="text" id="input" />
<div class="btn-group">
<button onclick="sendToVersoAndClose('cancel')">Cancel</button>
<button onclick="sendToVersoAndClose('ok')">Ok</button>
</div>
</div>
</body>
<script>
const inputEl = document.getElementById('input');
const msgEl = document.getElementById('msg');

const params = URL.parse(window.location.href).searchParams;

// Set input default value
const defaultValue = params.get('defaultValue');
if (typeof defaultValue === 'string' || defaultValue instanceof String) {
inputEl.defaultValue = defaultValue;
}

// Set dialog message
const msg = params.get('msg');
msgEl.textContent = msg ?? '';

function sendToVersoAndClose(action) {
// Use as an IPC between Verso and WebView
window.alert(
JSON.stringify({
action,
value: inputEl.value,
})
);
window.close();
}
</script>
</html>
30 changes: 30 additions & 0 deletions resources/components/prompt/prompt_test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<html>
<body>
<div style="display: block">
<button onclick="window.alert('<a> HREF </a>');">alert</button>
<button onclick="sendConfirm();">confirm</button>
<button onclick="sendPrompt('');">prompt</button>
<button onclick="sendPrompt(null, '>> default value >>');">
prompt with default value
</button>
</div>

<div style="display: inline-block" id="result"></div>

<script>
const resultEl = document.getElementById('result');

function sendConfirm(text) {
let result = window.confirm(text);
resultEl.textContent = JSON.stringify(result);
console.log(result);
}

function sendPrompt(text, defaultValue) {
let result = window.prompt(text, defaultValue);
resultEl.textContent = JSON.stringify(result);
console.log(result);
}
</script>
</body>
</html>
57 changes: 57 additions & 0 deletions resources/components/prompt/yes_no.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<html>
<head>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
margin: 0;
background-color: #7d818644;
}
.dialog {
display: flex;
background: #ffffff;
width: 400px;
min-height: 110px;
max-height: 300px;
flex-direction: column;
align-items: center;
border-radius: 10px;
box-shadow: 0 0 50px #ccc;
box-sizing: border-box;
padding: 8px;
gap: 8px;
}
.msg {
display: inline-block;
width: 100%;
min-height: 90px;
text-align: center;
}
</style>
</head>
<body>
<div class="dialog">
<div id="msg" class="msg"></div>
<div class="btn-group">
<button onclick="sendToVersoAndClose('no')">No</button>
<button onclick="sendToVersoAndClose('yes')">Yes</button>
</div>
</div>
</body>
<script>
let url = URL.parse(window.location.href);
let msg = url.searchParams.get('msg');

// Set dialog message
const msgEl = document.getElementById('msg');
msgEl.textContent = msg ?? '';

function sendToVersoAndClose(action) {
window.alert(action); // Use as an IPC between Verso and WebView
window.close();
}
</script>
</html>
17 changes: 4 additions & 13 deletions src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -916,19 +916,6 @@ impl IOCompositor {
.expect("Insert then get failed!")
}

fn pipeline(&self, pipeline_id: PipelineId) -> Option<&CompositionPipeline> {
match self.pipeline_details.get(&pipeline_id) {
Some(details) => details.pipeline.as_ref(),
None => {
warn!(
"Compositor layer has an unknown pipeline ({:?}).",
pipeline_id
);
None
}
}
}

/// Set the root pipeline for our WebRender scene to a display list that consists of an iframe
/// for each visible top-level browsing context, applying a transformation on the root for
/// pinch zoom, page zoom, and HiDPI scaling.
Expand Down Expand Up @@ -1246,6 +1233,10 @@ impl IOCompositor {
w.set_size(content_size);
self.on_resize_webview_event(w.webview_id, w.rect);
}
if let Some(prompt) = &mut window.prompt {
prompt.resize(content_size);
self.on_resize_webview_event(prompt.webview().webview_id, rect);
}

self.send_root_pipeline_display_list(window);
}
Expand Down
4 changes: 3 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,9 @@ impl ProtocolHandler for ResourceReader {
_done_chan: &mut net::fetch::methods::DoneChannel,
_context: &net::fetch::methods::FetchContext,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Response> + Send>> {
let path = self.0.join(request.current_url().domain().unwrap());
let current_url = request.current_url();
let path = current_url.path();
let path = self.0.join(path.strip_prefix('/').unwrap_or(path));

let response = if let Ok(file) = fs::read(path) {
let mut response = Response::new(
Expand Down
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,3 @@ pub use errors::{Error, Result};
pub use verso::Verso;
/// Re-exporting Winit for the sake of convenience.
pub use winit;
/// Context
pub mod context_menu;
8 changes: 6 additions & 2 deletions src/context_menu.rs → src/webview/context_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ impl ContextMenu {
/// Get resource URL of the context menu
fn resource_url(&self) -> ServoUrl {
let items_json: String = self.to_items_json();
let url_str = format!("verso://context_menu.html?items={}", items_json);
let url_str = format!(
"verso://resources/components/context_menu.html?items={}",
items_json
);
ServoUrl::parse(&url_str).unwrap()
}

Expand Down Expand Up @@ -221,8 +224,9 @@ impl MenuItem {
/// Context Menu Click Result
#[cfg(linux)]
#[derive(Debug, Clone, Serialize, Deserialize)]

pub struct ContextMenuResult {
/// The id of the menu ite /// Get the label of the menu item
/// The id of the menu item
pub id: String,
/// Close the context menu
pub close: bool,
Expand Down
7 changes: 7 additions & 0 deletions src/webview/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod webview;
/// WebView
pub use webview::{Panel, WebView};
/// Context Menu
pub mod context_menu;
/// Prompt Dialog
pub mod prompt;
Loading

0 comments on commit 6ca28dd

Please sign in to comment.