1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use dioxus::prelude::*;
use matrix_sdk::ruma::OwnedRoomId;
use crate::components::modal::Modal;
use crate::state::app_state::AppState;
/// Location sharing dialog - allows entering coordinates manually.
#[component]
pub fn LocationPicker(
room_id: String,
on_close: EventHandler<()>,
) -> Element {
let state = use_context::<Signal<AppState>>();
let mut latitude = use_signal(|| String::new());
let mut longitude = use_signal(|| String::new());
let mut description = use_signal(|| String::new());
let mut is_sending = use_signal(|| false);
let mut error_msg = use_signal(|| Option::<String>::None);
let can_send = !latitude.read().is_empty() && !longitude.read().is_empty();
rsx! {
Modal {
title: "Share Location".to_string(),
on_close: move |_| on_close.call(()),
div {
class: "location-picker",
p {
class: "location-picker__hint",
"Enter coordinates to share a location."
}
div {
class: "location-picker__field",
label { "Latitude" }
input {
r#type: "text",
placeholder: "e.g. 40.7128",
value: "{latitude}",
oninput: move |evt| latitude.set(evt.value()),
}
}
div {
class: "location-picker__field",
label { "Longitude" }
input {
r#type: "text",
placeholder: "e.g. -74.0060",
value: "{longitude}",
oninput: move |evt| longitude.set(evt.value()),
}
}
div {
class: "location-picker__field",
label { "Description (optional)" }
input {
r#type: "text",
placeholder: "e.g. Meeting point",
value: "{description}",
oninput: move |evt| description.set(evt.value()),
}
}
if let Some(ref err) = *error_msg.read() {
div { class: "location-picker__error", "{err}" }
}
div {
class: "location-picker__actions",
button {
class: "btn btn--secondary",
onclick: move |_| on_close.call(()),
"Cancel"
}
button {
class: "btn btn--primary",
disabled: !can_send || *is_sending.read(),
onclick: move |_| {
let lat = latitude.read().clone();
let lon = longitude.read().clone();
let desc = description.read().clone();
let rid = room_id.clone();
is_sending.set(true);
spawn(async move {
let client = { state.read().client.clone() };
if let Some(client) = client {
if let Ok(room_id) = OwnedRoomId::try_from(rid.as_str()) {
if let Some(room) = client.get_room(&room_id) {
let geo_uri = format!("geo:{},{}", lat, lon);
let body = if desc.is_empty() {
format!("Location: {}, {}", lat, lon)
} else {
format!("{} ({}, {})", desc, lat, lon)
};
use matrix_sdk::ruma::events::room::message::RoomMessageEventContent;
use matrix_sdk::ruma::events::room::message::LocationMessageEventContent;
let location_content = LocationMessageEventContent::new(body, geo_uri);
let content = RoomMessageEventContent::new(
matrix_sdk::ruma::events::room::message::MessageType::Location(location_content),
);
match room.send(content).await {
Ok(_) => {
tracing::info!("Location sent");
on_close.call(());
}
Err(e) => {
error_msg.set(Some(format!("Failed to send: {e}")));
}
}
}
}
}
is_sending.set(false);
});
},
if *is_sending.read() { "Sending..." } else { "Share Location" }
}
}
}
}
}
}