Verification, message sending
This commit is contained in:
parent
eac3d4bc3f
commit
f828837efe
|
@ -7,7 +7,7 @@ use eframe::NativeOptions;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
fn main() {
|
fn main() {
|
||||||
let app = ui::App::default();
|
let app = ui::App::default();
|
||||||
let mut options = NativeOptions::default();
|
let options = NativeOptions::default();
|
||||||
options.transparent = true;
|
//options.transparent = true;
|
||||||
eframe::run_native(Box::new(app), options);
|
eframe::run_native(Box::new(app), options);
|
||||||
}
|
}
|
||||||
|
|
71
src/sync.rs
71
src/sync.rs
|
@ -7,8 +7,11 @@ use std::sync::{
|
||||||
|
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use matrix_sdk::{
|
use matrix_sdk::{
|
||||||
|
encryption::verification::{
|
||||||
|
QrVerification, SasVerification, Verification, VerificationRequest,
|
||||||
|
},
|
||||||
room::Joined,
|
room::Joined,
|
||||||
ruma::{RoomId, UserId},
|
ruma::{events::room::message::MessageEventContent, RoomId, UserId},
|
||||||
Client, RoomMember,
|
Client, RoomMember,
|
||||||
};
|
};
|
||||||
use tokio::sync::{mpsc::UnboundedReceiver, Notify};
|
use tokio::sync::{mpsc::UnboundedReceiver, Notify};
|
||||||
|
@ -22,10 +25,25 @@ pub enum Request {
|
||||||
Login(Url, String, String),
|
Login(Url, String, String),
|
||||||
/// Restore session
|
/// Restore session
|
||||||
Restore(matrix_sdk::Session),
|
Restore(matrix_sdk::Session),
|
||||||
/// Get the calculated name for a room
|
/// Get the calculated name for a room.
|
||||||
RoomName(RoomId),
|
RoomName(RoomId),
|
||||||
|
/// Send a message to a room.
|
||||||
|
Message(Joined, String),
|
||||||
/// Get a member from a joined room
|
/// Get a member from a joined room
|
||||||
JoinedMember(Joined, UserId),
|
JoinedMember(Joined, UserId),
|
||||||
|
/// Get the verification request with the flow id.
|
||||||
|
VerifyRequest(UserId, String),
|
||||||
|
/// Cancel a verification attempt.
|
||||||
|
VerifyCancel(VerificationRequest),
|
||||||
|
/// Accept a verification request.
|
||||||
|
VerifyAccept(VerificationRequest),
|
||||||
|
/// Find an active verification with the flow id.
|
||||||
|
VerifyStart(UserId, String),
|
||||||
|
/// Start SAS verification flow.
|
||||||
|
VerifyStartSas(VerificationRequest),
|
||||||
|
VerifySasConfirm(SasVerification),
|
||||||
|
/// Start QR code verification flow.
|
||||||
|
VerifyStartQr(VerificationRequest),
|
||||||
/// Stop syncing
|
/// Stop syncing
|
||||||
Quit,
|
Quit,
|
||||||
}
|
}
|
||||||
|
@ -38,6 +56,12 @@ pub enum Response {
|
||||||
RoomName(RoomId, String),
|
RoomName(RoomId, String),
|
||||||
/// Retrived a member frmo a joined room.
|
/// Retrived a member frmo a joined room.
|
||||||
JoinedMember(RoomId, RoomMember),
|
JoinedMember(RoomId, RoomMember),
|
||||||
|
/// Got a verification request.
|
||||||
|
VerifyRequest(VerificationRequest),
|
||||||
|
/// Started SAS verification.
|
||||||
|
VerifySas(SasVerification),
|
||||||
|
/// Started QR verification.
|
||||||
|
VerifyQr(QrVerification),
|
||||||
/// An error happened while responding to a request
|
/// An error happened while responding to a request
|
||||||
Error(matrix_sdk::Error),
|
Error(matrix_sdk::Error),
|
||||||
}
|
}
|
||||||
|
@ -99,7 +123,48 @@ async fn handle_request(
|
||||||
},
|
},
|
||||||
Request::JoinedMember(room, user) => {
|
Request::JoinedMember(room, user) => {
|
||||||
if let Some(member) = room.get_member(&user).await? {
|
if let Some(member) = room.get_member(&user).await? {
|
||||||
response.send(Response::JoinedMember(room.room_id().clone(), member));
|
response.send(Response::JoinedMember(room.room_id().clone(), member))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Request::Message(room, message) => {
|
||||||
|
let event = MessageEventContent::text_plain(message);
|
||||||
|
room.send(event, None).await?;
|
||||||
|
}
|
||||||
|
Request::VerifyRequest(user, flow_id) => {
|
||||||
|
let verification = client.get_verification_request(&user, &flow_id).await;
|
||||||
|
if let Some(verification) = verification {
|
||||||
|
response.send(Response::VerifyRequest(verification))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Request::VerifyCancel(verify) => {
|
||||||
|
verify.cancel().await?;
|
||||||
|
}
|
||||||
|
Request::VerifyAccept(verify) => {
|
||||||
|
verify.accept().await?;
|
||||||
|
}
|
||||||
|
Request::VerifyStart(sender, flow_id) => {
|
||||||
|
if let Some(verify) = client.get_verification(&sender, &flow_id).await {
|
||||||
|
match verify {
|
||||||
|
// TODO: auto-accepting is very naughty
|
||||||
|
Verification::SasV1(sas) => {
|
||||||
|
sas.accept().await?;
|
||||||
|
response.send(Response::VerifySas(sas))?
|
||||||
|
}
|
||||||
|
Verification::QrV1(qr) => response.send(Response::VerifyQr(qr))?,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Request::VerifyStartSas(verify) => {
|
||||||
|
if let Some(sas) = verify.start_sas().await? {
|
||||||
|
response.send(Response::VerifySas(sas))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Request::VerifySasConfirm(sas) => {
|
||||||
|
sas.confirm().await?;
|
||||||
|
}
|
||||||
|
Request::VerifyStartQr(verify) => {
|
||||||
|
if let Some(qr) = verify.generate_qr_code().await? {
|
||||||
|
response.send(Response::VerifyQr(qr))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Request::Quit => {
|
Request::Quit => {
|
||||||
|
|
29
src/ui.rs
29
src/ui.rs
|
@ -34,7 +34,11 @@ impl epi::App for App {
|
||||||
storage
|
storage
|
||||||
.get_string("rooms")
|
.get_string("rooms")
|
||||||
.and_then(|s| ron::from_str(&s).ok())
|
.and_then(|s| ron::from_str(&s).ok())
|
||||||
.map(|list| view.room_list = list);
|
.map(|list| view.room_list = dbg!(list));
|
||||||
|
storage
|
||||||
|
.get_string("entry")
|
||||||
|
.and_then(|s| ron::from_str(&s).ok())
|
||||||
|
.map(|entry| view.entry = entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +53,9 @@ impl epi::App for App {
|
||||||
if let Ok(rooms) = ron::to_string(&main.room_list) {
|
if let Ok(rooms) = ron::to_string(&main.room_list) {
|
||||||
storage.set_string("rooms", rooms)
|
storage.set_string("rooms", rooms)
|
||||||
}
|
}
|
||||||
|
if let Ok(entry) = ron::to_string(&main.entry) {
|
||||||
|
storage.set_string("entry", entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +63,7 @@ impl epi::App for App {
|
||||||
fn on_exit(&mut self) {
|
fn on_exit(&mut self) {
|
||||||
match self.view {
|
match self.view {
|
||||||
View::Main(ref mut main) => {
|
View::Main(ref mut main) => {
|
||||||
main.request.send(sync::Request::Quit).ok();
|
main.request.quit();
|
||||||
main.sync_handle.take().map(|t| t.join());
|
main.sync_handle.take().map(|t| t.join());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -100,9 +107,7 @@ impl View {
|
||||||
});
|
});
|
||||||
let view = session::App::new(client, req_tx, res_rx, handle);
|
let view = session::App::new(client, req_tx, res_rx, handle);
|
||||||
for room in view.client.rooms() {
|
for room in view.client.rooms() {
|
||||||
view.request
|
view.request.room_name(room.room_id().clone());
|
||||||
.send(sync::Request::RoomName(room.room_id().clone()))
|
|
||||||
.ok();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*self = View::Main(view);
|
*self = View::Main(view);
|
||||||
|
@ -119,9 +124,23 @@ impl Default for View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Named ID's for widgets that need one.
|
||||||
#[derive(Debug, Clone, Copy, Hash)]
|
#[derive(Debug, Clone, Copy, Hash)]
|
||||||
pub enum Id {
|
pub enum Id {
|
||||||
|
/// Side panel with the room list.
|
||||||
RoomPanel,
|
RoomPanel,
|
||||||
|
/// Top panel with room name an such.
|
||||||
RoomSummary,
|
RoomSummary,
|
||||||
|
/// Panel with members of a room.
|
||||||
MemberList,
|
MemberList,
|
||||||
|
/// Message entry.
|
||||||
|
MessageEntry,
|
||||||
|
/// Error message.
|
||||||
|
ErrorPanel,
|
||||||
|
/// Panel showing verification requests.
|
||||||
|
VerificationPanel,
|
||||||
|
/// Window for a SAS verification session.
|
||||||
|
SasVerification,
|
||||||
|
/// Window for a QR verification session.
|
||||||
|
QrVerification,
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,14 @@ use crossbeam_channel::Receiver;
|
||||||
use eframe::egui::{self, Color32, Label, ScrollArea, Sense};
|
use eframe::egui::{self, Color32, Label, ScrollArea, Sense};
|
||||||
use matrix_sdk::{
|
use matrix_sdk::{
|
||||||
deserialized_responses::SyncResponse,
|
deserialized_responses::SyncResponse,
|
||||||
room::Room,
|
encryption::verification::{SasVerification, Verification, VerificationRequest},
|
||||||
|
room::{Joined, Room},
|
||||||
ruma::{
|
ruma::{
|
||||||
events::{room::message::MessageType, AnyMessageEvent, AnyRoomEvent},
|
events::{
|
||||||
|
key::verification::VerificationMethod,
|
||||||
|
room::{create::RoomType as CreateRoomType, message::MessageType},
|
||||||
|
AnyMessageEvent, AnyRoomEvent, AnyToDeviceEvent,
|
||||||
|
},
|
||||||
RoomId, UserId,
|
RoomId, UserId,
|
||||||
},
|
},
|
||||||
Client, RoomMember,
|
Client, RoomMember,
|
||||||
|
@ -25,13 +30,25 @@ use super::Id;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct App {
|
pub struct App {
|
||||||
pub client: matrix_sdk::Client,
|
pub client: matrix_sdk::Client,
|
||||||
pub request: UnboundedSender<sync::Request>,
|
/// Request sender.
|
||||||
|
pub request: RequestSender,
|
||||||
|
/// Response receiver.
|
||||||
pub response: Receiver<sync::Response>,
|
pub response: Receiver<sync::Response>,
|
||||||
|
/// Handle to the sync loop thread.
|
||||||
pub sync_handle: Option<std::thread::JoinHandle<()>>,
|
pub sync_handle: Option<std::thread::JoinHandle<()>>,
|
||||||
|
/// Error message.
|
||||||
pub error: Option<String>,
|
pub error: Option<String>,
|
||||||
|
/// State of an active verification request.
|
||||||
|
pub verify_req: Option<VerificationRequest>,
|
||||||
|
/// State of a started verification session.
|
||||||
|
pub verify: Option<Verification>,
|
||||||
|
|
||||||
|
/// Data for the room list
|
||||||
pub room_list: RoomList,
|
pub room_list: RoomList,
|
||||||
|
/// Data for storing a timeline
|
||||||
pub timelines: HashMap<RoomId, Timeline>,
|
pub timelines: HashMap<RoomId, Timeline>,
|
||||||
|
/// Message entry
|
||||||
|
pub entry: MessageEntry,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
|
@ -49,6 +66,17 @@ pub struct Timeline {
|
||||||
member_pending: HashSet<UserId>,
|
member_pending: HashSet<UserId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct MessageEntry {
|
||||||
|
text: HashMap<RoomId, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageEntry {
|
||||||
|
pub fn get(&mut self, room: &RoomId) -> &mut String {
|
||||||
|
self.text.entry(room.clone()).or_default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RoomList {
|
impl RoomList {
|
||||||
fn room_name<'a>(&'a self, room: &matrix_sdk::BaseRoom) -> Cow<'a, str> {
|
fn room_name<'a>(&'a self, room: &matrix_sdk::BaseRoom) -> Cow<'a, str> {
|
||||||
if let Some(name) = self.room_name.get(room.room_id()) {
|
if let Some(name) = self.room_name.get(room.room_id()) {
|
||||||
|
@ -85,13 +113,16 @@ impl App {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
client,
|
client,
|
||||||
request,
|
request: RequestSender(request),
|
||||||
response,
|
response,
|
||||||
|
|
||||||
sync_handle: Some(sync_handle),
|
sync_handle: Some(sync_handle),
|
||||||
room_list: RoomList::default(),
|
room_list: RoomList::default(),
|
||||||
error: None,
|
|
||||||
timelines: HashMap::new(),
|
timelines: HashMap::new(),
|
||||||
|
verify_req: None,
|
||||||
|
verify: None,
|
||||||
|
error: None,
|
||||||
|
entry: MessageEntry::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,11 +132,20 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
egui::SidePanel::left(Id::RoomPanel)
|
egui::SidePanel::left(Id::RoomPanel)
|
||||||
.max_width(800.0)
|
.max_width(400.0)
|
||||||
.default_width(400.0)
|
.default_width(400.0)
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.add(egui::Label::new("Joined").strong());
|
ui.add(egui::Label::new("Joined").strong());
|
||||||
for room in self.client.joined_rooms() {
|
|
||||||
|
let mut joined = self.client.joined_rooms();
|
||||||
|
joined.sort_by_key(|room| self.room_list.room_name(&room).to_uppercase());
|
||||||
|
joined.retain(|room| {
|
||||||
|
room.create_content()
|
||||||
|
.and_then(|c| c.room_type)
|
||||||
|
.map_or(true, |t| t != CreateRoomType::Space)
|
||||||
|
});
|
||||||
|
|
||||||
|
for room in joined {
|
||||||
let group = if self.room_list.is_selected(room.room_id()) {
|
let group = if self.room_list.is_selected(room.room_id()) {
|
||||||
egui::Frame::group(&Default::default())
|
egui::Frame::group(&Default::default())
|
||||||
} else {
|
} else {
|
||||||
|
@ -150,11 +190,99 @@ impl App {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if self.error.is_some() {
|
||||||
|
egui::TopBottomPanel::top(Id::ErrorPanel).show(ctx, |ui| {
|
||||||
|
if ui.button("x").clicked() {
|
||||||
|
self.error = None;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ui.label(self.error.as_ref().unwrap());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref verify_req) = self.verify_req {
|
||||||
|
egui::TopBottomPanel::top(Id::VerificationPanel).show(ctx, |ui| {
|
||||||
|
ui.label(format!(
|
||||||
|
"Verification request for {}",
|
||||||
|
verify_req.other_user_id(),
|
||||||
|
));
|
||||||
|
if !verify_req.is_ready() {
|
||||||
|
if verify_req.is_cancelled() {
|
||||||
|
ui.label("Verification attempt canceled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if verify_req.we_started() {
|
||||||
|
ui.label("Waiting for other user to accept verification.");
|
||||||
|
} else {
|
||||||
|
if ui.button("Accept").clicked() {
|
||||||
|
self.request.verify_accept(verify_req.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if verify_req.is_ready() {
|
||||||
|
let methods = verify_req.their_supported_methods().unwrap();
|
||||||
|
for method in methods {
|
||||||
|
if method == VerificationMethod::SasV1 {
|
||||||
|
if ui.button("Verify with emoji").clicked() {
|
||||||
|
self.request.verify_start_sas(verify_req.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ui.button("Cancel").clicked() {
|
||||||
|
self.request.verify_cancel(verify_req.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(verify) = self.verify.clone() {
|
||||||
|
match verify {
|
||||||
|
Verification::SasV1(sas) => {
|
||||||
|
egui::Window::new("Emoji verification")
|
||||||
|
.id(egui::Id::new(Id::SasVerification))
|
||||||
|
.fixed_size([500.0, 300.0])
|
||||||
|
.show(ctx, |ui| {
|
||||||
|
if let Some(cancel) = sas.cancel_info() {
|
||||||
|
ui.label("Verification cancelled");
|
||||||
|
ui.label(cancel.reason());
|
||||||
|
}
|
||||||
|
ui.horizontal_wrapped(|ui| {
|
||||||
|
if let Some(emojis) = sas.emoji() {
|
||||||
|
for (emoji, name) in emojis {
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.set_max_width(50.0);
|
||||||
|
ui.heading(emoji);
|
||||||
|
ui.label(name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
if ui.button("Confirm").clicked() {
|
||||||
|
self.request.verify_sas_confirm(sas);
|
||||||
|
}
|
||||||
|
if ui.button("Close").clicked() {
|
||||||
|
self.verify = None;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Verification::QrV1(_qr) => {
|
||||||
|
egui::Window::new("QR code verification")
|
||||||
|
.id(egui::Id::new(Id::QrVerification))
|
||||||
|
.auto_sized()
|
||||||
|
.show(ctx, |ui| {
|
||||||
|
ui.label("Not implemented yet oops");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let joined = match room {
|
let joined = match room {
|
||||||
Room::Joined(ref room) => room,
|
Room::Joined(ref room) => room,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Main panel with the timeline
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
ScrollArea::auto_sized().show(ui, |ui| {
|
ScrollArea::auto_sized().show(ui, |ui| {
|
||||||
let timeline = self.timelines.entry(room.room_id().clone()).or_default();
|
let timeline = self.timelines.entry(room.room_id().clone()).or_default();
|
||||||
|
@ -164,12 +292,7 @@ impl App {
|
||||||
Some(member) => member.name(),
|
Some(member) => member.name(),
|
||||||
None => {
|
None => {
|
||||||
if !timeline.member_pending.contains(sender) {
|
if !timeline.member_pending.contains(sender) {
|
||||||
self.request
|
self.request.joined_member(joined.clone(), sender.clone());
|
||||||
.send(sync::Request::JoinedMember(
|
|
||||||
joined.clone(),
|
|
||||||
sender.clone(),
|
|
||||||
))
|
|
||||||
.ok();
|
|
||||||
}
|
}
|
||||||
sender.localpart()
|
sender.localpart()
|
||||||
}
|
}
|
||||||
|
@ -178,14 +301,18 @@ impl App {
|
||||||
AnyRoomEvent::Message(AnyMessageEvent::RoomMessage(msg)) => {
|
AnyRoomEvent::Message(AnyMessageEvent::RoomMessage(msg)) => {
|
||||||
match &msg.content.msgtype {
|
match &msg.content.msgtype {
|
||||||
MessageType::Text(text) => {
|
MessageType::Text(text) => {
|
||||||
ui.add(Label::new(name).strong())
|
ui.horizontal_wrapped(|ui| {
|
||||||
.on_hover_text(event.sender());
|
ui.add(Label::new(name).strong())
|
||||||
ui.label(&text.body);
|
.on_hover_text(event.sender());
|
||||||
|
ui.label(&text.body);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
MessageType::Notice(notice) => {
|
MessageType::Notice(notice) => {
|
||||||
ui.add(Label::new(name).strong())
|
ui.horizontal_wrapped(|ui| {
|
||||||
.on_hover_text(event.sender());
|
ui.add(Label::new(name).strong())
|
||||||
ui.add(egui::Label::new(¬ice.body).weak());
|
.on_hover_text(event.sender());
|
||||||
|
ui.add(egui::Label::new(¬ice.body).weak());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
MessageType::ServerNotice(notice) => {
|
MessageType::ServerNotice(notice) => {
|
||||||
ui.add(Label::new(name).strong())
|
ui.add(Label::new(name).strong())
|
||||||
|
@ -196,35 +323,62 @@ impl App {
|
||||||
ui.label(format!("* {} {}", name, emote.body));
|
ui.label(format!("* {} {}", name, emote.body));
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
});
|
||||||
|
egui::TopBottomPanel::bottom(Id::MessageEntry).show(ctx, |ui| {
|
||||||
|
ui.add(
|
||||||
|
egui::TextEdit::multiline(self.entry.get(joined.room_id()))
|
||||||
|
.desired_width(ui.available_width()),
|
||||||
|
);
|
||||||
|
if ui.button("Send").clicked() {
|
||||||
|
self.send_message(joined.clone());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send_message(&mut self, room: Joined) {
|
||||||
|
let entry = self.entry.get(room.room_id());
|
||||||
|
self.request.message(room, std::mem::take(entry));
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_response(&mut self, response: sync::Response) {
|
fn handle_response(&mut self, response: sync::Response) {
|
||||||
|
use sync::Response;
|
||||||
match response {
|
match response {
|
||||||
sync::Response::RoomName(room, name) => {
|
Response::Sync(sync) => self.handle_sync(sync),
|
||||||
|
Response::RoomName(room, name) => {
|
||||||
self.room_list.room_name.insert(room, name);
|
self.room_list.room_name.insert(room, name);
|
||||||
}
|
}
|
||||||
sync::Response::JoinedMember(room, member) => {
|
Response::JoinedMember(room, member) => {
|
||||||
self.timelines
|
self.timelines
|
||||||
.entry(room)
|
.entry(room)
|
||||||
.or_default()
|
.or_default()
|
||||||
.member
|
.member
|
||||||
.insert(member.user_id().clone(), member);
|
.insert(member.user_id().clone(), member);
|
||||||
}
|
}
|
||||||
sync::Response::Error(e) => {
|
Response::VerifyRequest(verification) => {
|
||||||
|
self.verify_req = Some(verification);
|
||||||
|
}
|
||||||
|
Response::VerifySas(sas) => {
|
||||||
|
self.verify_req = None;
|
||||||
|
self.verify = Some(Verification::SasV1(sas));
|
||||||
|
}
|
||||||
|
Response::VerifyQr(qr) => {
|
||||||
|
self.verify_req = None;
|
||||||
|
self.verify = Some(Verification::QrV1(qr));
|
||||||
|
}
|
||||||
|
Response::Error(e) => {
|
||||||
self.error = Some(e.to_string());
|
self.error = Some(e.to_string());
|
||||||
}
|
}
|
||||||
sync::Response::Sync(sync) => self.handle_sync(sync),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_sync(&mut self, sync: SyncResponse) {
|
fn handle_sync(&mut self, sync: SyncResponse) {
|
||||||
|
dbg!(&sync);
|
||||||
for (id, room) in sync.rooms.join {
|
for (id, room) in sync.rooms.join {
|
||||||
let timeline = self.timelines.entry(id.clone()).or_default();
|
let timeline = self.timelines.entry(id.clone()).or_default();
|
||||||
for event in room.timeline.events {
|
for event in room.timeline.events {
|
||||||
|
@ -235,5 +389,75 @@ impl App {
|
||||||
timeline.messages.push(event.into_full_event(id.clone()));
|
timeline.messages.push(event.into_full_event(id.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for to_device in sync.to_device.events {
|
||||||
|
let to_device = match to_device.deserialize() {
|
||||||
|
Ok(to_device) => to_device,
|
||||||
|
Err(_) => continue,
|
||||||
|
};
|
||||||
|
match to_device {
|
||||||
|
AnyToDeviceEvent::KeyVerificationRequest(req) => {
|
||||||
|
self.request
|
||||||
|
.verify_request(req.sender, req.content.transaction_id);
|
||||||
|
}
|
||||||
|
AnyToDeviceEvent::KeyVerificationStart(start) => {
|
||||||
|
if self.verify_req.is_none() {
|
||||||
|
self.request
|
||||||
|
.verify_start(start.sender, start.content.transaction_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RequestSender(UnboundedSender<sync::Request>);
|
||||||
|
|
||||||
|
impl RequestSender {
|
||||||
|
pub fn room_name(&self, name: RoomId) {
|
||||||
|
self.0.send(sync::Request::RoomName(name)).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn joined_member(&self, room: Joined, id: UserId) {
|
||||||
|
self.0.send(sync::Request::JoinedMember(room, id)).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn message(&self, room: Joined, message: String) {
|
||||||
|
self.0.send(sync::Request::Message(room, message)).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_request(&self, user: UserId, flow_id: String) {
|
||||||
|
self.0
|
||||||
|
.send(sync::Request::VerifyRequest(user, flow_id))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_cancel(&self, verify: VerificationRequest) {
|
||||||
|
self.0.send(sync::Request::VerifyCancel(verify)).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_accept(&self, verify: VerificationRequest) {
|
||||||
|
self.0.send(sync::Request::VerifyAccept(verify)).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_start(&self, user: UserId, flow_id: String) {
|
||||||
|
self.0.send(sync::Request::VerifyStart(user, flow_id)).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_start_sas(&self, verify: VerificationRequest) {
|
||||||
|
self.0.send(sync::Request::VerifyStartSas(verify)).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_sas_confirm(&self, sas: SasVerification) {
|
||||||
|
self.0.send(sync::Request::VerifySasConfirm(sas)).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_start_qr(&self, verify: VerificationRequest) {
|
||||||
|
self.0.send(sync::Request::VerifyStartQr(verify)).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn quit(&self) {
|
||||||
|
self.0.send(sync::Request::Quit).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue