-
-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement image sending from sender #113
Implement image sending from sender #113
Conversation
25303cf
to
269bfd7
Compare
Reformatted by rust code |
5c0c00b
to
269bfd7
Compare
Reformatted by rust code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't want to send using the newly, yet to be approved MSC but instead use the existing "attachment" types.
native/effektio/Cargo.toml
Outdated
@@ -51,6 +52,9 @@ features = [ | |||
"anyhow", | |||
] | |||
|
|||
[dependencies.ruma-common] | |||
features = ["unstable-msc3552"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I appreciate you finding out there is an open msc... but there's also an already implemented version we should be doing instead...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted. Will check it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just pushed #0eb3936393570afddc6ba244aaa9ab4ba7809277 (Replace msc3552 with standard on image send)
native/effektio/src/api/room.rs
Outdated
Some(val) => UInt::new(val), | ||
None => None, | ||
}; | ||
let file = FileContent::plain(url, Some(Box::new(info))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than sending over a URI, we should be handing over the actual source-content to the SDK and use room.send_attachment
to upload it to the server and send an appropriate image message...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted. Will check it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just pushed #0eb3936393570afddc6ba244aaa9ab4ba7809277 (Replace msc3552 with standard on image send)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
native/effektio/src/api/room.rs
Outdated
@@ -205,9 +203,11 @@ impl Room { | |||
&self, | |||
message: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
message isn't used anymore.
message: String, |
native/effektio/api.rsh
Outdated
@@ -139,7 +139,7 @@ object Conversation { | |||
/// received over timeline().next() | |||
fn send_plain_message(text_message: string) -> Future<Result<string>>; | |||
|
|||
fn send_image_message(message: string, uri: string, name: Option<string>, mimetype: Option<string>, size: Option<u64>) -> Future<Result<string>>; | |||
fn send_image_message(message: string, uri: string, name: string, mimetype: string, size: u32, width: u32, height: u32) -> Future<Result<string>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
message
isn't used anymore.
The The user credential is needed before encrypted image can be decrypted. And on rust side, I implemented the class that keeps image-specific info, excluding standard message info. I used |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revert from using a global client and instead pass a client: self.client.clone()
when creating messages from the room.
Further comments inline.
native/effektio/src/api/client.rs
Outdated
@@ -47,6 +47,8 @@ impl std::ops::Deref for Client { | |||
} | |||
} | |||
|
|||
static mut CURRENT_CLIENT: Option<MatrixClient> = None; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can't do that, sorry. The client is hold by the surrounding SDK and the code may not assume that there is a global to store the current client. Why? Because the SDK is meant to allow for multi-client support (even if the UI doesn't implement it yet).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, correct.
It doesn't look smart for me too.
But I guess on rust side there is no way to manage the multiple clients and set active to some client.
Alternatively on flutter side there is currentClient
of EffektioSdk
.
If we go and back between rust and flutter, we can get delay.
Before flutter can deliver current client to rust, flutter must pass token to rust and rust must login with it, so it takes a bit of time to perform this login, because login is operation via network.
Really I tested it and confirmed delay when opening ChatScreen
page.
So I just wanted to finish all operations in rust, without go and back between rust and flutter.
Okay.
Will work from currentClient
of EffektioSdk
of flutter side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you tested it in release build?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I tested in debug build.
In that testing, 10 logins were needed when 10 image messages loaded.
Anyway, will find solution.
native/effektio/src/api/messages.rs
Outdated
_bin_data: Vec<u8>, | ||
_name: String, | ||
_mimetype: Option<String>, | ||
_size: u64, | ||
_width: Option<u64>, | ||
_height: Option<u64>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in rust all fields are private, unless prefixed with pub
. _
-prefixes are only used for internal variables, that aren't actually needed. Let's stick to that model and stay with regular names instead.
_bin_data: Vec<u8>, | |
_name: String, | |
_mimetype: Option<String>, | |
_size: u64, | |
_width: Option<u64>, | |
_height: Option<u64>, | |
bin_data: Vec<u8>, | |
name: String, | |
mimetype: Option<String>, | |
size: u64, | |
width: Option<u64>, | |
height: Option<u64>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, rust recognize _
as private property in struct.
By the way, ImageDescription
must keep the getter functions about these fields.
So I appended the prefix _
to properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, _
-prefixes are acceptable, but are unnecessary and make it needlessly harder to read, so I'd prefer we dropped them. Of course that doesn't mean we don't need the getter functions, that's totally okay. Was just talking about the style of these names...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood.
Will change property name and keep getter function name.
native/effektio/src/api/messages.rs
Outdated
} | ||
|
||
impl ImageDescription { | ||
pub async fn bin_data(&self) -> Result<api::FfiBuffer<u8>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this shouldn't copy here but only on request actually call to client and fetch the image and return it.
native/effektio/src/api/messages.rs
Outdated
} | ||
|
||
pub struct ImageDescription { | ||
_bin_data: Vec<u8>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't hold this constantly in memory here.
native/effektio/src/api/messages.rs
Outdated
let bin_data = client | ||
.get_media_content( | ||
&MediaRequest { | ||
source: content.source.clone(), | ||
format: MediaFormat::File, | ||
}, | ||
false, | ||
) | ||
.await?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we shouldn't do this here but only upon request of the actual function call.
native/effektio/src/api/messages.rs
Outdated
pub async fn image_description(&self) -> Result<ImageDescription> { | ||
match &self.inner.content.msgtype { | ||
MessageType::Image(content) => { | ||
let client = Client::current_client().unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than assuming a global, we should put client
onto the room-message (and the image description), so we can do:
let client = Client::current_client().unwrap(); | |
let client = self.client.clone(); |
native/effektio/api.rsh
Outdated
|
||
object ImageDescription { | ||
|
||
fn bin_data() -> Future<Result<buffer<u8>>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we have a better name for this function? How about image_binary
or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea
native/effektio/api.rsh
Outdated
|
||
fn msgtype() -> string; | ||
|
||
fn image_description() -> Future<Result<ImageDescription>>; | ||
} | ||
|
||
object ImageDescription { | ||
|
||
fn bin_data() -> Future<Result<buffer<u8>>>; | ||
|
||
fn name() -> string; | ||
|
||
fn mimetype() -> Option<string>; | ||
|
||
fn size() -> u64; | ||
|
||
fn width() -> Option<u64>; | ||
|
||
fn height() -> Option<u64>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add doc comments to all new functions in this file.
On flutter side:
Without mutex, it is impossible to solve these problems atomically. PS: |
Hi, Ben. |
I used I used I moved the image/file reading from message to room. |
we've just removed fluttertoast (see #119 ), please use the default Material Snackbar.
Let's not. Please use rust's |
Great idea. |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a bunch of minor API design and internal style remarks. Please fix at your own peril and merge.
/// m.audio, m.emote, m.file, m.image, m.location, m.service_notice, m.text, m.video or m.key.verification.request | ||
fn msgtype() -> string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we might want to consider switching this into an Enum
-type... but later...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's make that into an issue for later, once the PR is merged.
fn image_description() -> Result<ImageDescription>; | ||
|
||
/// contains source data, name, mimetype and size | ||
fn file_description() -> Result<FileDescription>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if there is no image/file? I assume this is then None
? Shouldn't this be Option
rather than Result
then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, I was planning to user these functions for only file/image.
Will fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to abstract image description and file description into a single struct.
But they have different fields, so I couldn't abstract them.
/// file size | ||
fn size() -> u64; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... in byte?
/// file size | |
fn size() -> u64; | |
/// file size in byte | |
fn size() -> u64; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are correct.
/// MIME | ||
fn mimetype() -> Option<string>; | ||
|
||
/// file size |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// file size | |
/// file size in byte |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are correct
fn send_image_message(uri: string, name: string, mimetype: string, size: u32, width: u32, height: u32) -> Future<Result<string>>; | ||
|
||
/// decrypted image file data | ||
fn image_binary(event_id: string) -> Future<Result<buffer<u8>>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this function not on image
or RoomMessage
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flutter keeps room as member variable in UI.
Flutter doesn't keep room message as variable, because it may have to load so many messages in screen.
So I wanted to get image binary data from member variable.
Getting temporary variable for each message may be slow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, fair enough then. keep it the way it is.
}, | ||
}; | ||
use std::{fs::File, io::Write}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think these are needed ...
use std::{fs::File, io::Write}; |
size: u32, | ||
width: u32, | ||
height: u32, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't these be optionals, too? Or can we be sure that any flutter will always provide them for us?
[room.room_id().as_str().as_bytes(), event_id.as_bytes()].concat(); | ||
client | ||
.store() | ||
.set_custom_value(&key, path.to_str().unwrap().as_bytes().to_vec()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please don't unwrap
in actual code (tests are fine). Instead always use .expect(MSG)
with a message stating, why we can be sure this never panics. e.g. :
.set_custom_value(&key, path.to_str().unwrap().as_bytes().to_vec()) | |
.set_custom_value(&key, path.to_str().expect("Path was generated from strings. Must be string").as_bytes().to_vec()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix
let path = client.store().get_custom_value(&key).await?; | ||
match path { | ||
Some(value) => { | ||
let text = std::str::from_utf8(&value).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above. please don't unwrap. always expect
.
None => Ok("".to_owned()), | ||
} | ||
} | ||
_ => Ok("".to_owned()), | ||
}, | ||
_ => Ok("".to_owned()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure, these should all be None
rather than Ok
of an empty string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
I tested image sending.
I confirmed message history appears in chat.
But image is not displayed.
Because the feature that fetches the received image is not implemented on flutter & rust.
Now implementing it.