Skip to content

Commit

Permalink
Merge pull request #5 from afifurrohman-id/drop
Browse files Browse the repository at this point in the history
fix: fix: Drag and drop api not support on mobile and add message how to swap image
  • Loading branch information
afifurrohman-id authored May 26, 2024
2 parents d067f50 + c4763f6 commit ddc1db2
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 27 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ features = [
"DragEvent",
"HtmlImageElement",
"Headers",
"Navigator",
"Request",
"RequestInit",
"RequestMode",
Expand All @@ -31,7 +32,7 @@ features = [
"Url",
"Blob",
"BlobPropertyBag",
"Window"
"Window",
]

[profile.release]
Expand Down
1 change: 1 addition & 0 deletions assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<body class="notranslate">
<header>
<h1>Pecahkan puzzle nya dan dapatkan kata inggris nya</h1>
<p id="message">Seret dan lepas untuk menukar gambar</p>
</header>

<main>
Expand Down
6 changes: 6 additions & 0 deletions assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ h1 {
font-size: 1rem;
}

p {
text-align: center;
opacity: 0.8;
}

details {
text-align: center;
}
Expand Down Expand Up @@ -96,6 +101,7 @@ img {
border: 2px solid gray;
margin: 2px;
width: 12vw;
touch-action: none;
}

fieldset {
Expand Down
2 changes: 1 addition & 1 deletion compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ services:
command: firebase emulators:start -P $COMPOSE_PROJECT_NAME
volumes:
- ./firebase.json:/home/node/firebase.json
- ./assets:/home/node/assets
- ./assets:/home/node/assets
69 changes: 55 additions & 14 deletions src/display.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
use wasm_bindgen::JsCast;
use web_sys::{DragEvent, HtmlImageElement};
use web_sys::{DragEvent, Element, Event, HtmlImageElement};

use crate::util;

pub fn change_message(msg: &str) {
let document = web_sys::window().unwrap().document().unwrap();
document
.get_element_by_id("message")
.unwrap()
.set_text_content(Some(msg));
}

pub fn toggle_loading(display: bool) {
let document = web_sys::window().unwrap().document().unwrap();

Expand Down Expand Up @@ -51,34 +59,67 @@ pub fn compare_rand_urls(urls: &[String]) -> bool {
urls.eq(&random_urls)
}

pub fn send_src_url(e: DragEvent) {
let el = e.target().unwrap().dyn_into::<HtmlImageElement>().unwrap();
pub fn send_img_src_on_drag(e: DragEvent) {
let t_id = e
.target()
.unwrap()
.dyn_into::<HtmlImageElement>()
.unwrap()
.id();
e.data_transfer().unwrap().clear_data().unwrap();

e.data_transfer()
.unwrap()
.set_data("text/plain", &el.id())
.set_data("text/plain", &t_id)
.unwrap();
}

pub fn swap_url(e: DragEvent) {
let window = web_sys::window().unwrap();
let document = window.document().unwrap();

pub fn swap_img_src_on_drag(e: DragEvent) {
e.prevent_default();
let el = e.target().unwrap().dyn_into::<HtmlImageElement>().unwrap();
let src = el.src();

let document = web_sys::window().unwrap().document().unwrap();

let target = e.target().unwrap().dyn_into::<HtmlImageElement>().unwrap();

let id = e.data_transfer().unwrap().get_data("text/plain").unwrap();
let dst_el = document
let source = document
.get_element_by_id(&id)
.unwrap()
.dyn_into::<HtmlImageElement>()
.unwrap();
let dst_src = dst_el.src();
let temp = target.src();

target.set_src(&source.src());
source.set_src(&temp);
}

pub fn swap_img_src_on_touch(e: Event) {
let document = web_sys::window().unwrap().document().unwrap();
let clicked = document.query_selector(r#"[data-touched="ok"]"#).unwrap();

let t_id = e
.current_target()
.unwrap()
.dyn_into::<Element>()
.unwrap()
.id();

let target = document
.get_element_by_id(&t_id)
.unwrap()
.dyn_into::<HtmlImageElement>()
.unwrap();

dst_el.set_src(&src);
el.set_src(&dst_src);
if let Some(clicked) = clicked {
let clicked = clicked.dyn_into::<HtmlImageElement>().unwrap();

let temp = target.src();
target.set_src(&clicked.src());
clicked.set_src(&temp);
clicked.remove_attribute("data-touched").unwrap()
} else {
target.set_attribute("data-touched", "ok").unwrap();
}
}

pub fn display_img_url(id: usize, url: &str) {
Expand Down
41 changes: 32 additions & 9 deletions src/puzzle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,69 @@ use std::rc::Rc;

use wasm_bindgen::closure::Closure;
use wasm_bindgen::JsCast;
use web_sys::{DragEvent, Element, HtmlImageElement, HtmlLabelElement};
use web_sys::{DragEvent, Element, Event, HtmlImageElement, HtmlLabelElement};

use crate::{data::Data, display, util};

pub fn puzzle_handler(urls: Vec<String>, data: Data) {
let document = web_sys::window().unwrap().document().unwrap();
let imgs = document.query_selector_all("figure img").unwrap();

let drag_over_handler =
Closure::new(Box::new(|e: DragEvent| e.prevent_default()) as Box<dyn FnMut(_)>);

let urls = Rc::new(urls);
let data = Rc::new(data);

let drag_over_handler =
Closure::new(Box::new(|e: DragEvent| e.prevent_default()) as Box<dyn FnMut(_)>);

for i in 0..imgs.length() {
let img = imgs
.item(i)
.unwrap()
.dyn_into::<HtmlImageElement>()
.unwrap();

let urls = Rc::clone(&urls);
let data = Rc::clone(&data);

if util::is_mobile() && !util::support_drag_drop() {
display::change_message("Tekan 2 gambar untuk menukarnya");

let click_handler = Closure::new(Box::new(move |e: Event| {
display::swap_img_src_on_touch(e);

let ok = display::compare_rand_urls(&urls);
if ok {
success_handler(&data);
}
}) as Box<dyn FnMut(_)>);

img.add_event_listener_with_callback(
"touchstart",
click_handler.as_ref().unchecked_ref(),
)
.unwrap();

click_handler.forget();
continue;
}

img.add_event_listener_with_callback(
"dragover",
drag_over_handler.as_ref().unchecked_ref(),
)
.unwrap();

let drag_start_handler = Closure::new(Box::new(display::send_src_url) as Box<dyn FnMut(_)>);
let drag_start_handler =
Closure::new(Box::new(display::send_img_src_on_drag) as Box<dyn FnMut(_)>);

img.add_event_listener_with_callback(
"dragstart",
drag_start_handler.as_ref().unchecked_ref(),
)
.unwrap();

let urls = Rc::clone(&urls);
let data = Rc::clone(&data);

let drop_handler = Closure::new(Box::new(move |e: DragEvent| {
display::swap_url(e);
display::swap_img_src_on_drag(e);

let ok = display::compare_rand_urls(&urls);
if ok {
Expand Down
26 changes: 24 additions & 2 deletions src/util.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
use std::fmt::Display;

use wasm_bindgen::JsValue;
use wasm_bindgen::{JsCast, JsValue};
use web_sys::{
js_sys::{Array, Math, Uint8Array},
Blob, BlobPropertyBag,
Blob, BlobPropertyBag, HtmlElement,
};

pub fn is_mobile() -> bool {
let window = web_sys::window().unwrap();

let touch_start_exists = window.ontouchstart().is_some();
let touch_points = window.navigator().max_touch_points();
touch_start_exists || touch_points > 0
}

pub fn support_drag_drop() -> bool {
let document = web_sys::window().unwrap().document().unwrap();
let div = document
.create_element("div")
.unwrap()
.dyn_into::<HtmlElement>()
.unwrap();

div.draggable()
&& div.ondragstart().is_some()
&& div.ondrop().is_some()
&& div.ondragover().is_some()
}

pub fn js_buffer_to_bytes(js_buff: &JsValue) -> Vec<u8> {
let js_bytes = Uint8Array::new(js_buff);
js_bytes.to_vec()
Expand Down

0 comments on commit ddc1db2

Please sign in to comment.