commit 54a50c1ff0a47c6315a55f3e31630912cd687e7f Author: Adrien Date: Thu Aug 3 20:44:53 2023 +0200 🎉 First commit (💩) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..869df07 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..67ae498 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "beau-gosse-du-92" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +dioxus = "0.3.2" +sir = { version = "0.3.0", features = ["dioxus"] } +dioxus-desktop = "0.3.0" +# matrix-sdk = { version = "0.6.2", features = ["js"] } +matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk.git", branch = "main" , features = ["js"]} +anyhow = "1.0.71" +url = "2.4.0" +tokio = "1.29.1" +dirs = "5.0.1" +ctrlc-async = "3.2.2" +tracing-subscriber = "0.3.17" + +[build] +target = "x86_64-unknown-linux-gnu" diff --git a/images/add_user.png b/images/add_user.png new file mode 100644 index 0000000..f13708a Binary files /dev/null and b/images/add_user.png differ diff --git a/images/aerobutton_border.png b/images/aerobutton_border.png new file mode 100644 index 0000000..1f1c388 Binary files /dev/null and b/images/aerobutton_border.png differ diff --git a/images/aerobutton_border_down.png b/images/aerobutton_border_down.png new file mode 100644 index 0000000..656a1f3 Binary files /dev/null and b/images/aerobutton_border_down.png differ diff --git a/images/brush.png b/images/brush.png new file mode 100644 index 0000000..c5e2ff4 Binary files /dev/null and b/images/brush.png differ diff --git a/images/button_border.png b/images/button_border.png new file mode 100644 index 0000000..2102a4c Binary files /dev/null and b/images/button_border.png differ diff --git a/images/button_border_disabled.png b/images/button_border_disabled.png new file mode 100644 index 0000000..a5a0298 Binary files /dev/null and b/images/button_border_disabled.png differ diff --git a/images/button_border_focus.png b/images/button_border_focus.png new file mode 100644 index 0000000..83f333f Binary files /dev/null and b/images/button_border_focus.png differ diff --git a/images/default-avatar.png b/images/default-avatar.png new file mode 100644 index 0000000..295d49d Binary files /dev/null and b/images/default-avatar.png differ diff --git a/images/directory.png b/images/directory.png new file mode 100644 index 0000000..061952d Binary files /dev/null and b/images/directory.png differ diff --git a/images/letter.png b/images/letter.png new file mode 100644 index 0000000..6d10b8e Binary files /dev/null and b/images/letter.png differ diff --git a/images/logo-msn.png b/images/logo-msn.png new file mode 100644 index 0000000..9590615 Binary files /dev/null and b/images/logo-msn.png differ diff --git a/images/news.png b/images/news.png new file mode 100644 index 0000000..1063df2 Binary files /dev/null and b/images/news.png differ diff --git a/images/settings.png b/images/settings.png new file mode 100644 index 0000000..6a23c2b Binary files /dev/null and b/images/settings.png differ diff --git a/images/status_away.png b/images/status_away.png new file mode 100644 index 0000000..39486a6 Binary files /dev/null and b/images/status_away.png differ diff --git a/images/status_busy.png b/images/status_busy.png new file mode 100644 index 0000000..471ff6b Binary files /dev/null and b/images/status_busy.png differ diff --git a/images/status_online.png b/images/status_online.png new file mode 100644 index 0000000..dd53972 Binary files /dev/null and b/images/status_online.png differ diff --git a/images/tbc_transfert.png b/images/tbc_transfert.png new file mode 100644 index 0000000..4ec8570 Binary files /dev/null and b/images/tbc_transfert.png differ diff --git a/src/app_settings.rs b/src/app_settings.rs new file mode 100644 index 0000000..b0122ca --- /dev/null +++ b/src/app_settings.rs @@ -0,0 +1,29 @@ +use std::cell::RefCell; +use std::rc::Rc; +use std::sync::{Arc, Mutex}; + +use crate::matrix_client::MatrixClient; +use crate::matrix_client::Requester; + +#[derive(Debug, Clone)] +pub struct AppSettings { + // pub matrix_client: Option>>, + // pub matrix_client: Arc, + // pub matrix_client: Rc>, + // pub matrix_client: Arc, + //pub matrix_client: Arc>, + pub requester: Option>, +} + +impl AppSettings { + pub fn new() -> Self { + Self { + // matrix_client: Arc::new(MatrixClient::new()), + //matrix_client: Arc::new(Mutex::new(MatrixClient::new())), + requester: None, + // matrix_client: Arc::new(Mutex::new(MatrixClient::new())), + // matrix_client: Arc::new(MatrixClient::new()), + // matrix_client: Rc::new(RefCell::new(MatrixClient::new())), + } + } +} diff --git a/src/base.rs b/src/base.rs new file mode 100644 index 0000000..adcb1f6 --- /dev/null +++ b/src/base.rs @@ -0,0 +1,5 @@ +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Info {} + +// pub type ProgramStore = Store; +// pub type AsyncProgramStore = Arc>; diff --git a/src/components.rs b/src/components.rs new file mode 100644 index 0000000..ce11cfa --- /dev/null +++ b/src/components.rs @@ -0,0 +1,4 @@ +pub mod avatar_selector; +pub mod control_window; +pub mod header; +pub mod login; diff --git a/src/components/avatar_selector.rs b/src/components/avatar_selector.rs new file mode 100644 index 0000000..0d1d534 --- /dev/null +++ b/src/components/avatar_selector.rs @@ -0,0 +1,77 @@ +use dioxus::prelude::*; +use sir::css; + +pub fn AvatarSelector(cx: Scope) -> Element { + let selector = css!( + " + position: relative; + //left: 35%; + height: 100%; + aspect-ratio: 1; + " + ); + + let picture = css!( + " + position: absolute; + height: 75%; + aspect-ratio: 1; + + bottom: 17.5%; + right: 18%; + " + ); + + cx.render(rsx! { + div { + class: "{selector}", + svg { + view_box: "0 0 100 100", + linearGradient { + id: "avatar-gradient", + x1: 1, + y1: 1, + x2: 0, + y2: 0, + stop { + offset: "0%", + stop_color: "rgb(138, 191, 209)", + } + stop { + offset: "60%", + stop_color: "rgb(236, 246, 249)", + } + }, + filter { + id: "avatar-shadow", + feDropShadow { + dx: 2, + dy: 2, + std_deviation: 3, + flood_opacity: 0.5, + }, + }, + rect { + width: "90", + height: "90", + rx: "12", + fill: "url('#avatar-gradient')", + filter: "url('#avatar-shadow')", + stroke: "grey", + }, + // rect { + // x: "7.5", + // y: "7.5", + // width: "75", + // height: "75", + // fill: "transparent", + // stroke: "grey", + // }, + }, + img { + class: "{picture}", + src: "./images/default-avatar.png", + }, + }, + }) +} diff --git a/src/components/control_window.rs b/src/components/control_window.rs new file mode 100644 index 0000000..17df33e --- /dev/null +++ b/src/components/control_window.rs @@ -0,0 +1,467 @@ +use dioxus::prelude::*; +use sir::{css, global_css}; + +use crate::app_settings::AppSettings; +use crate::components::avatar_selector::AvatarSelector; +use crate::components::header::Header; + +pub fn ControlWindow(cx: Scope) -> Element { + let app_context = use_shared_state::(cx).unwrap(); + println!("app_context={:?}", app_context.read()); + + // TODO: Use @extend once implemented (https://github.com/kaj/rsass/issues/65) + global_css!( + " + .aero-button { + height: 50%; + min-height: 16px; + aspect-ratio: 1; + background-color: transparent; + border: 2px solid transparent; + background-size: contain !important; + margin-right: 1%; + } + .aero-button:hover { + border-image: url(./images/aerobutton_border.png) 2 round; + } + .aero-button:active { + border-image: url(./images/aerobutton_border_down.png) 2 round; + } + + .button { + height: 50%; + min-height: 16px; + aspect-ratio: 1; + background-color: transparent; + border: 2px solid transparent; + background-size: contain !important; + margin-right: 1%; + } + .button:hover { + border-image: url(./images/button_border.png) 2 round; + } + .button:active { + border-image: url(./images/button_border_down.png) 2 round; + } + + .flex-right { + margin-left: auto; + } + + .user-info { + position: relative; + height: 75%; + width: 99%; + top: -75%; + left: 1%; + aspect-ratio: 1; + z-index: 1; + display: flex; + flex-direction: row; + align-items: center; + + .avatar-selector { + height: 100%; + aspect-ratio: 1; + } + + .info-container { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + height: 100%; + width: 100%; + + .user-id { + height: 30%; + width: fit-content; + display: flex; + text-align: begin; + align-items: center; + + .user-name { + display: inline-block; + width: fit-content; + color: white; + margin: 0; + } + + .user-status { + display: inline-block; + color: #B9DDE7; + width: fit-content; + //margin-left: 1%; + //padding-left: 1%; + } + } + + .user-message { + width: fit-content; + height: 30%; + display: flex; + text-align: begin; + align-items: center; + margin: 0; + color: white; + } + } + } + + // From https://codepen.io/zoomodesign/pen/yNbVVZ + .contacts { + height: 72%; + width: 100%; + background-color: white; + font-size: 8pt; + + &.active { + .arrow { + transform: rotate(45deg) translate(-5px,-5px); + &:before { + transform: translate(10px,0); + } + &:after { + transform: rotate(90deg) translate(10px,0); + } + } + ul { + opacity: 0; + } + } + + .header { + height: 2%; + width: 98%; + display: flex; + flex-direction: row; + align-items: center; + cursor: pointer; + margin: 0; + margin-left: 1%; + padding-top: 1%; + font-weight: bold; + } + + ul { + height: 100%; + margin: 0; + overflow: hidden; + opacity: 1; + transition: 0.4s ease; + } + + li { + list-style-type: none; + height: 2%; + margin: 0 auto; + cursor: pointer; + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + + img { + height: 100%; + aspect-ratio: 1; + } + } + + .arrow { + width: calc((100%/1080)*10); + aspect-ratio: 1; + display: inline-block; + transition: 0.4s ease; + margin-top: calc((100%/1080)*2); + margin-right: 2%; + text-align: left; + transform: rotate(45deg); + float: right; + &:before, &:after { + position: absolute; + content: ''; + display: inline-block; + width: 100%; + height: 15%; + background-color: #000; + transition: 0.4s ease; + } + &:after { + position: absolute; + transform: rotate(90deg); + top: -5px; + left: 5px; + } + } + + .contact { + list-style-type: none + margin: 0 auto + text-align: left + cursor: pointer + } + } + " + ); + + let root = css!( + " + width: 100%; + height: 100%; + + background-color: #ECF6F9; + font-family: \"Tahoma\", sans-serif; + + border: thin solid #707070; + border-radius: 8px; + box-shadow: 0 0 5px #00000050; + " + ); + + let header = css!( + " + height: 10%; + width: 100%; + " + ); + + let title_bar = css!( + " + height: 60%; + width: 100%; + background: + linear-gradient(180deg, #7DC5E3, #3883A3); + " + ); + let user_info = css!( + " + height: 40%; + width: 100%; + background: + linear-gradient(180deg, #00658B, #0077A6); + " + ); + let contacts_nav = css!( + " + height: calc(31/1080*100%); + background: + linear-gradient(180deg, #00658B, #0077A6); + " + ); + + let contacts_nav_inner = css!( + " + margin-left: 1%; + margin-right: 1%; + height: 100%; + display: flex; + align-items: center; + " + ); + + let search = css!( + " + height: calc(38/1080*100%); + width: 100%; + + border-bottom: thin solid #e2eaf3; + " + ); + + // TODO: Remove following div + let search_inner = css!( + " + height: 100%; + width: 98%; + padding-left: 1%; + display: flex; + flex-direction: row; + align-items: center; + " + ); + + let search_input = css!( + " + height: calc(23/38*100%); + width: 100%; + margin-right: 1%; + border: thin solid #c7c7c7; + box-shadow: inset 0 0 calc(3/1080*100%) #0000002a; + font-size: 8pt; + + padding-left: 1%; + " + ); + + let footer = css!( + " + height: 10%; + " + ); + + let show_contacts = use_state(cx, || false); + + let contacts_active = if **show_contacts { "active" } else { "" }; + + cx.render(rsx! { + div { + class: "{root}", + + div { + class: "{header}", + + div { + class: "{title_bar}", + }, + + div { + class: "{user_info}", + }, + + div { + class: "user-info", + + div { + class: "avatar-selector", + AvatarSelector {}, + }, + + div { + class: "info-container", + + div { + class: "aero-button user-id", + p { + class: "user-name", + "SUPER USER" + }, + p { + class: "user-status", + "(Busy)", + }, + }, + + div { + class: "aero-button user-message", + p { + "My message", + } + }, + }, + }, + }, + + div { + class: "{contacts_nav}", + div { + class: "{contacts_nav_inner}", + + button { + class: "aero-button", + style: "background: url(./images/letter.png) center no-repeat", + }, + button { + class: "aero-button", + style: "background: url(./images/directory.png) no-repeat center", + }, + button { + class: "aero-button", + style: "background: url(./images/news.png) no-repeat center", + }, + + button { + class: "aero-button flex-right", + style: "background: url(./images/brush.png) no-repeat center", + }, + button { + class: "aero-button", + style: "background: url(./images/settings.png) no-repeat center", + }, + + }, + + }, + + div { + class: "{search}", + + div { + class: "{search_inner}", + + input { + class: "{search_input}", + placeholder: "Find a contact...", + r#type: "text", + }, + + button { + class: "button", + style: "background: url(./images/add_user.png) no-repeat center", + }, + + button { + class: "button", + style: "background: url(./images/tbc_transfert.png) no-repeat center", + }, + }, + }, + + div { + class: "contacts {contacts_active}", + + p { + class: "header", + onclick: move |_| show_contacts.set(!show_contacts), + span { + class: "arrow", + }, + "Online (4)", + }, + + // TODO: Test overflow + ul { + li { + img { + src: "./images/status_online.png", + }, + p { + "Contact AAAAAAAA -", + }, + p { + style: "color: darkgrey;", + "i'm sad all day until i get to talk with friends, online friends that is", + }, + }, + li { + img { + src: "./images/status_busy.png", + }, + p { + "Contact BBBBBB -", + }, + p { + style: "color: darkgrey;", + "i'm sad all day until i get to talk with friends, online friends that is", + } + }, + li { + img { + src: "./images/status_away.png", + }, + p { + "Contact CCC -", + }, + p { + style: "color: darkgrey;", + "i'm sad all day until i get to talk with friends, online friends that is", + } + }, + }, + }, + + div { + class: "{footer}", + }, + }, + }) +} diff --git a/src/components/header.rs b/src/components/header.rs new file mode 100644 index 0000000..3c71131 --- /dev/null +++ b/src/components/header.rs @@ -0,0 +1,38 @@ +use dioxus::prelude::*; +use sir::css; + +pub fn Header(cx: Scope) -> Element { + let header = css!( + " + height: 100%; + width: 100%; + display: flex; + + img { + height: 100%; + } + svg { + fill: white; + } + " + ); + + cx.render(rsx! { + div { + class: "{header}", + img { + // src: "./assets/live-logo2.png" + src: "./images/logo-msn.png" + } + svg { + view_box: "0 0 100 10", + text { + y: "55%", + dominant_baseline: "middle", + font_size: "5", + "Windows Live Messenger", + }, + }, + } + }) +} diff --git a/src/components/login.rs b/src/components/login.rs new file mode 100644 index 0000000..dd857dd --- /dev/null +++ b/src/components/login.rs @@ -0,0 +1,170 @@ +use dioxus::prelude::*; +use sir::css; +use std::str::FromStr; +use std::sync::Arc; + +use crate::app_settings::AppSettings; +use crate::components::avatar_selector::AvatarSelector; +use crate::components::header::Header; +use crate::matrix_client::{LoginStyle, MatrixClient}; + +pub fn Login(cx: Scope) -> Element { + let app_context = use_shared_state::(cx).unwrap(); + println!("app_context={:?}", app_context.read()); + + let login = use_ref(cx, || Login::new()); + + let empty_placeholder = String::from(""); + + let root = css!( + " + width: 90%; + height: 98%; + + display: flex; + flex-direction: column; + align-items: center; + + padding: 5%; + padding-top: 2%; + + background: linear-gradient(rgb(138, 191, 209), rgb(236, 246, 249) 10%); + " + ); + + let header = css!( + " + height: 5%; + width: 100%; + " + ); + + let body = css!( + " + height: 50%; + width: 50%; + max-width: 400px; + + display: flex; + flex-direction: column; + justify-content: center; + + padding-bottom: 3%; + " + ); + + let footer_buttons = css!( + " + width: 100%; + + padding-top: 5%; + + display: flex; + justify-content: center; + " + ); + + let avatar_selector = css!( + " + height: 30%; + width: 100%; + " + ); + + let run_matrix_client = move |_| { + to_owned![app_context, login]; + + let homeserver_url = login.read().homeserver_url.clone().unwrap(); + let username = login.read().email.clone().unwrap(); + let password = login.read().password.clone().unwrap(); + + cx.spawn(async { + let requester = MatrixClient::spawn(homeserver_url).await; + + requester.init(); + requester.login(LoginStyle::Password(username, password)); + + let context = app_context; + context.write().requester = Some(Arc::new(requester)); + }); + }; + + cx.render(rsx! { + div { + class: "{root}", + + div { + class: "{header}", + Header {}, + }, + + div { + class: "{body}", + div { + class: "{avatar_selector}", + AvatarSelector {}, + }, + + p { + "Matrix homeserver:" + }, + input { + id: "input-homeserver-url", + r#type: "text", + name: "homeserver URL", + value: "{(login.read().homeserver_url.as_ref().unwrap_or(&empty_placeholder))}", + oninput: move |evt| login.write().homeserver_url = Some(evt.value.clone()), + }, + + p { + "E-mail address:" + }, + input { + id: "login-input-email", + r#type: "text", + name: "email", + value: "{login.read().email.as_ref().unwrap_or(&empty_placeholder)}", + oninput: move |evt| login.write().email = Some(evt.value.clone()), + }, + p { + "Password:" + }, + input { + id: "login-input-password", + r#type: "password", + name: "Password", + value: "{login.read().password.as_ref().unwrap_or(&empty_placeholder)}", + oninput: move |evt| login.write().password = Some(evt.value.clone()), + }, + + div { + class: "{footer_buttons}", + input { + class: "button", + onclick: run_matrix_client, + r#type: "submit", + value: "sign in", + }, + }, + }, + }, + }) +} + +#[derive(Debug)] +struct Login { + homeserver_url: Option, + email: Option, + password: Option, +} + +impl Login { + fn new() -> Self { + let login = Self { + homeserver_url: None, + email: None, + password: None, + }; + login + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b66ce5d --- /dev/null +++ b/src/main.rs @@ -0,0 +1,55 @@ +#![allow(non_snake_case)] +use dioxus::prelude::*; +use dioxus_desktop::Config; +use sir::{global_css, AppStyle}; + +pub mod app_settings; +pub mod components; +pub mod matrix_client; + +use crate::app_settings::AppSettings; +use crate::components::control_window::ControlWindow; +use crate::components::login::Login; + +mod base; + +fn App(cx: Scope) -> Element { + use_shared_state_provider(cx, || cx.props.clone()); + + global_css!( + " + body { + height: 100vh; + width: 100vw; + margin: 0px; + padding: 0px; + outline: 0px; + font-family: Tahoma, sans-serif; + } + #main { + height: 100%; + width: 100%; + }" + ); + + // let window = dioxus_desktop::use_window(cx); + // let dom = VirtualDom::new(ControlWindow); + // window.new_window(dom, cx.props.clone()); + + cx.render(rsx! { + AppStyle {}, + // Login {} + ControlWindow {} + }) +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt::init(); + + let app_settings = AppSettings::new(); + + dioxus_desktop::launch_with_props(App, app_settings, Config::default()); + + Ok(()) +} diff --git a/src/matrix_client.rs b/src/matrix_client.rs new file mode 100644 index 0000000..c5ee1df --- /dev/null +++ b/src/matrix_client.rs @@ -0,0 +1,208 @@ +use dirs; +use matrix_sdk::{ + config::SyncSettings, + room::Room, + ruma::events::room::{ + member::StrippedRoomMemberEvent, + message::{OriginalSyncRoomMessageEvent, RoomMessageEventContent, SyncRoomMessageEvent}, + }, + Client, Error as MatrixError, +}; +use std::fmt::{Debug, Formatter}; +use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; +use std::sync::{Arc, Mutex}; +use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}; +use tokio::task::JoinHandle; +use tokio::time::{sleep, Duration}; + +use crate::base::Info; + +#[derive(Debug)] +pub enum LoginStyle { + // SessionRestore(Session), + Password(String, String), +} + +pub struct ClientResponse(Receiver); +pub struct ClientReply(SyncSender); + +impl ClientResponse { + fn recv(self) -> T { + self.0 + .recv() + .expect("failed to receive response from client thread") + } +} + +impl ClientReply { + fn send(self, t: T) { + self.0.send(t).unwrap(); + } +} + +pub enum WorkerTask { + // Init(AsyncProgramStore, ClientReply<()>), + // Init(ClientReply<()>), + Init(ClientReply<()>), + //Login(LoginStyle, ClientReply), + Login(LoginStyle, ClientReply<()>), +} + +impl Debug for WorkerTask { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + match self { + WorkerTask::Init(_) => f + .debug_tuple("WorkerTask::Init") + .field(&format_args!("_")) + // .field(&format_args!("_")) + .finish(), + WorkerTask::Login(style, _) => f + .debug_tuple("WorkerTask::Login") + .field(style) + // .field(&format_args!("_")) + .finish(), + } + } +} + +fn oneshot() -> (ClientReply, ClientResponse) { + let (tx, rx) = sync_channel(1); + let reply = ClientReply(tx); + let response = ClientResponse(rx); + + return (reply, response); +} + +#[derive(Debug)] +pub struct Requester { + pub client: Client, + // pub matrix_client: MatrixClient, + pub tx: UnboundedSender, +} + +impl Requester { + pub fn init(&self) { + println!("Requester.init BEG"); + let (reply, response) = oneshot(); + + self.tx.send(WorkerTask::Init(reply)).unwrap(); + + println!("Requester.init END"); + return response.recv(); + } + + pub fn login(&self, style: LoginStyle) { + println!("Requester.login BEG"); + let (reply, response) = oneshot(); + + self.tx.send(WorkerTask::Login(style, reply)).unwrap(); + + println!("Requester.login END"); + return response.recv(); + } +} + +#[derive(Debug)] +pub struct MatrixClient { + initialized: bool, + // client: Client, + client: Option>, + sync_token: Option, + load_handle: Option>, + sync_handle: Option>, +} + +impl MatrixClient { + pub async fn spawn(homeserver_url: String) -> Requester { + let (tx, rx) = unbounded_channel::(); + + let client = Client::builder() + .homeserver_url(&homeserver_url) + .build() + .await + .unwrap(); + + let mut matrix_client = MatrixClient { + client: None, + initialized: false, + sync_token: None, + load_handle: None, + sync_handle: None, + }; + matrix_client.client = Some(Arc::new(client.clone())); + + tokio::spawn(async move { + matrix_client.work(rx).await; + }); + + Requester { client, tx } + } + + async fn work(&mut self, mut rx: UnboundedReceiver) { + println!("MatrixClient.work BEG"); + loop { + let task = rx.recv().await; + println!("task={:?}", task); + + match task { + Some(task) => self.run(task).await, + None => { + break; + } + } + } + + println!("MatrixClient.work END"); + + if let Some(handle) = self.sync_handle.take() { + handle.abort(); + } + } + + async fn run(&mut self, task: WorkerTask) { + println!("Run({:?}", task); + match task { + WorkerTask::Init(reply) => { + assert_eq!(self.initialized, false); + self.init().await; + reply.send(()); + } + WorkerTask::Login(style, reply) => { + assert!(self.initialized); + reply.send(self.login_and_sync(style).await.unwrap()); + } + } + } + + async fn init(&mut self) { + self.initialized = true; + } + + async fn login_and_sync(&mut self, style: LoginStyle) -> anyhow::Result<()> { + let client = self.client.clone().unwrap(); + + match style { + LoginStyle::Password(username, password) => { + let resp = client + .matrix_auth() + .login_username(&username, &password) + .initial_device_display_name("TODO") + .send() + .await?; + dbg!(resp); + } + } + + self.sync_handle = tokio::spawn(async move { + loop { + let settings = SyncSettings::default(); + + let _ = client.sync(settings).await; + } + }) + .into(); + + println!("User connected to the homeserver"); + Ok(()) + } +}