flyerhq / flutter_chat_ui

Actively maintained, community-driven chat UI implementation with an optional Firebase BaaS.
https://flyer.chat
1.65k stars 710 forks source link

User image from memory #308

Closed AdrKacz closed 1 week ago

AdrKacz commented 2 years ago

Hello 👋

I want my avatar saved locally and not from an external URL. How could I do that?

For now, I have:

types.User(
          id: author,
          imageUrl: <myUrl>)

However, the image won't be saved online but only on the client, so I'd like to have:

types.User(
          id: author,
          imageProvider: <myImageProvider>)

Or

types.User(
          id: author,
          image: <myImage>)

It shouldn't be far from the current implementation. imageUrl may be fed into an Image. Network or NetworkImage at some point. How could I remove this abstraction layer to display any image I want?

Thank you for this fantastic framework,

Adrien

Yogesh-Dubey-Ayesavi commented 2 years ago

I think the process is really straight forward for this probably you need to fork the flutter_chat_types then clone it after changing the required attributes do not forget to run the command flutter pub run build_runner build

in order to bring changes in the to json or from json methods mentioned in user.g.dart

But i think the more better option is to provide an avatar builder where you will pass the file path of the image. as far as i can understand your problem this solution fit's perfect as per your requirement otherwise you can go for the one i mentioned above.

https://github.com/flyerhq/flutter_chat_ui/blob/802a41f1b52f38808e8bd9e7d83c40a180c3ea5b/lib/src/widgets/chat.dart#L34

demchenkoalex commented 2 years ago

If I will do

if (uri.startsWith('http')) {
  return NetworkImage(uri);
} else {
  return FileImage(File(uri));
}

this will work?

you will pass local path to the imageUrl instead of the remote url. The parameter should be eventually renamed to the imageUri I guess.

Types are pretty dumb dart code, I can't use Flutter's providers or images there.

AdrKacz commented 2 years ago

I think the process is really straight forward for this probably you need to fork the flutter_chat_types then clone it after changing the required attributes do not forget to run the command

flutter pub run build_runner build

in order to bring changes in the to json or from json methods mentioned in user.g.dart

But i think the more better option is to provide an avatar builder where you will pass the file path of the image. as far as i can understand your problem this solution fit's perfect as per your requirement otherwise you can go for the one i mentioned above.

https://github.com/flyerhq/flutter_chat_ui/blob/802a41f1b52f38808e8bd9e7d83c40a180c3ea5b/lib/src/widgets/chat.dart#L34

Thanks for the suggestion, I ended using a AvatarBuilder. To keep the same style I had to copy-paste the code of UserAvatar and replace NetworkImage with my custom Image provider function.


class CustomFlyerUserAvatar extends StatelessWidget {
  /// Creates user avatar
  const CustomFlyerUserAvatar({
    super.key,
    required this.userId,
    this.onAvatarTap,
  });

  /// Author to show image and name initials from
  final String userId;

  /// Called when user taps on an avatar
  final void Function(String)? onAvatarTap;

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsetsDirectional.only(end: 8),
      child: GestureDetector(
        onTap: () => onAvatarTap?.call(userId),
        child: CircleAvatar(
          backgroundColor: Colors.transparent,
          backgroundImage: User.getUserImageProvider(userId),
          radius: 16,
        ),
      ),
    );
  }
}

It does the trick, however it means I'll have to manually keep my copy-paste of UserAvatar up-to-date with each update of flyer-chat-ui.

@demchenkoalex, unfortunately this is still too restrictive. What if the image comes from a Uint8List? Ideally, I'll be able to provide the image to display, without any induce logic within the framework.

If that's not possible because of types, no worries. The trick of copy-pasting UserAvatar and using its alternative version in AvatarBuilder will be good enough for now.

Let me know if I can be of any help on this.

Thank you very much for your amazing package. I can't count the number of hours it saves me! 🤩

SilverLinings89 commented 2 years ago

Hi,

in our project we are at a similar point: For other reasons, we already have the user avatars in local memory and downloading them happens with signed URL pattern so it's tedious. For that reason it would be nice for us to be able to just pass a local path to the image path argument and have it use the local path. Alternatively, it would also work for us to have a global setting about how that images should be constructed, i.e. if Image or NetworkImage should be used.

Greetings!

provokateurin commented 2 years ago

I had a similar problem where I have to request the avatar using a special API client. What I did was override the avatarBuilder with a custom widget. A string is passed to the function which is set by the imageUrl in the User which I used it to identify the user and request the corresponding avatar.

Yogesh-Dubey-Ayesavi commented 2 years ago

Yeah, i think providing customavatarbuilder would be fine for now, in most off the cases we make use of network images so i dont think so changing from root would be a nice idea. What we can do as of now is making use of customAvatarBuilder.