Skip to content
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

Support query string in Wasm example #128

Merged
merged 6 commits into from
Jul 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/wasm/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
rustflags = ["--cfg=web_sys_unstable_apis"]
25 changes: 14 additions & 11 deletions examples/wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@ version = "0.1.0"
edition = "2021"

[dependencies]
gloo-worker = "0.2.1" # MIT or Apache-2.0
i18n-embed = { version = "0.13.8", features = ["fluent-system", "web-sys-requester"]} # MIT
i18n-embed-fl = "0.6.5" # MIT
once_cell = "1.17.0" # MIT or Apache-2.0
ouroboros = "0.17.2" # MIT or Apache-2.0
rust-embed = "6.4.2" # MIT
ruzstd = "0.5.0" # MIT
gloo-timers = "0.3.0" # MIT or Apache-2.0
gloo-worker = "0.5.0" # MIT or Apache-2.0
i18n-embed = { version = "0.14.1", features = ["fluent-system", "web-sys-requester"]} # MIT
i18n-embed-fl = "0.8.0" # MIT
js-sys = "0.3.69" # MIT or Apache-2.0
once_cell = "1.19.0" # MIT or Apache-2.0
ouroboros = "0.18.4" # MIT or Apache-2.0
rust-embed = "8.5.0" # MIT
ruzstd = "0.7.0" # MIT
serde = "1" # MIT or Apache-2.0
unic-langid = { version = "0.9.1", features = ["macros"] } # MIT or Apache-2.0
unic-langid = { version = "0.9.5", features = ["macros"] } # MIT or Apache-2.0
vaporetto = { path = "../../vaporetto", default-features = false, features = ["std", "cache-type-score", "fix-weight-length", "tag-prediction"] } # MIT or Apache-2.0
vaporetto_rules = { path = "../../vaporetto_rules" } # MIT or Apache-2.0
wasm-bindgen = "0.2.83" # MIT or Apache-2.0
web-sys = { version = "0.3.61", features = ["Event", "EventTarget", "InputEvent"] } # MIT or Apache-2.0
yew = { version = "0.20", features = ["csr"] } # MIT or Apache-2.0
wasm-bindgen = "0.2.92" # MIT or Apache-2.0
wasm-bindgen-futures = "0.4.42" # MIT or Apache-2.0
web-sys = { version = "0.3.69", features = ["Clipboard", "Event", "EventTarget", "InputEvent"] } # MIT or Apache-2.0
yew = { version = "0.21", features = ["csr"] } # MIT or Apache-2.0

[profile.release]
panic = "abort"
Expand Down
25 changes: 25 additions & 0 deletions examples/wasm/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
color: #fff;
}

html {
max-width: 1000px;
margin: 0 auto;
}

body {
width: calc(100% - 20px);
margin: 10px;
Expand All @@ -39,6 +44,26 @@
text-align: right;
}

.input-bar {
display: flex;
flex-direction: row;
}

.input-bar button {
font-size: 14pt;
align-self: center;
background-color: #ffffff;
border: 1px solid #000000;
}

.input-bar button:hover {
background-color: #dddddd;
}

.input-bar button.copied {
background-color: #008800;
}

a {
color: #000;
}
Expand Down
41 changes: 20 additions & 21 deletions examples/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use vaporetto_rules::{
string_filters::KyteaFullwidthFilter,
SentenceFilter, StringFilter,
};
use web_sys::UrlSearchParams;
use yew::{html, Component, Context, Html};

use crate::text_input::TextInput;
Expand All @@ -38,10 +39,10 @@ pub struct VaporettoWorker {

#[borrows(predictor)]
#[covariant]
sentence_orig: Sentence<'static, 'this>,
sentence_filtered: Sentence<'static, 'this>,
#[borrows(predictor)]
#[covariant]
sentence_filtered: Sentence<'static, 'this>,
sentence_orig: Sentence<'static, 'this>,
}

impl Worker for VaporettoWorker {
Expand Down Expand Up @@ -150,13 +151,19 @@ impl Component for App {
})
.spawn("./vaporetto_worker.js");

// Sends a dummy message.
// The first response indicates that the worker is ready.
bridge.send(String::new());
let text = web_sys::window()
.unwrap()
.location()
.search()
.ok()
.and_then(|s| UrlSearchParams::new_with_str(&s).ok())
.and_then(|q| q.get("text"))
.unwrap_or_else(String::new);
bridge.send(text.clone());

Self {
bridge,
text: String::new().into(),
text: text.into(),
tokens: None,
n_tags: 0,
}
Expand Down Expand Up @@ -186,22 +193,14 @@ impl Component for App {
</p>
</header>
<main>
<div>
{
if self.tokens.is_some() {
html! {
<TextInput
callback={ctx.link().callback(Msg::SetText)}
value={Rc::clone(&self.text)}
/>
}
} else {
html!{
<input type="text" disabled=true />
}
}
{
html! {
<TextInput
callback={ctx.link().callback(Msg::SetText)}
value={self.tokens.is_some().then(|| Rc::clone(&self.text))}
/>
}
</div>
}
{
if let Some(tokens) = &self.tokens {
html! {
Expand Down
94 changes: 74 additions & 20 deletions examples/wasm/src/text_input.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use std::rc::Rc;

use wasm_bindgen::{JsCast, UnwrapThrowExt};
use web_sys::{Event, HtmlInputElement, InputEvent};
use yew::{html, Callback, Component, Context, Html, NodeRef, Properties};
use gloo_timers::callback::Timeout;
use wasm_bindgen_futures::JsFuture;
use web_sys::HtmlInputElement;
use yew::{html, platform::spawn_local, Callback, Component, Context, Html, NodeRef, Properties};

use crate::fl;

#[derive(Clone, PartialEq, Properties)]
pub struct Props {
pub value: Rc<String>,
pub value: Option<Rc<String>>,
pub callback: Callback<String>,
}

pub struct TextInput {
node_ref: NodeRef,
input_ref: NodeRef,
button_ref: NodeRef,
}

impl Component for TextInput {
Expand All @@ -22,29 +24,81 @@ impl Component for TextInput {

fn create(_ctx: &Context<Self>) -> Self {
Self {
node_ref: NodeRef::default(),
input_ref: NodeRef::default(),
button_ref: NodeRef::default(),
}
}

fn view(&self, ctx: &Context<Self>) -> Html {
let Props { value, callback } = ctx.props();
let callback = callback.clone();

let oninput = Callback::from(move |e: InputEvent| {
let event: Event = e.dyn_into().unwrap_throw();
let event_target = event.target().unwrap_throw();
let target: HtmlInputElement = event_target.dyn_into().unwrap_throw();
callback.emit(target.value());
let input_ref = self.input_ref.clone();
let oninput = Callback::from(move |_| {
let input = input_ref.cast::<HtmlInputElement>().unwrap();
callback.emit(input.value());
});

html! {
<input
ref={self.node_ref.clone()}
type="text"
placeholder={ fl!("place-holder") }
value={value.to_string()}
{oninput}
/>
let input_ref = self.input_ref.clone();
let button_ref = self.button_ref.clone();
let clipboard_click = Callback::from(move |_| {
let input = input_ref.cast::<HtmlInputElement>().unwrap();
if let Some(clipboard) = web_sys::window().unwrap().navigator().clipboard() {
let loc = web_sys::window().unwrap().location();
let content = format!(
"{}{}?text={}",
loc.origin().unwrap(),
loc.pathname().unwrap(),
js_sys::encode_uri_component(&input.value())
);
let promise = clipboard.write_text(&content);
let button_ref = button_ref.clone();
spawn_local(async move {
JsFuture::from(promise).await.unwrap();
let button = button_ref.cast::<HtmlInputElement>().unwrap();
button.set_class_name("copied");
let button_ref = button_ref.clone();
let timeout = Timeout::new(1000, move || {
let button = button_ref.cast::<HtmlInputElement>().unwrap();
button.set_class_name("");
});
timeout.forget();
});
}
});
if let Some(value) = value.as_ref() {
html! {
<div class="input-bar">
<input
ref={self.input_ref.clone()}
type="text"
placeholder={ fl!("place-holder") }
value={value.to_string()}
{oninput}
/>
<button
ref={self.button_ref.clone()}
onclick={clipboard_click}
>
{"🔗"}
</button>
</div>
}
} else {
html! {
<div class="input-bar">
<input
type="text"
placeholder={ fl!("place-holder") }
disabled=true
/>
<button
disabled=true
>
{"🔗"}
</button>
</div>
}
}
}

Expand All @@ -54,7 +108,7 @@ impl Component for TextInput {

fn rendered(&mut self, _ctx: &Context<Self>, first_render: bool) {
if first_render {
if let Some(input) = self.node_ref.cast::<HtmlInputElement>() {
if let Some(input) = self.input_ref.cast::<HtmlInputElement>() {
input.focus().unwrap();
}
}
Expand Down
1 change: 1 addition & 0 deletions vaporetto/src/dict_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use bincode::{Decode, Encode};

use crate::errors::{Result, VaporettoError};

#[cfg(feature = "kytea")]
#[derive(Clone, Copy, Default)]
pub struct DictWeight {
pub right: i32,
Expand Down
Loading