Skip to content

Commit

Permalink
feat(chat): Quickprofile layout (#1300)
Browse files Browse the repository at this point in the history
Co-authored-by: Flemmli97 <Flemmli97@users.noreply.github.com>
Co-authored-by: Darius Clark <dariusc93@users.noreply.github.com>
Co-authored-by: Sara Tavares <29093946+stavares843@users.noreply.github.com>
Co-authored-by: sdwoodbury <stuartwoodbury@protonmail.ch>
Co-authored-by: Matt Wisniewski <infamousvaguerat@gmail.com>
  • Loading branch information
6 people authored Oct 27, 2023
1 parent a13f734 commit 0cb1e79
Show file tree
Hide file tree
Showing 11 changed files with 445 additions and 165 deletions.
277 changes: 142 additions & 135 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion common/locales/en-US/main.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ messages = Messages
.pinned-none = There are no pinned messages in this chat
.pinned-max = You reached the maximum amount of pinned messages for this chat
.missing-emoji-picker = Emoji extension is disabled
.unknown-identity = User not found:
favorites = Favorites
.favorites = Favorites
.add = Add to Favorites
Expand Down Expand Up @@ -133,6 +134,7 @@ friends = Friends
.copied-did = Copied ID to clipboard!
.unblock = Unblock
.request-exist = Friend request is already pending!
.add-name = ➕ Add { $name }
.nothing-to-see-here = Nothing to see here
files = Files
Expand Down
29 changes: 29 additions & 0 deletions common/src/warp_runner/manager/commands/multipass_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ pub enum MultiPassCmd {
username: String,
rsp: oneshot::Sender<Result<Identity, warp::error::Error>>,
},
#[display(fmt = "GetIdentity")]
GetIdentity {
did: DID,
rsp: oneshot::Sender<Result<Identity, warp::error::Error>>,
},
//#[display(fmt = "GetIdentities")]
//GetIdentities {
// dids: Vec<DID>,
Expand Down Expand Up @@ -396,6 +401,30 @@ pub async fn handle_multipass_cmd(cmd: MultiPassCmd, warp: &mut super::super::Wa
rsp.send(Err(e))
}
};
}
MultiPassCmd::GetIdentity { did, rsp } => {
let r = match warp
.multipass
.get_identity(Identifier::DID(did.clone()))
.await
{
Ok(ids) => {
if ids.is_empty() {
Err(Error::IdentityDoesntExist)
} else {
let mut id = Identity::from(ids[0].clone());
if let Ok(pic) = warp.multipass.identity_picture(&did).await {
id.set_profile_picture(&identity_image_to_base64(&pic));
}
if let Ok(banner) = warp.multipass.identity_banner(&did).await {
id.set_profile_banner(&identity_image_to_base64(&banner));
}
Ok(id)
}
}
Err(err) => Err(err),
};
let _ = rsp.send(r);
} //MultiPassCmd::GetIdentities { dids, rsp } => {
// let r = _multipass_get_identities(dids, &mut warp.multipass).await;
// let _ = rsp.send(r);
Expand Down
1 change: 1 addition & 0 deletions kit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ linkify = { workspace = true }
reqwest = { workspace = true }
base64 = { workspace = true }
mime = { workspace = true }
futures = { workspace = true }
once_cell = { workspace = true }
emojis = "0.5"
unic-segment = "0.9"
Expand Down
12 changes: 8 additions & 4 deletions kit/src/components/context_menu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ pub fn ContextItem<'a>(cx: Scope<'a, ItemProps<'a>>) -> Element<'a> {
#[derive(PartialEq, Props)]
pub struct IdentityProps {
sender_did: DID,
with_status: Option<bool>,
}

#[allow(non_snake_case)]
Expand All @@ -133,6 +134,7 @@ pub fn IdentityHeader(cx: Scope<IdentityProps>) -> Element {
.unwrap_or_default();
let image = sender.profile_picture();
let banner = sender.profile_banner();
let with_status = cx.props.with_status.unwrap_or(true);
cx.render(rsx!(
div {
class: "identity-header",
Expand All @@ -145,10 +147,12 @@ pub fn IdentityHeader(cx: Scope<IdentityProps>) -> Element {
id: "profile-image",
aria_label: "profile-image",
style: "background-image: url('{image}');",
Indicator {
status: sender.identity_status().into(),
platform: sender.platform().into(),
}
with_status.then(||{
rsx!(Indicator {
status: sender.identity_status().into(),
platform: sender.platform().into(),
})
})
}
}
}
Expand Down
1 change: 0 additions & 1 deletion kit/src/components/context_menu/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
min-width: var(--width-sidebar);
background-size: cover;
background-color: var(--secondary);
margin-bottom: var(--height-input);
padding: 0;
border-radius: var(--border-radius-inner) var(--border-radius-inner) var(--border-radius) var(--border-radius);

Expand Down
186 changes: 183 additions & 3 deletions kit/src/components/message/mod.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
use std::collections::HashSet;
use std::{collections::HashSet, str::FromStr};

use common::state::pending_message::progress_file;
use common::warp_runner::thumbnail_to_base64;
use common::language::{get_local_text, get_local_text_with_args};
use common::state::{Action, Identity, State, ToastNotification};
use common::warp_runner::{thumbnail_to_base64, MultiPassCmd, WarpCmd};
use common::{state::pending_message::progress_file, WARP_CMD_CH};
//use common::icons::outline::Shape as Icon;
use derive_more::Display;
use dioxus::prelude::*;
use futures::StreamExt;
use linkify::{LinkFinder, LinkKind};
use once_cell::sync::Lazy;
use pulldown_cmark::{CodeBlockKind, Options, Tag};
use regex::Regex;
use warp::error::Error;
use warp::{
constellation::{file::File, Progression},
crypto::DID,
logging::tracing::log,
};

use common::icons::outline::Shape as Icon;

use crate::components::context_menu::IdentityHeader;
use crate::elements::button::Button;
use crate::{components::embeds::file_embed::FileEmbed, elements::textarea};

use super::embeds::link_embed::EmbedLinks;
Expand Down Expand Up @@ -332,6 +339,9 @@ pub struct ChatMessageProps {

#[allow(non_snake_case)]
pub fn ChatText(cx: Scope<ChatMessageProps>) -> Element {
if let Ok(id) = DID::from_str(&cx.props.text) {
return cx.render(rsx!(IdentityMessage { id: id }));
}
let mut formatted_text = format_text(&cx.props.text, cx.props.markdown, cx.props.ascii_emoji);
formatted_text = wrap_links_with_a_tags(&formatted_text);

Expand Down Expand Up @@ -547,6 +557,176 @@ fn markdown(text: &str, emojis: bool) -> String {
html_output
}

#[derive(Display)]
pub enum IdentityCmd {
#[display(fmt = "GetIdentity")]
GetIdentity(DID),
#[display(fmt = "SentFriendRequest")]
SentFriendRequest(String, Vec<Identity>),
}

#[derive(Props, PartialEq)]
pub struct IdentityMessageProps {
id: DID,
}

#[allow(non_snake_case)]
pub fn IdentityMessage(cx: Scope<IdentityMessageProps>) -> Element {
let state = use_shared_state::<State>(cx)?;
let identity = use_state(cx, || None);
let ch = use_coroutine(cx, |mut rx: UnboundedReceiver<IdentityCmd>| {
to_owned![identity, state];
async move {
let warp_cmd_tx = WARP_CMD_CH.tx.clone();
while let Some(cmd) = rx.next().await {
match cmd {
IdentityCmd::GetIdentity(id) => {
let (tx, rx) = futures::channel::oneshot::channel();
let _ = warp_cmd_tx.send(WarpCmd::MultiPass(MultiPassCmd::GetIdentity {
did: id,
rsp: tx,
}));
let r = rx.await.expect("no identity found");
if let Ok(id) = r {
identity.set(Some(id));
}
}
IdentityCmd::SentFriendRequest(id, outgoing_requests) => {
let (tx, rx) = futures::channel::oneshot::channel();
let _ = warp_cmd_tx.send(WarpCmd::MultiPass(MultiPassCmd::RequestFriend {
id,
outgoing_requests,
rsp: tx,
}));
let res = rx.await.expect("failed to get response from warp_runner");
match res {
Ok(_) => {}
Err(e) => match e {
Error::PublicKeyIsBlocked => {
log::warn!("add friend failed: {}", e);
state.write().mutate(Action::AddToastNotification(
ToastNotification::init(
"".into(),
get_local_text("friends.key-blocked"),
None,
2,
),
));
}
_ => {
//The other errors are covered by button already
log::error!("add friend failed: {}", e);
state.write().mutate(Action::AddToastNotification(
ToastNotification::init(
"".into(),
get_local_text("friends.add-failed"),
None,
2,
),
));
}
},
}
}
}
}
}
});
use_effect(cx, &cx.props.id, |id| {
to_owned![ch];
async move {
ch.send(IdentityCmd::GetIdentity(id));
}
});
match identity.as_ref() {
Some(identity) => {
let disabled = state
.read()
.outgoing_fr_identities()
.iter()
.any(|req| req.did_key().eq(&identity.did_key()))
|| state
.read()
.get_own_identity()
.did_key()
.eq(&identity.did_key())
|| state
.read()
.friend_identities()
.iter()
.any(|req| req.did_key().eq(&identity.did_key()));
return cx.render(rsx!(div {
class: "embed-identity",
IdentityHeader {
sender_did: identity.did_key(),
with_status: false,
},
div {
class: "profile-container",
div {
id: "profile-name",
aria_label: "profile-name",
p {
class: "text",
aria_label: "profile-name-value",
format!("{}", identity.username())
}
}
identity.status_message().and_then(|s|{
cx.render(rsx!(
div {
id: "profile-status",
aria_label: "profile-status",
p {
class: "text",
aria_label: "profile-status-value",
s
}
}
))
}),
},
Button {
aria_label: String::from("embed-identity-button"),
disabled: disabled,
with_title: false,
onpress: move |_| {
ch.send(IdentityCmd::SentFriendRequest(identity.did_key().to_string(), state.read().outgoing_fr_identities()));
},
text: get_local_text_with_args("friends.add-name", vec![("name", identity.username().into())]),
appearance: crate::elements::Appearance::Primary
}
}));
}
None => {
return cx.render(rsx!(div {
class: "embed-identity",
div {
class: "profile-container empty-profile",
div {
class: "unknown-user",
aria_label: "unknown-user",
p {
class: "text",
aria_label: "unknown-user-value",
get_local_text("messages.unknown-identity")
}
},
div {
id: "unknown-user-did",
aria_label: "unknown-user-did",
p {
class: "text",
aria_label: "unknown-user-did-value",
cx.props.id.to_string()
}
}
}
}))
}
}
}

use unic_emoji_char::{
is_emoji, is_emoji_component, is_emoji_modifier, is_emoji_modifier_base, is_emoji_presentation,
};
Expand Down
34 changes: 34 additions & 0 deletions kit/src/components/message/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,38 @@
fill: transparent;
stroke: var(--text-color-link);
}
}

.embed-identity {
display: flex;
flex-direction: column;
.profile-container {
max-width: 300px;
}
.empty-profile {
margin-left: 0;
}
.unknown-user {
.text {
font-size: var(--text-size-more);
}
}
.unknown-user-did {
.text {
font-size: var(--text-size-less);
}
}
.btn-wrap {
padding-top: var(--padding-less);
.btn {
max-width: calc(var(--height-input) * 2 + 300px);
width: 100%;
.btn-text {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
color: var(--text-color-dark);
}
}
}
}
Loading

0 comments on commit 0cb1e79

Please sign in to comment.