⬆️ Use of Dioxus main branch instead of 0.5 release
This commit is contained in:
17
Cargo.toml
17
Cargo.toml
@@ -43,30 +43,35 @@ tracing-forest = "0.1.6"
|
||||
turf = "0.8.0"
|
||||
|
||||
# Dioxus
|
||||
dioxus = { version = "0.5", default-features = false }
|
||||
dioxus-free-icons = { version = "0.8", features = ["ionicons", "font-awesome-solid"] }
|
||||
# dioxus-free-icons = { version = "0.8", features = ["ionicons", "font-awesome-solid"] }
|
||||
dioxus-free-icons = { git = "https://github.com/ASR-ASU/dioxus-free-icons.git", branch = "asr/dioxus-0.6", features = ["ionicons", "font-awesome-solid"] }
|
||||
modx = "0.1.2"
|
||||
|
||||
[patch.crates-io]
|
||||
dioxus = { git = "https://github.com/DioxusLabs/dioxus.git" }
|
||||
# Matrix rich text editor
|
||||
wysiwyg = { path = "../matrix.org/matrix-rich-text-editor/crates/wysiwyg/" }
|
||||
|
||||
[target.'cfg(target_family = "wasm")'.dependencies]
|
||||
# Logging/tracing
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
tracing-web = "0.1.3"
|
||||
|
||||
# Dioxus
|
||||
dioxus = { features = ["web"] }
|
||||
dioxus = { git = "https://github.com/DioxusLabs/dioxus.git", branch = "main", features = ["web"] }
|
||||
web-sys = "0.3.69"
|
||||
|
||||
# Matrix
|
||||
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk.git", default-features = false, features = ["rustls-tls", "js"] }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||
# Utils
|
||||
time = "0.3.36"
|
||||
|
||||
# Logging/tracing
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "time"] }
|
||||
|
||||
# Dioxus
|
||||
dioxus = { features = ["desktop"] }
|
||||
dioxus = { git = "https://github.com/DioxusLabs/dioxus.git", branch = "main", features = ["desktop"] }
|
||||
|
||||
# Matrix
|
||||
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk.git", default-features = false, features = ["rustls-tls"] }
|
||||
|
||||
|
@@ -9,7 +9,7 @@ use dioxus::prelude::Task;
|
||||
use matrix_sdk::{
|
||||
config::SyncSettings,
|
||||
event_handler::Ctx,
|
||||
media::{MediaFormat, MediaRequest, MediaThumbnailSize},
|
||||
media::{MediaFormat, MediaRequest, MediaThumbnailSettings, MediaThumbnailSize},
|
||||
room::{ParentSpace, Room},
|
||||
ruma::{
|
||||
api::client::media::get_content_thumbnail::v3::Method,
|
||||
@@ -448,10 +448,13 @@ impl Client {
|
||||
async fn on_room_avatar_event(room: &Room, senders: &Ctx<Senders>) {
|
||||
let room_id = room.room_id();
|
||||
let avatar = match room
|
||||
.avatar(MediaFormat::Thumbnail(MediaThumbnailSize {
|
||||
.avatar(MediaFormat::Thumbnail(MediaThumbnailSettings {
|
||||
size: MediaThumbnailSize {
|
||||
method: Method::Scale,
|
||||
width: uint!(256),
|
||||
height: uint!(256),
|
||||
},
|
||||
animated: false,
|
||||
}))
|
||||
.await
|
||||
{
|
||||
@@ -668,10 +671,13 @@ impl Client {
|
||||
|
||||
match client
|
||||
.account()
|
||||
.get_avatar(MediaFormat::Thumbnail(MediaThumbnailSize {
|
||||
.get_avatar(MediaFormat::Thumbnail(MediaThumbnailSettings {
|
||||
size: MediaThumbnailSize {
|
||||
method: Method::Scale,
|
||||
width: uint!(256),
|
||||
height: uint!(256),
|
||||
},
|
||||
animated: false,
|
||||
}))
|
||||
.await
|
||||
{
|
||||
@@ -685,10 +691,13 @@ impl Client {
|
||||
|
||||
if let Some(room) = client.get_room(room_id) {
|
||||
match room
|
||||
.avatar(MediaFormat::Thumbnail(MediaThumbnailSize {
|
||||
.avatar(MediaFormat::Thumbnail(MediaThumbnailSettings {
|
||||
size: MediaThumbnailSize {
|
||||
method: Method::Scale,
|
||||
width: uint!(256),
|
||||
height: uint!(256),
|
||||
},
|
||||
animated: false,
|
||||
}))
|
||||
.await
|
||||
{
|
||||
@@ -709,10 +718,13 @@ impl Client {
|
||||
|
||||
let request = MediaRequest {
|
||||
source: MediaSource::Plain(media_url),
|
||||
format: MediaFormat::Thumbnail(MediaThumbnailSize {
|
||||
format: MediaFormat::Thumbnail(MediaThumbnailSettings {
|
||||
size: MediaThumbnailSize {
|
||||
method: Method::Scale,
|
||||
width: uint!(256),
|
||||
height: uint!(256),
|
||||
},
|
||||
animated: false,
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -739,10 +751,13 @@ impl Client {
|
||||
Ok(room_member) => {
|
||||
if let Some(room_member) = room_member {
|
||||
let res = match room_member
|
||||
.avatar(MediaFormat::Thumbnail(MediaThumbnailSize {
|
||||
.avatar(MediaFormat::Thumbnail(MediaThumbnailSettings {
|
||||
size: MediaThumbnailSize {
|
||||
method: Method::Scale,
|
||||
width: uint!(256),
|
||||
height: uint!(256),
|
||||
},
|
||||
animated: false,
|
||||
}))
|
||||
.await
|
||||
{
|
||||
|
@@ -21,19 +21,14 @@ turf::style_sheet!("src/ui/components/conversations.scss");
|
||||
|
||||
#[component]
|
||||
fn AccountAvatar(content: Option<Vec<u8>>, class_name: Option<String>) -> Element {
|
||||
match content {
|
||||
Some(content) => {
|
||||
let encoded = general_purpose::STANDARD.encode(content);
|
||||
rsx! {
|
||||
if let Some(content) = content {
|
||||
div {
|
||||
class: class_name,
|
||||
background_image: format!("url(data:image/jpeg;base64,{encoded})")
|
||||
background_image: format!("url(data:image/jpeg;base64,{})", general_purpose::STANDARD.encode(content))
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Manage acount without avatar
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
@@ -54,11 +49,11 @@ fn PresenceState(state: Option<DomainPresenceState>, class_name: Option<String>)
|
||||
rsx! {
|
||||
div {
|
||||
class: classes,
|
||||
LogoIcon {},
|
||||
LogoIcon {}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
None => VNode::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,12 +65,12 @@ fn DisplayName(display_name: Option<String>, class_name: Option<String>) -> Elem
|
||||
div {
|
||||
class: class_name,
|
||||
p {
|
||||
{display_name},
|
||||
{display_name}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
None => VNode::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,37 +132,35 @@ pub fn Account() -> Element {
|
||||
});
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
|
||||
div {
|
||||
class: ClassName::ACCOUNT,
|
||||
|
||||
{avatar},
|
||||
{presence_state},
|
||||
{display_name},
|
||||
{avatar}
|
||||
{presence_state}
|
||||
{display_name}
|
||||
|
||||
{status},
|
||||
{status}
|
||||
|
||||
div {
|
||||
class: ClassName::ACCOUNT_SPACES,
|
||||
Button {
|
||||
SpacesIcon {},
|
||||
SpacesIcon {}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::ACCOUNT_CHAT,
|
||||
Button {
|
||||
ChatsIcon {},
|
||||
ChatsIcon {}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::ACCOUNT_ROOM,
|
||||
Button {
|
||||
RoomsIcon {},
|
||||
RoomsIcon {}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,8 +168,8 @@ pub fn Account() -> Element {
|
||||
#[component]
|
||||
pub fn ConversationAvatar(
|
||||
room_id: RoomId,
|
||||
on_selected: EventHandler<RoomId>,
|
||||
on_pressed: EventHandler<RoomId>,
|
||||
on_selected: Option<EventHandler<RoomId>>,
|
||||
on_pressed: Option<EventHandler<RoomId>>,
|
||||
) -> Element {
|
||||
let long_press_duration = Duration::from_millis(500);
|
||||
|
||||
@@ -185,7 +178,7 @@ pub fn ConversationAvatar(
|
||||
let room_id = Rc::new(room_id);
|
||||
let room_name = room.name();
|
||||
|
||||
let selected_room_id = use_context::<Signal<Option<RoomId>>>();
|
||||
let selected_room_id = use_signal(|| None::<RoomId>);
|
||||
|
||||
let invited_badge = if room.is_invited() {
|
||||
rsx! {
|
||||
@@ -193,12 +186,12 @@ pub fn ConversationAvatar(
|
||||
class: ClassName::CONVERSATION_AVATAR_INVITED_BADGE,
|
||||
|
||||
p {
|
||||
"Invited",
|
||||
"Invited"
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
VNode::empty()
|
||||
};
|
||||
|
||||
let is_selected = match selected_room_id.read().as_ref() {
|
||||
@@ -206,7 +199,6 @@ pub fn ConversationAvatar(
|
||||
None => false,
|
||||
};
|
||||
|
||||
// let avatar = if let Some(Some(content)) = &*avatar.read() {
|
||||
let avatar = if let Some(content) = room.avatar() {
|
||||
let encoded = general_purpose::STANDARD.encode(content);
|
||||
rsx! {
|
||||
@@ -230,7 +222,7 @@ pub fn ConversationAvatar(
|
||||
div {
|
||||
class: ClassName::CONVERSATION_AVATAR_IMAGE,
|
||||
|
||||
{placeholder},
|
||||
{placeholder}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -244,12 +236,12 @@ pub fn ConversationAvatar(
|
||||
let on_press = {
|
||||
let room_id = room_id.clone();
|
||||
move || {
|
||||
on_selected.call(room_id.as_ref().clone());
|
||||
on_selected.map(|c| c.call(room_id.as_ref().clone()));
|
||||
}
|
||||
};
|
||||
|
||||
let on_long_press = move || {
|
||||
on_pressed.call(room_id.as_ref().clone());
|
||||
on_pressed.map(|c| c.call(room_id.as_ref().clone()));
|
||||
};
|
||||
|
||||
let long_press_hook = use_long_press(long_press_duration, on_press, on_long_press);
|
||||
@@ -302,7 +294,7 @@ pub fn ConversationsCarousel(
|
||||
onscroll: move |_| {
|
||||
// Catch scrolling events.
|
||||
},
|
||||
{rendered_avatars},
|
||||
{rendered_avatars}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -367,8 +359,6 @@ pub fn Space(id: Option<SpaceId>, on_pressed_conversation: EventHandler<RoomId>)
|
||||
let classes_str = space_classes.join(" ");
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
|
||||
div {
|
||||
class: "{classes_str}",
|
||||
|
||||
@@ -382,17 +372,17 @@ pub fn Space(id: Option<SpaceId>, on_pressed_conversation: EventHandler<RoomId>)
|
||||
p {
|
||||
{name}
|
||||
}
|
||||
},
|
||||
}
|
||||
ConversationsCarousel {
|
||||
on_selected_conversation,
|
||||
on_pressed_conversation,
|
||||
},
|
||||
}
|
||||
div {
|
||||
class: ClassName::SPACE_CONVERSATION_NAME,
|
||||
p {
|
||||
{selected_room_name},
|
||||
{selected_room_name}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -412,19 +402,24 @@ pub fn Spaces(on_pressed_conversation: EventHandler<RoomId>) -> Element {
|
||||
div {
|
||||
class: ClassName::SPACES,
|
||||
|
||||
{rendered_spaces},
|
||||
{rendered_spaces}
|
||||
|
||||
Space { on_pressed_conversation },
|
||||
Space { on_pressed_conversation }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Search() -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
class: ClassName::SEARCH,
|
||||
|
||||
div {
|
||||
class: ClassName::SEARCH_TEXT,
|
||||
|
||||
TextInput {}
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::SEARCH_BUTTON,
|
||||
@@ -437,7 +432,15 @@ pub fn Search() -> Element {
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn ConversationOptionsMenu(room_id: RoomId, on_close: EventHandler) -> Element {
|
||||
fn ConversationOptionsMenu(
|
||||
room_id: RoomId,
|
||||
on_close: EventHandler,
|
||||
on_join: EventHandler,
|
||||
) -> Element {
|
||||
let room = STORE.read().rooms().get(&room_id).unwrap().signal();
|
||||
|
||||
let topic = room.topic().unwrap_or("<No topic set>".to_string());
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
class: ClassName::CONVERSATION_OPTIONS_MENU,
|
||||
@@ -447,31 +450,44 @@ fn ConversationOptionsMenu(room_id: RoomId, on_close: EventHandler) -> Element {
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_AVATAR,
|
||||
ConversationAvatar { room_id }
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_NAME,
|
||||
p {
|
||||
{room.name()}
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_TOPIC,
|
||||
p {
|
||||
{topic}
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_CONFIG,
|
||||
p {
|
||||
"Coming soon..."
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_CLOSE_BUTTON,
|
||||
RejectButton {
|
||||
onclick: move |_| on_close(()),
|
||||
onclick: move |_| on_close(())
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATION_OPTIONS_MENU_INNER_JOIN_BUTTON,
|
||||
JoinButton {
|
||||
onclick: move |_| on_close(()),
|
||||
onclick: move |_| {
|
||||
on_join(());
|
||||
on_close(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -480,37 +496,54 @@ fn ConversationOptionsMenu(room_id: RoomId, on_close: EventHandler) -> Element {
|
||||
}
|
||||
|
||||
pub fn Conversations() -> Element {
|
||||
let mut conversation_options_menu = use_signal(|| None::<Element>);
|
||||
let mut room_id = use_signal(|| None::<RoomId>);
|
||||
|
||||
let on_conversation_options_menu_close = move |_| {
|
||||
conversation_options_menu.set(None);
|
||||
let on_menu_close = move |_| {
|
||||
room_id.set(None);
|
||||
};
|
||||
|
||||
let on_pressed_conversation = move |room_id: RoomId| {
|
||||
conversation_options_menu.set(Some(rsx! { ConversationOptionsMenu { room_id, on_close: on_conversation_options_menu_close } }));
|
||||
let on_menu_join = move |_| async move {
|
||||
let rooms = STORE.read().rooms();
|
||||
if let Some(room_id) = room_id.read().to_owned() {
|
||||
if let Some(room) = rooms.get(&room_id) {}
|
||||
}
|
||||
};
|
||||
|
||||
let on_pressed_conversation = move |id: RoomId| {
|
||||
room_id.set(Some(id));
|
||||
};
|
||||
|
||||
let menu = match room_id.read().as_ref() {
|
||||
Some(room_id) => {
|
||||
let room_id = room_id.clone();
|
||||
rsx! {
|
||||
ConversationOptionsMenu { room_id, on_close: on_menu_close, on_join: on_menu_join }
|
||||
}
|
||||
}
|
||||
None => VNode::empty(),
|
||||
};
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
style { {STYLE_SHEET} }
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS,
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_ACCOUNT,
|
||||
Account {},
|
||||
},
|
||||
Account {}
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_SPACES,
|
||||
Spaces { on_pressed_conversation },
|
||||
},
|
||||
Spaces { on_pressed_conversation }
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_SEARCH,
|
||||
Search {},
|
||||
},
|
||||
},
|
||||
{conversation_options_menu}
|
||||
Search {}
|
||||
}
|
||||
}
|
||||
{menu}
|
||||
}
|
||||
}
|
||||
|
@@ -268,6 +268,11 @@
|
||||
display: flex;
|
||||
gap: 5%;
|
||||
|
||||
&__text {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__button {
|
||||
@include button-class();
|
||||
|
||||
@@ -313,6 +318,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
%base-helper-text {
|
||||
margin: 0;
|
||||
margin-top: 0.3vh;
|
||||
|
||||
font-size: 1.2vh;
|
||||
|
||||
// TODO: Set color used for text in _base.scss file
|
||||
color: get-color(greyscale, 90);
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
|
||||
&.invalid {
|
||||
color: get-color(critical, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.conversation-options-menu {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -355,23 +378,50 @@
|
||||
|
||||
width: 100%;
|
||||
aspect-ratio: 1;
|
||||
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
&__name {
|
||||
grid-area: name;
|
||||
background-color: orange;
|
||||
|
||||
// TODO: Merge with &__display-name
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
p {
|
||||
font-size: 2.5vh;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
&__topic {
|
||||
grid-area: topic;
|
||||
background-color: aqua;
|
||||
|
||||
// TODO: Merge with &__display-name
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@extend %base-helper-text;
|
||||
p {
|
||||
font-size: 2vh;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
&__config {
|
||||
grid-area: config;
|
||||
background-color: purple;
|
||||
|
||||
// TODO: Merge with &__display-name
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
border: $border-thin;
|
||||
border-color: get-color(ternary, 90);
|
||||
border-radius: $border-radius;
|
||||
}
|
||||
|
||||
button {
|
||||
|
@@ -76,10 +76,10 @@ pub fn Modal(props: ModalProps) -> Element {
|
||||
Severity::Critical => ErrorButton,
|
||||
};
|
||||
|
||||
icon.as_ref()?;
|
||||
icon.as_ref().ok_or(VNode::empty());
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
style { {STYLE_SHEET} }
|
||||
|
||||
div {
|
||||
class: ClassName::MODAL,
|
||||
@@ -90,17 +90,17 @@ pub fn Modal(props: ModalProps) -> Element {
|
||||
div {
|
||||
class: ClassName::MODAL_CONTENT_ICON,
|
||||
{icon}
|
||||
},
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::MODAL_CONTENT_TITLE,
|
||||
{props.title},
|
||||
},
|
||||
{props.title}
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::MODAL_CONTENT_MSG,
|
||||
{props.children},
|
||||
},
|
||||
{props.children}
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::MODAL_CONTENT_BUTTONS,
|
||||
@@ -109,10 +109,10 @@ pub fn Modal(props: ModalProps) -> Element {
|
||||
if let Some(cb) = &props.on_confirm {
|
||||
cb.call(evt);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -67,7 +67,7 @@ pub fn TextInput(props: InputProps<TextInputState>) -> Element {
|
||||
let input_classes_str = [ClassName::TEXT_INPUT_INPUT, criticity_class].join(" ");
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
style { {STYLE_SHEET} }
|
||||
|
||||
div {
|
||||
class: ClassName::TEXT_INPUT,
|
||||
@@ -83,7 +83,7 @@ pub fn TextInput(props: InputProps<TextInputState>) -> Element {
|
||||
cb.call(evt);
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::TEXT_INPUT_HELPER_TEXT,
|
||||
@@ -159,7 +159,7 @@ pub fn PasswordTextInput(props: InputProps<PasswordInputState>) -> Element {
|
||||
let input_classes = [ClassName::PASSWORD_TEXT_INPUT_INPUT, criticity_class].join(" ");
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
style { {STYLE_SHEET} }
|
||||
|
||||
div {
|
||||
class: "{text_input_classes}",
|
||||
@@ -175,7 +175,7 @@ pub fn PasswordTextInput(props: InputProps<PasswordInputState>) -> Element {
|
||||
cb.call(evt);
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if let Some(score) = score {
|
||||
div {
|
||||
@@ -184,7 +184,7 @@ pub fn PasswordTextInput(props: InputProps<PasswordInputState>) -> Element {
|
||||
ratio: score,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::PASSWORD_TEXT_INPUT_SHOW_TOGGLE,
|
||||
@@ -203,7 +203,7 @@ pub fn PasswordTextInput(props: InputProps<PasswordInputState>) -> Element {
|
||||
icon: IoEye,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::PASSWORD_TEXT_INPUT_HELPER_TEXT,
|
||||
@@ -212,7 +212,7 @@ pub fn PasswordTextInput(props: InputProps<PasswordInputState>) -> Element {
|
||||
class: criticity_class,
|
||||
{helper_text}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
@import "../_base.scss"
|
||||
@import "../_base.scss";
|
||||
|
||||
%base-text-input {
|
||||
$horizontal-padding: 1vw;
|
||||
|
@@ -14,20 +14,20 @@ pub fn use_long_press(
|
||||
on_long_press: impl FnMut() + 'static,
|
||||
) -> UseLongPress {
|
||||
let on_press = std::rc::Rc::new(RefCell::new(on_press));
|
||||
let on_press_cb = use_callback(move || {
|
||||
let on_press_cb = use_callback(move |_| {
|
||||
let mut on_press = on_press.as_ref().borrow_mut();
|
||||
on_press();
|
||||
});
|
||||
|
||||
let on_long_press = std::rc::Rc::new(RefCell::new(on_long_press));
|
||||
let on_long_press_cb = use_callback(move || {
|
||||
let on_long_press_cb = use_callback(move |_| {
|
||||
let mut on_long_press = on_long_press.as_ref().borrow_mut();
|
||||
on_long_press();
|
||||
});
|
||||
|
||||
let mut timer = use_future(move || async move {
|
||||
task::sleep(duration).await;
|
||||
on_long_press_cb.call();
|
||||
on_long_press_cb.call(());
|
||||
});
|
||||
|
||||
timer.cancel();
|
||||
@@ -39,7 +39,7 @@ pub fn use_long_press(
|
||||
let selection_end_cb = move |_: Event<PlatformEventData>| {
|
||||
if !timer.finished() {
|
||||
timer.cancel();
|
||||
on_press_cb.call();
|
||||
on_press_cb.call(());
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,15 +1,19 @@
|
||||
use std::rc::Rc;
|
||||
use std::{collections::HashSet, rc::Rc};
|
||||
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
use dioxus::prelude::*;
|
||||
use futures::join;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::ui::{
|
||||
use crate::{
|
||||
domain::model::room::RoomId,
|
||||
ui::{
|
||||
components::{
|
||||
chat_panel::ChatPanel, conversations::Conversations as ConversationsComponent,
|
||||
wallpaper::Wallpaper,
|
||||
},
|
||||
STORE,
|
||||
},
|
||||
};
|
||||
|
||||
turf::style_sheet!("src/ui/layouts/conversations.scss");
|
||||
@@ -66,7 +70,7 @@ fn LayoutSmall() -> Element {
|
||||
let inner = rsx! {
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW_SMALL_PANEL_INNER,
|
||||
ChatPanel { name: format!("CHAT {room_name_repr}") },
|
||||
ChatPanel { name: format!("CHAT {room_name_repr}") }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -88,7 +92,7 @@ fn LayoutSmall() -> Element {
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(panel) = panel {
|
||||
if let Ok(panel) = panel {
|
||||
conversation_panels.push(panel);
|
||||
}
|
||||
} else {
|
||||
@@ -97,7 +101,7 @@ fn LayoutSmall() -> Element {
|
||||
}
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
style { {STYLE_SHEET} }
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW_SMALL,
|
||||
@@ -133,9 +137,9 @@ fn LayoutSmall() -> Element {
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW_SMALL_CONVERSATIONS_PANEL_INNER,
|
||||
ConversationsComponent {},
|
||||
},
|
||||
},
|
||||
ConversationsComponent {}
|
||||
}
|
||||
}
|
||||
|
||||
{conversation_panels.iter()}
|
||||
|
||||
@@ -164,33 +168,33 @@ fn LayoutBig() -> Element {
|
||||
is_first = false;
|
||||
rsx! {
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW_BIG_CONVERSATION_PANELS_PANEL,
|
||||
class: ClassName::CONVERSATIONS_VIEW_BIG_CONVERSATIONS_PANELS_PANEL,
|
||||
onmounted: move |cx| async move {
|
||||
let data = cx.data();
|
||||
let _ = data.as_ref().scroll_to(ScrollBehavior::Smooth).await;
|
||||
first_div.set(Some(data));
|
||||
},
|
||||
ChatPanel { name: room_name_repr },
|
||||
ChatPanel { name: room_name_repr }
|
||||
}
|
||||
}
|
||||
} else if displayed_room_ids_it.peek().is_none() {
|
||||
rsx! {
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW_BIG_CONVERSATION_PANELS_PANEL,
|
||||
class: ClassName::CONVERSATIONS_VIEW_BIG_CONVERSATIONS_PANELS_PANEL,
|
||||
onmounted: move |cx: Event<MountedData>| last_div.set(Some(cx.data())),
|
||||
ChatPanel { name: room_name_repr },
|
||||
ChatPanel { name: room_name_repr }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rsx! {
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW_BIG_CONVERSATION_PANELS_PANEL,
|
||||
ChatPanel { name: room_name_repr },
|
||||
class: ClassName::CONVERSATIONS_VIEW_BIG_CONVERSATIONS_PANELS_PANEL,
|
||||
ChatPanel { name: room_name_repr }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(panel) = panel {
|
||||
if let Ok(panel) = panel {
|
||||
conversation_panels.push(panel);
|
||||
}
|
||||
} else {
|
||||
@@ -199,7 +203,7 @@ fn LayoutBig() -> Element {
|
||||
}
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
style { {STYLE_SHEET} }
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW_BIG,
|
||||
@@ -207,11 +211,16 @@ fn LayoutBig() -> Element {
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW_BIG_CONVERSATIONS_PANEL,
|
||||
|
||||
ConversationsComponent {},
|
||||
},
|
||||
ConversationsComponent {}
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW_BIG_CONVERSATION_PANELS,
|
||||
class: ClassName::CONVERSATIONS_VIEW_BIG_CONVERSATIONS,
|
||||
|
||||
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW_BIG_CONVERSATIONS_PANELS,
|
||||
|
||||
onmounted: move |cx| async move {
|
||||
let data = cx.data();
|
||||
@@ -239,8 +248,8 @@ fn LayoutBig() -> Element {
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW_TAIL,
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,29 +258,29 @@ pub fn Conversations() -> Element {
|
||||
let mut layout = use_signal(|| None::<VNode>);
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
style { {STYLE_SHEET} }
|
||||
|
||||
Wallpaper {
|
||||
display_version: true
|
||||
},
|
||||
}
|
||||
|
||||
div {
|
||||
class: ClassName::CONVERSATIONS_VIEW,
|
||||
|
||||
onresized: move |cx| {
|
||||
onresize: move |cx| {
|
||||
let data = cx.data();
|
||||
let mut use_big_layout = false;
|
||||
|
||||
if let Ok(size) = data.get_border_box_size() {
|
||||
if let Some(size) = size.first() {
|
||||
// Use LayoutBig if the layout can contain 2 panels side by side
|
||||
let component_width = size.height * INNER_PANEL_HEIGHT_RATIO * ASPECT_RATIO;
|
||||
let breakpoint_width = component_width * 2_f64;
|
||||
use_big_layout = size.width > breakpoint_width;
|
||||
}
|
||||
}
|
||||
|
||||
layout.set(rsx! { if use_big_layout { LayoutBig {} } else { LayoutSmall {} }});
|
||||
// let layout_result = rsx! { if use_big_layout { LayoutBig {} } else { LayoutSmall {} }};
|
||||
let layout_result = rsx! { LayoutBig {} };
|
||||
layout.set(Some(layout_result.unwrap()));
|
||||
},
|
||||
|
||||
{layout}
|
||||
|
@@ -110,11 +110,29 @@ $inner-panel-height-ratio: 0.95;
|
||||
aspect-ratio: $aspect-ratio;
|
||||
}
|
||||
|
||||
&__conversation-panels {
|
||||
&__conversations {
|
||||
height: $content-height;
|
||||
min-width: 64px;
|
||||
|
||||
flex-grow: 1;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $gap;
|
||||
|
||||
&__tabs-bar {
|
||||
height: 5%;
|
||||
width: 100%;
|
||||
|
||||
flex-grow: 0;
|
||||
|
||||
// overflow: scroll;
|
||||
// scrollbar-width: none;
|
||||
}
|
||||
|
||||
&__panels {
|
||||
flex-grow: 1;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow-x: scroll;
|
||||
@@ -135,4 +153,5 @@ $inner-panel-height-ratio: 0.95;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user