🚧 Remove ChatsWindow and ContactsWindow components
Before Width: | Height: | Size: 698 B |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 494 B |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 221 B |
Before Width: | Height: | Size: 223 B |
Before Width: | Height: | Size: 755 B |
Before Width: | Height: | Size: 864 B |
Before Width: | Height: | Size: 306 B |
Before Width: | Height: | Size: 853 B |
Before Width: | Height: | Size: 430 B |
Before Width: | Height: | Size: 639 B |
Before Width: | Height: | Size: 388 B |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 323 B |
@@ -1 +0,0 @@
|
||||
<svg enable-background="new 0 0 48 48" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg"><path d="m36.5 44h-25c-1.1 0-1.8-1.2-1.3-2.2l2.8-4.8h22l2.7 4.8c.6 1-.1 2.2-1.2 2.2z" fill="#455a64"/><circle cx="24" cy="23" fill="#78909c" r="18"/><path d="m24 35c-6.6 0-12-5.4-12-12s5.4-12 12-12 12 5.4 12 12-5.4 12-12 12z" fill="#455a64"/><circle cx="24" cy="23" fill="#42a5f5" r="9"/><path d="m28.8 20c-1.2-1.4-3-2.2-4.8-2.2s-3.6.8-4.8 2.2c-.5.5-.4 1.3.1 1.8s1.3.4 1.8-.1c1.5-1.7 4.3-1.7 5.8 0 .3.3.6.4 1 .4.3 0 .6-.1.9-.3.4-.4.5-1.3 0-1.8z" fill="#90caf9"/></svg>
|
Before Width: | Height: | Size: 562 B |
Before Width: | Height: | Size: 719 B |
@@ -1,94 +0,0 @@
|
||||
@import "../../_base.scss"
|
||||
|
||||
.chats-window {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
$horizontal-padding-margin: calc((2*100%)/1980);
|
||||
|
||||
.tabs {
|
||||
height: 2%;
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
overflow-x: scroll;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
.tab {
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
padding: 0 $horizontal-padding-margin;
|
||||
|
||||
display: flex;
|
||||
|
||||
button {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
$clamped-horizontal-padding-margin: clamp(5px, $horizontal-padding-margin, $horizontal-padding-margin);
|
||||
margin: 0 $clamped-horizontal-padding-margin;
|
||||
padding: 0 $clamped-horizontal-padding-margin;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
background-color: #EFF9F9;
|
||||
border: $border-style;
|
||||
|
||||
$radius: calc((6*100%)/1980);
|
||||
$clamped-radius: clamp(6px, $radius, $radius);
|
||||
border-radius: $clamped-radius $clamped-radius 0 0;
|
||||
|
||||
font-size: $font-size;
|
||||
|
||||
img {
|
||||
height: $icon-size;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat {
|
||||
height: 98%;
|
||||
width: 100%;
|
||||
|
||||
background-color: #ECF6F9;
|
||||
|
||||
.header {
|
||||
height: 7%;
|
||||
|
||||
border: $border-style;
|
||||
|
||||
.info {
|
||||
height: 45%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
padding-left: 2%;
|
||||
|
||||
background: linear-gradient(180deg, #BFE3EB, #DEFBFE);
|
||||
|
||||
font-size: $font-size;
|
||||
|
||||
.room-name {
|
||||
margin: 0;
|
||||
margin-top: 1%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.room-topic {
|
||||
margin: 0;
|
||||
color: darkgrey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,87 +0,0 @@
|
||||
use dioxus::prelude::*;
|
||||
use log::error;
|
||||
use matrix_sdk::ruma::OwnedRoomId;
|
||||
|
||||
use super::edit_section::EditSection;
|
||||
use crate::base::{sync_messages, ROOMS};
|
||||
use crate::ui::components::avatar_selector::AvatarSelector;
|
||||
use crate::ui::components::icons::DownArrowIcon;
|
||||
|
||||
turf::style_sheet!("src/ui/components/chats_window/conversation.scss");
|
||||
|
||||
#[component]
|
||||
pub(super) fn Conversation(room_id: OwnedRoomId) -> Element {
|
||||
error!("Conversation {} rendering", room_id);
|
||||
|
||||
let _sync_message_coro: Coroutine<()> =
|
||||
use_coroutine(|_: UnboundedReceiver<_>| sync_messages(&ROOMS, room_id));
|
||||
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATION,
|
||||
div {
|
||||
class: ClassName::ROOM_EVENTS,
|
||||
ul {
|
||||
li {
|
||||
class: ClassName::ROOM_EVENT,
|
||||
div {
|
||||
p {
|
||||
class: ClassName::TITLE,
|
||||
"MON POTE says:"
|
||||
},
|
||||
p {
|
||||
class: ClassName::CONTENT,
|
||||
"Coucou mon pote",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
div {
|
||||
class: ClassName::OTHER_AVATAR_SELECTOR_CONTAINER,
|
||||
div {
|
||||
class: ClassName::AVATAR_SELECTOR,
|
||||
AvatarSelector {},
|
||||
},
|
||||
div {
|
||||
class: ClassName::WEBCAM,
|
||||
img {
|
||||
src: "images/webcam.svg"
|
||||
},
|
||||
},
|
||||
div {
|
||||
class: ClassName::ARROW_ICON,
|
||||
DownArrowIcon {}
|
||||
},
|
||||
},
|
||||
div {
|
||||
class: ClassName::HOLDER,
|
||||
"••••••"
|
||||
},
|
||||
div {
|
||||
class: ClassName::EDIT_SECTION,
|
||||
EditSection {},
|
||||
},
|
||||
div {
|
||||
class: ClassName::MY_AVATAR_SELECTOR_CONTAINER,
|
||||
div {
|
||||
class: ClassName::AVATAR_SELECTOR,
|
||||
AvatarSelector {},
|
||||
},
|
||||
div {
|
||||
class: ClassName::WEBCAM,
|
||||
img {
|
||||
src: "images/webcam.svg"
|
||||
},
|
||||
},
|
||||
div {
|
||||
class: ClassName::ARROW_ICON,
|
||||
DownArrowIcon {}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
@@ -1,113 +0,0 @@
|
||||
@import "../../_base.scss"
|
||||
|
||||
.conversation {
|
||||
$padding-top: 2%;
|
||||
|
||||
height: calc(93% - $padding-top);
|
||||
|
||||
padding-left: 2%;
|
||||
padding-top: $padding-top;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 75% 25%;
|
||||
grid-template-rows: 70% 1% 29%;
|
||||
cursor: pointer;
|
||||
|
||||
.holder {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
|
||||
color: darkgrey;
|
||||
}
|
||||
|
||||
.room-events {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
border: $border-style;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.room-event {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: space-between;
|
||||
|
||||
padding-top: 1%;
|
||||
|
||||
font-size: $font-size;
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 0;
|
||||
padding-left: 2%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
%selector-container {
|
||||
aspect-ratio: 1;
|
||||
|
||||
grid-column: 2;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 10% 15% 50% 15% 10%;
|
||||
grid-template-rows: 80% 20%;
|
||||
|
||||
.avatar-selector {
|
||||
grid-column-start: 1;
|
||||
grid-column-end: 6;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
.webcam {
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
grid-column: 4;
|
||||
grid-row: 2;
|
||||
|
||||
svg {
|
||||
path:last-child {
|
||||
fill: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.other-avatar-selector-container {
|
||||
@extend %selector-container;
|
||||
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.my-avatar-selector-container {
|
||||
@extend %selector-container;
|
||||
|
||||
grid-row: 3;
|
||||
}
|
||||
|
||||
.edit-section {
|
||||
grid-row: 3;
|
||||
}
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
turf::style_sheet!("src/ui/components/chats_window/edit_section.scss");
|
||||
|
||||
pub fn EditSection() -> Element {
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
|
||||
div {
|
||||
class: ClassName::INPUT_AREA,
|
||||
|
||||
div {
|
||||
class: ClassName::BUTTONS,
|
||||
|
||||
button {
|
||||
"😀"
|
||||
},
|
||||
|
||||
button {
|
||||
"😉"
|
||||
},
|
||||
|
||||
button {
|
||||
"😴"
|
||||
},
|
||||
|
||||
button {
|
||||
"🔊"
|
||||
},
|
||||
},
|
||||
|
||||
textarea {
|
||||
class: ClassName::EDIT,
|
||||
placeholder: "Type your message here...",
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::CMD_BUTTONS,
|
||||
|
||||
button {
|
||||
class: ClassName::SEND_BUTTON,
|
||||
|
||||
"Send"
|
||||
},
|
||||
|
||||
button {
|
||||
"🔎"
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
@@ -1,55 +0,0 @@
|
||||
@import "../../_base.scss"
|
||||
|
||||
.input-area {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
margin-bottom: 2%;
|
||||
|
||||
.buttons {
|
||||
$padding-top-bottom: 0.5%;
|
||||
|
||||
height: calc(10% - ($padding-top-bottom * 2));
|
||||
padding-left: 2%;
|
||||
padding-top: $padding-top-bottom;
|
||||
padding-bottom: $padding-top-bottom;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
border: $border-style;
|
||||
background: linear-gradient(180deg, #F5FDFF, #E3ECF0, #F5FDFF);
|
||||
|
||||
button {
|
||||
@extend .aeroButton;
|
||||
height: $icon-size;
|
||||
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-right: 2%;
|
||||
|
||||
font-size: larger;
|
||||
}
|
||||
}
|
||||
|
||||
.edit {
|
||||
height: 80%;
|
||||
// Remove border from width
|
||||
width: calc(100% - 2px);
|
||||
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cmd-buttons {
|
||||
height: 7%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.send-button {
|
||||
width: 15%;
|
||||
}
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use matrix_sdk::ruma::OwnedRoomId;
|
||||
use tokio::sync::broadcast::error::SendError;
|
||||
use tokio::sync::broadcast::{channel, Receiver, Sender};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Tasks {
|
||||
ToggleRoom(OwnedRoomId),
|
||||
}
|
||||
|
||||
pub struct Interface {
|
||||
sender: Sender<Tasks>,
|
||||
receiver: RefCell<Receiver<Tasks>>,
|
||||
}
|
||||
|
||||
impl Interface {
|
||||
pub fn new() -> Self {
|
||||
let (sender, receiver) = channel::<Tasks>(32);
|
||||
Self {
|
||||
sender,
|
||||
receiver: RefCell::new(receiver),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn receiver(&self) -> &RefCell<Receiver<Tasks>> {
|
||||
&self.receiver
|
||||
}
|
||||
|
||||
pub fn toggle_room(&self, room_id: OwnedRoomId) -> Result<usize, SendError<Tasks>> {
|
||||
self.sender.send(Tasks::ToggleRoom(room_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Interface {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
@@ -1,171 +0,0 @@
|
||||
mod conversation;
|
||||
mod edit_section;
|
||||
mod navbar;
|
||||
|
||||
pub(crate) mod interface;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use log::{debug, error};
|
||||
use matrix_sdk::ruma::OwnedRoomId;
|
||||
use tokio::sync::broadcast::Receiver;
|
||||
|
||||
use crate::base::{sync_rooms, ROOMS};
|
||||
use crate::domain::model::room::Room;
|
||||
use crate::infrastructure::messaging::matrix::requester::Receivers;
|
||||
use conversation::Conversation;
|
||||
use navbar::Navbar;
|
||||
|
||||
use interface::{Interface, Tasks};
|
||||
|
||||
turf::style_sheet!("src/ui/components/chats_window/chats_window.scss");
|
||||
|
||||
#[derive(Props, Clone, PartialEq)]
|
||||
pub struct ChatsWindowProps {
|
||||
pub receivers: Receivers,
|
||||
pub interface: Signal<Interface>,
|
||||
}
|
||||
|
||||
fn render_rooms_tabs(
|
||||
by_id_rooms: &GlobalSignal<HashMap<OwnedRoomId, RefCell<Room>>>,
|
||||
displayed_room_ids: Signal<HashSet<OwnedRoomId>>,
|
||||
) -> Vec<Element> {
|
||||
let rooms_ref = by_id_rooms.read();
|
||||
let displayed_room_ids = displayed_room_ids.read();
|
||||
rooms_ref
|
||||
.values()
|
||||
.filter(|room| displayed_room_ids.contains(room.borrow().id()))
|
||||
.map(|room| {
|
||||
let room = room.borrow();
|
||||
let room_name = match room.name() {
|
||||
Some(room_name) => room_name.clone(),
|
||||
None => room.id().to_string(),
|
||||
};
|
||||
rsx!(
|
||||
div {
|
||||
class: ClassName::TAB,
|
||||
button {
|
||||
img {
|
||||
src: "/public/images/status_online.png",
|
||||
},
|
||||
"{room_name}",
|
||||
},
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn render_rooms_conversations(
|
||||
by_id_rooms: &GlobalSignal<HashMap<OwnedRoomId, RefCell<Room>>>,
|
||||
displayed_room_ids: Signal<HashSet<OwnedRoomId>>,
|
||||
) -> Vec<Element> {
|
||||
let rooms_ref = by_id_rooms.read();
|
||||
let displayed_room_ids = displayed_room_ids.read();
|
||||
rooms_ref
|
||||
.values()
|
||||
.filter(|room| displayed_room_ids.contains(room.borrow().id()))
|
||||
.map(|room| {
|
||||
let room = room.borrow();
|
||||
let room_id = room.id();
|
||||
rsx!(Conversation {
|
||||
room_id: room_id.clone()
|
||||
},)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
async fn handle_controls(
|
||||
receiver_ref: &RefCell<Receiver<Tasks>>,
|
||||
mut displayed_room_ids: Signal<HashSet<OwnedRoomId>>,
|
||||
) {
|
||||
loop {
|
||||
let result = receiver_ref.borrow_mut().recv().await;
|
||||
match result {
|
||||
Ok(task) => match task {
|
||||
Tasks::ToggleRoom(room_id) => {
|
||||
error!("ON TOGGLE ROOM {}", room_id);
|
||||
let mut displayed_room_ids = displayed_room_ids.write();
|
||||
match displayed_room_ids.take(&room_id) {
|
||||
Some(_) => {
|
||||
error!("{} room already dispayed... close it", room_id);
|
||||
}
|
||||
None => {
|
||||
error!("{} room isn't dispayed... open it", room_id);
|
||||
displayed_room_ids.insert(room_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => error!("{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ChatsWindow(props: ChatsWindowProps) -> Element {
|
||||
debug!("ChatsWindow rendering");
|
||||
|
||||
let receivers = &props.receivers;
|
||||
let interface_ref = &props.interface;
|
||||
|
||||
let displayed_room_ids = use_signal(HashSet::<OwnedRoomId>::new);
|
||||
|
||||
let sync_rooms_coro = use_coroutine(|rx| {
|
||||
to_owned![receivers];
|
||||
sync_rooms(rx, receivers, &ROOMS)
|
||||
});
|
||||
sync_rooms_coro.send(true);
|
||||
|
||||
let _: Coroutine<()> = use_coroutine(|_: UnboundedReceiver<_>| {
|
||||
to_owned![interface_ref, displayed_room_ids];
|
||||
async move {
|
||||
let interface = interface_ref.read();
|
||||
let receiver = &interface.receiver();
|
||||
handle_controls(receiver, displayed_room_ids).await
|
||||
}
|
||||
});
|
||||
|
||||
let rendered_rooms_tabs = render_rooms_tabs(&ROOMS, displayed_room_ids);
|
||||
let rendered_rooms_conversations = render_rooms_conversations(&ROOMS, displayed_room_ids);
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
|
||||
div {
|
||||
class: ClassName::CHATS_WINDOW,
|
||||
|
||||
div {
|
||||
class: ClassName::TABS,
|
||||
{rendered_rooms_tabs.into_iter()},
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::CHAT,
|
||||
|
||||
div {
|
||||
class: ClassName::HEADER,
|
||||
|
||||
div {
|
||||
class: ClassName::INFO,
|
||||
|
||||
p {
|
||||
class: ClassName::ROOM_NAME,
|
||||
"MON POTE",
|
||||
},
|
||||
|
||||
p {
|
||||
class: ClassName::ROOM_TOPIC,
|
||||
"LE STATUT A MON POTE",
|
||||
},
|
||||
},
|
||||
|
||||
Navbar {},
|
||||
},
|
||||
|
||||
{rendered_rooms_conversations.into_iter()},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
use dioxus::prelude::*;
|
||||
use log::debug;
|
||||
|
||||
turf::style_sheet!("src/ui/components/chats_window/navbar.scss");
|
||||
|
||||
pub fn Navbar() -> Element {
|
||||
debug!("Navbar rendering");
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
|
||||
div {
|
||||
class: ClassName::NAVBAR,
|
||||
|
||||
button {
|
||||
style: "background: url(/public/images/add_user2.png) center no-repeat",
|
||||
},
|
||||
|
||||
button {
|
||||
style: "background: url(/public/images/directory.png) center no-repeat",
|
||||
},
|
||||
|
||||
button {
|
||||
style: "background: url(/public/images/phone.png) center no-repeat",
|
||||
},
|
||||
|
||||
button {
|
||||
style: "background: url(/public/images/medias.png) center no-repeat",
|
||||
},
|
||||
|
||||
button {
|
||||
style: "background: url(/public/images/games.png) center no-repeat",
|
||||
},
|
||||
|
||||
button {
|
||||
style: "background: url(/public/images/ban_user.png) center no-repeat",
|
||||
},
|
||||
|
||||
button {
|
||||
class: ClassName::FLEX_RIGHT_AERO_BUTTON,
|
||||
style: "background: url(/public/images/brush.png) center no-repeat",
|
||||
},
|
||||
|
||||
button {
|
||||
class: ClassName::FLEX_LAST_BUTTON,
|
||||
style: "background: url(/public/images/settings.png) center no-repeat",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
@import "../../_base.scss"
|
||||
|
||||
.navbar {
|
||||
height: 55%;
|
||||
padding-left: 2%;
|
||||
padding-right: 2%;
|
||||
|
||||
background: linear-gradient(180deg, #A9D3E0, #F0F9FA);
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
button {
|
||||
@extend .aeroButton;
|
||||
padding-right: 2%;
|
||||
}
|
||||
|
||||
.flex-right-aero-button {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.flex-last-button {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use log::debug;
|
||||
|
||||
use crate::ui::components::contacts_window::contacts_section::{
|
||||
filter_people_conversations, filter_room_conversations, ContactsSection,
|
||||
};
|
||||
|
||||
turf::style_sheet!("src/ui/components/contacts_window/contacts.scss");
|
||||
|
||||
pub fn Contacts() -> Element {
|
||||
debug!("Contacts rendering");
|
||||
|
||||
// TODO: Test overflow
|
||||
// TODO: Add offline users ?
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
|
||||
div {
|
||||
class: ClassName::CONTACTS,
|
||||
ContactsSection {name: "Groups", filter: Rc::new(filter_room_conversations)},
|
||||
ContactsSection {name: "Available", filter: Rc::new(filter_people_conversations)},
|
||||
},
|
||||
}
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
@import "../../_base.scss"
|
||||
|
||||
.contacts {
|
||||
height: 72%;
|
||||
background-color: white;
|
||||
}
|
@@ -1,149 +0,0 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_free_icons::icons::io_icons::IoChevronDown;
|
||||
use dioxus_free_icons::Icon;
|
||||
use log::debug;
|
||||
|
||||
use crate::base::{CHATS_WIN_INTERFACE, ROOMS};
|
||||
use crate::domain::model::room::{ByIdRooms, Room, RoomId};
|
||||
use crate::ui::components::chats_window::interface::Interface as ChatsWindowInterface;
|
||||
|
||||
turf::style_sheet!("src/ui/components/contacts_window/contacts_section.scss");
|
||||
|
||||
fn ContactsArrow() -> Element {
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
Icon {
|
||||
icon: IoChevronDown,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
static NO_NAME_REPR: &str = "No name";
|
||||
static NO_SUBJECT_REPR: &str = "No subject";
|
||||
|
||||
pub(super) fn filter_people_conversations(
|
||||
by_id_rooms: &GlobalSignal<ByIdRooms>,
|
||||
) -> Vec<RefCell<Room>> {
|
||||
let by_id_rooms = by_id_rooms.read();
|
||||
|
||||
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(by_id_rooms.len());
|
||||
|
||||
for room in by_id_rooms.values() {
|
||||
let is_direct = room.borrow().is_direct().unwrap();
|
||||
if !is_direct {
|
||||
filtered_rooms.push(room.to_owned());
|
||||
}
|
||||
}
|
||||
filtered_rooms
|
||||
}
|
||||
|
||||
pub(super) fn filter_room_conversations(
|
||||
by_id_rooms: &GlobalSignal<ByIdRooms>,
|
||||
) -> Vec<RefCell<Room>> {
|
||||
let by_id_rooms = by_id_rooms.read();
|
||||
|
||||
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(by_id_rooms.len());
|
||||
|
||||
for room in by_id_rooms.values() {
|
||||
let is_direct = room.borrow().is_direct().unwrap();
|
||||
if is_direct {
|
||||
filtered_rooms.push(room.to_owned());
|
||||
}
|
||||
}
|
||||
filtered_rooms
|
||||
}
|
||||
|
||||
// TODO: Handle errors
|
||||
fn on_clicked_room(room_id: &RoomId, chats_window_interface: &GlobalSignal<ChatsWindowInterface>) {
|
||||
let _ = chats_window_interface.read().toggle_room(room_id.clone());
|
||||
}
|
||||
|
||||
#[derive(Props, Clone)]
|
||||
pub struct ContactsSectionProps {
|
||||
name: String,
|
||||
filter: Rc<dyn Fn(&GlobalSignal<ByIdRooms>) -> Vec<RefCell<Room>>>,
|
||||
}
|
||||
impl PartialEq for ContactsSectionProps {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name == other.name && Rc::ptr_eq(&self.filter, &other.filter)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ContactsSection(props: ContactsSectionProps) -> Element {
|
||||
debug!("ContactsSection rendering");
|
||||
|
||||
let contacts = props.filter.to_owned()(&ROOMS);
|
||||
let contacts_len = contacts.len();
|
||||
|
||||
let mut show = use_signal(|| false);
|
||||
|
||||
let classes = [
|
||||
ClassName::SECTION,
|
||||
if *show.read() { ClassName::ACTIVE } else { "" },
|
||||
]
|
||||
.join(" ");
|
||||
|
||||
let rendered_contacts = contacts.into_iter().map(|room| {
|
||||
let room = room.borrow();
|
||||
|
||||
let topic = room.topic().clone().unwrap_or("".to_string());
|
||||
let name = match room.name() {
|
||||
Some(name) => name.clone(),
|
||||
None => NO_NAME_REPR.to_string(),
|
||||
};
|
||||
let id = room.id().clone();
|
||||
let is_invited = room.is_invited().unwrap_or(false);
|
||||
|
||||
let formatted = format!(
|
||||
"{name} - {}",
|
||||
if is_invited {
|
||||
"Invited - ".to_string()
|
||||
} else {
|
||||
"".to_string()
|
||||
}
|
||||
);
|
||||
|
||||
rsx! {
|
||||
li {
|
||||
onclick: move |_| on_clicked_room(&id, &CHATS_WIN_INTERFACE),
|
||||
img {
|
||||
src: "/public/images/status_online.png",
|
||||
},
|
||||
p {
|
||||
{formatted},
|
||||
},
|
||||
p {
|
||||
style: "color: darkgrey;",
|
||||
{topic},
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
|
||||
div {
|
||||
class: "{classes}",
|
||||
|
||||
p {
|
||||
class: ClassName::HEADER,
|
||||
onclick: move |_| {
|
||||
let state = *show.read();
|
||||
show.set(!state)
|
||||
},
|
||||
|
||||
ContactsArrow {},
|
||||
|
||||
{format!("{} ({contacts_len})", props.name)},
|
||||
},
|
||||
|
||||
ul {
|
||||
{rendered_contacts.into_iter()},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
@@ -1,67 +0,0 @@
|
||||
@import "../../_base.scss"
|
||||
|
||||
.section {
|
||||
width: 100%;
|
||||
font-size: $font-size;
|
||||
|
||||
&.active {
|
||||
ul {
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
img {
|
||||
height: $icon-size;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
transition: 0.4s ease;
|
||||
}
|
||||
|
||||
.contact {
|
||||
list-style-type: none;
|
||||
margin: 0 auto;
|
||||
text-align: left;
|
||||
cursor: pointer
|
||||
}
|
||||
}
|
@@ -1,84 +0,0 @@
|
||||
@import "../../_base.scss";
|
||||
|
||||
.contactsWindow {
|
||||
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;
|
||||
|
||||
|
||||
.header {
|
||||
height: 10%;
|
||||
width: 100%;
|
||||
|
||||
.titleBar {
|
||||
height: 60%;
|
||||
width: 100%;
|
||||
background:
|
||||
linear-gradient(180deg, #7DC5E3, #3883A3);
|
||||
}
|
||||
|
||||
.userInfo {
|
||||
height: 40%;
|
||||
width: 100%;
|
||||
background:
|
||||
linear-gradient(180deg, #00658B, #0077A6);
|
||||
}
|
||||
}
|
||||
|
||||
.contactsNav {
|
||||
height: calc(31/1080*100%);
|
||||
background:
|
||||
linear-gradient(180deg, #00658B, #0077A6);
|
||||
|
||||
.inner {
|
||||
margin-left: 1%;
|
||||
margin-right: 1%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.flexRightAeroButton {
|
||||
@extend .aeroButton;
|
||||
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search {
|
||||
height: calc(38/1080*100%);
|
||||
width: 100%;
|
||||
|
||||
border-bottom: thin solid #e2eaf3;
|
||||
|
||||
.inner {
|
||||
height: 100%;
|
||||
width: 98%;
|
||||
padding-left: 1%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.searchInput {
|
||||
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%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
height: 10%;
|
||||
}
|
||||
}
|
@@ -1,98 +0,0 @@
|
||||
mod contacts;
|
||||
mod contacts_section;
|
||||
mod user_infos;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use log::debug;
|
||||
|
||||
use crate::ui::components::contacts_window::contacts::Contacts;
|
||||
use crate::ui::components::contacts_window::user_infos::UserInfos;
|
||||
|
||||
turf::style_sheet!("src/ui/components/contacts_window/contacts_window.scss");
|
||||
|
||||
pub fn ContactsWindow() -> Element {
|
||||
debug!("ContactsWindow rendering");
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
|
||||
div {
|
||||
class: ClassName::CONTACTS_WINDOW,
|
||||
|
||||
div {
|
||||
class: ClassName::HEADER,
|
||||
|
||||
div {
|
||||
class: ClassName::TITLE_BAR,
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::USER_INFO,
|
||||
},
|
||||
|
||||
UserInfos {},
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::CONTACTS_NAV,
|
||||
div {
|
||||
class: ClassName::INNER,
|
||||
|
||||
button {
|
||||
class: ClassName::AERO_BUTTON,
|
||||
style: "background: url(/public/images/letter.png) center no-repeat",
|
||||
},
|
||||
button {
|
||||
class: ClassName::AERO_BUTTON,
|
||||
style: "background: url(/public/images/directory.png) no-repeat center",
|
||||
},
|
||||
button {
|
||||
class: ClassName::AERO_BUTTON,
|
||||
style: "background: url(/public/images/news.png) no-repeat center",
|
||||
},
|
||||
|
||||
button {
|
||||
class: ClassName::FLEX_RIGHT_AERO_BUTTON,
|
||||
style: "background: url(/public/images/brush.png) no-repeat center",
|
||||
},
|
||||
button {
|
||||
class: ClassName::AERO_BUTTON,
|
||||
style: "background: url(/public/images/settings.png) no-repeat center",
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::SEARCH,
|
||||
|
||||
div {
|
||||
class: ClassName::INNER,
|
||||
|
||||
input {
|
||||
class: ClassName::SEARCH_INPUT,
|
||||
placeholder: "Find a contact...",
|
||||
r#type: "text",
|
||||
},
|
||||
|
||||
button {
|
||||
class: ClassName::BUTTON,
|
||||
style: "background: url(/public/images/add_user.png) no-repeat center",
|
||||
},
|
||||
|
||||
button {
|
||||
class: ClassName::BUTTON,
|
||||
style: "background: url(/public/images/tbc_transfert.png) no-repeat center",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Contacts {},
|
||||
|
||||
div {
|
||||
class: ClassName::FOOTER,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
@@ -1,76 +0,0 @@
|
||||
use dioxus::prelude::*;
|
||||
use log::debug;
|
||||
|
||||
use crate::ui::components::avatar_selector::AvatarSelector;
|
||||
use crate::ui::components::icons::DownArrowIcon;
|
||||
|
||||
turf::style_sheet!("src/ui/components/contacts_window/user_infos.scss");
|
||||
|
||||
static MESSAGE_PLACEHOLDER: &str = "<Enter a personal message>";
|
||||
|
||||
pub fn UserInfos() -> Element {
|
||||
debug!("UserInfos rendering");
|
||||
|
||||
// let app_settings = use_atom_ref(cx, &APP_SETTINGS);
|
||||
// let store = &app_settings.read().store;
|
||||
|
||||
// println!("----------------------------------");
|
||||
// println!("UserInfos rendering");
|
||||
// // println!("store={:?}", &store);
|
||||
// dbg!(&store.user_id);
|
||||
// println!("----------------------------------");
|
||||
|
||||
// let user_id = store.user_id..as_ref().unwrap();
|
||||
|
||||
// let mut user_info_option = None;
|
||||
let user_display_name_option: Option<bool> = None;
|
||||
let user_display_name = "AIE";
|
||||
|
||||
// let user_id_option = &store.user_id;
|
||||
// if user_id_option.is_some() {
|
||||
// let user_id = user_id_option.as_ref().unwrap();
|
||||
// let user_info_option = store.user_infos.get(user_id);
|
||||
// if user_info_option.is_some() {
|
||||
// user_display_name_option = user_info_option.unwrap().display_name.as_ref();
|
||||
// }
|
||||
// }
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
|
||||
div {
|
||||
class: ClassName::USER_INFO,
|
||||
|
||||
div {
|
||||
class: ClassName::AVATAR_SELECTOR,
|
||||
AvatarSelector {},
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::INFO_CONTAINER,
|
||||
|
||||
div {
|
||||
class: ClassName::USER_ID,
|
||||
p {
|
||||
class: ClassName::USER_NAME,
|
||||
if user_display_name_option.is_some() { "{user_display_name}" } else { "AIE" },
|
||||
},
|
||||
p {
|
||||
class: ClassName::USER_STATUS,
|
||||
"(Busy)",
|
||||
},
|
||||
DownArrowIcon {},
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::USER_MESSAGE,
|
||||
p {
|
||||
// TODO: Handle user message
|
||||
{MESSAGE_PLACEHOLDER},
|
||||
}
|
||||
DownArrowIcon {},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
@@ -1,63 +0,0 @@
|
||||
@import "../../_base.scss"
|
||||
|
||||
.userInfo {
|
||||
position: relative;
|
||||
height: 75%;
|
||||
width: 99%;
|
||||
top: -75%;
|
||||
left: 1%;
|
||||
aspect-ratio: 1;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.avatarSelector {
|
||||
height: 100%;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
.infoContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.userId {
|
||||
@extend .aeroButton;
|
||||
|
||||
height: 30%;
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
text-align: begin;
|
||||
align-items: center;
|
||||
|
||||
.userName {
|
||||
display: inline-block;
|
||||
width: fit-content;
|
||||
color: white;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.userStatus {
|
||||
display: inline-block;
|
||||
width: fit-content;
|
||||
color: #B9DDE7;
|
||||
}
|
||||
}
|
||||
|
||||
.userMessage {
|
||||
@extend .aeroButton;
|
||||
|
||||
width: fit-content;
|
||||
height: 30%;
|
||||
display: flex;
|
||||
text-align: begin;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|