Skip to content
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

feat: ✨add default avatar profile image, cached network image for network images and image type to support profile image as asset, network or base64 data #172

Merged
merged 2 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## [2.0.0] (Unreleased)

* **Feat**: [156](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/156) Added
default avatar, error builder for asset, network and base64 profile image and
cached_network_image for network images.
* **Breaking**: [173](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/173) Added
callback to sort message in chat.
* **Fix**: [181](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/181) Removed
Expand Down
51 changes: 49 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,54 @@ ChatView(
)
```

30. Added a `replyMessageBuilder` to customize view for the reply.
30. Add default avatar for profile image `defaultAvatarImage`,
error builder for asset and network profile image `assetImageErrorBuilder` `networkImageErrorBuilder`,
Enum `ImageType` to define image as asset, network or base64 data.
```dart
ChatView(
...
appBar: ChatViewAppBar(
defaultAvatarImage: defaultAvatar,
imageType: ImageType.network,
networkImageErrorBuilder: (context, url, error) {
return Center(
child: Text('Error $error'),
);
},
assetImageErrorBuilder: (context, error, stackTrace) {
return Center(
child: Text('Error $error'),
);
},
),
...
),
```


31. Added a `customMessageReplyViewBuilder` to customize reply message view for custom type message.

```dart
ChatView(
...
messageConfig: MessageConfiguration(
customMessageBuilder: (ReplyMessage state) {
return Text(
state.message,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 12,
color: Colors.black,
),
);
},
),
...
)
```

32. Added a `replyMessageBuilder` to customize view for the reply.

```dart
ChatView(
Expand Down Expand Up @@ -766,7 +813,7 @@ ChatView(
```


30. Added callback `messageSorter` to sort message in `ChatBackgroundConfiguration`.
33. Added callback `messageSorter` to sort message in `ChatBackgroundConfiguration`.
```dart

ChatView(
Expand Down
15 changes: 11 additions & 4 deletions lib/src/extensions/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/
import 'package:chatview/chatview.dart';
import 'package:chatview/src/widgets/chat_view_inherited_widget.dart';
import 'package:chatview/src/widgets/profile_image_widget.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../utils/constants/constants.dart';
Expand Down Expand Up @@ -74,12 +75,18 @@ extension ValidateString on String {
double? profileCircleRadius,
EdgeInsets? profileCirclePadding,
}) {
final user = getChatUser(this);
return Padding(
padding: profileCirclePadding ?? const EdgeInsets.only(left: 4),
child: CircleAvatar(
radius: profileCircleRadius ?? 8,
backgroundImage:
NetworkImage(getChatUser(this)?.profilePhoto ?? profileImage),
child: ProfileImageWidget(
imageUrl: user?.profilePhoto,
imageType: user?.imageType,
defaultAvatarImage: user?.defaultAvatarImage ?? profileImage,
circleRadius: profileCircleRadius ?? 8,
assetImageErrorBuilder: user?.assetImageErrorBuilder,
networkImageErrorBuilder: user?.networkImageErrorBuilder,
networkImageProgressIndicatorBuilder:
user?.networkImageProgressIndicatorBuilder,
),
);
}
Expand Down
37 changes: 30 additions & 7 deletions lib/src/models/chat_user.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,63 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

import '../utils/constants/constants.dart';
import '../values/enumeration.dart';
import '../values/typedefs.dart';

class ChatUser {
/// Provides id of user.
final String id;

/// Provides name of user.
final String name;

/// Provides profile picture URL of user.
/// Provides profile picture as network URL or asset of user.
/// Or
/// Provides profile picture's data in base64 string.
/// This will be determined by [isProfilePhotoInBase64].
final String? profilePhoto;

/// To check whether profile photo is in base64 or network url.
final bool? isProfilePhotoInBase64;
/// Field to set default image if network url for profile image not provided
final String defaultAvatarImage;

/// Field to define image type [network, asset or base64]
final ImageType imageType;

/// Error builder to build error widget for asset image
final AssetImageErrorBuilder? assetImageErrorBuilder;

/// Error builder to build error widget for network image
final NetworkImageErrorBuilder? networkImageErrorBuilder;

/// Progress indicator builder for network image
final NetworkImageProgressIndicatorBuilder?
networkImageProgressIndicatorBuilder;

ChatUser({
required this.id,
required this.name,
this.profilePhoto,
this.isProfilePhotoInBase64,
this.defaultAvatarImage = profileImage,
this.imageType = ImageType.network,
this.assetImageErrorBuilder,
this.networkImageErrorBuilder,
this.networkImageProgressIndicatorBuilder,
});

factory ChatUser.fromJson(Map<String, dynamic> json) => ChatUser(
id: json["id"],
name: json["name"],
profilePhoto: json["profilePhoto"],
isProfilePhotoInBase64: json["isProfilePhotoInBase64"],
imageType: json["imageType"],
aditya-css marked this conversation as resolved.
Show resolved Hide resolved
defaultAvatarImage: json["defaultAvatarImage"],
);

Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'profilePhoto': profilePhoto,
'isProfilePhotoInBase64': isProfilePhotoInBase64,
'imageType': imageType,
'defaultAvatarImage': defaultAvatarImage,
};
}
27 changes: 22 additions & 5 deletions lib/src/models/profile_circle.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@
import 'package:flutter/material.dart';

import '../../chatview.dart';
import '../utils/constants/constants.dart';

class ProfileCircleConfiguration {
/// Used to give padding to profile circle.
final EdgeInsetsGeometry? padding;

/// Provides image url of user.
/// Provides image url as network or asset of user.
/// Or
/// Provides image data of user in base64
/// This will be determined by [isProfilePhotoInBase64].
final String? profileImageUrl;

/// Used for give bottom padding to profile circle
Expand All @@ -45,8 +45,21 @@ class ProfileCircleConfiguration {
/// Provides callback when user long press on profile circle.
final void Function(ChatUser)? onAvatarLongPress;

/// To check whether profile photo is in base64 or network url.
final bool? isProfilePhotoInBase64;
/// Field to define image type [network, asset or base64]
final ImageType imageType;

/// Field to set default avatar image if profile image link not provided
final String defaultAvatarImage;

/// Error builder to build error widget for asset image
final AssetImageErrorBuilder? assetImageErrorBuilder;

/// Error builder to build error widget for network image
final NetworkImageErrorBuilder? networkImageErrorBuilder;

/// Progress indicator builder for network image
final NetworkImageProgressIndicatorBuilder?
networkImageProgressIndicatorBuilder;

const ProfileCircleConfiguration({
this.onAvatarTap,
Expand All @@ -55,6 +68,10 @@ class ProfileCircleConfiguration {
this.bottomPadding,
this.circleRadius,
this.onAvatarLongPress,
this.isProfilePhotoInBase64,
this.imageType = ImageType.network,
this.defaultAvatarImage = profileImage,
this.networkImageErrorBuilder,
this.assetImageErrorBuilder,
this.networkImageProgressIndicatorBuilder,
});
}
12 changes: 12 additions & 0 deletions lib/src/values/enumeration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ enum ChatViewState { hasMessages, noData, loading, error }

enum ShowReceiptsIn { all, lastMessage }

enum ImageType {
asset,
network,
base64;

bool get isNetwork => this == ImageType.network;

bool get isAsset => this == ImageType.asset;

bool get isBase64 => this == ImageType.base64;
}

extension ChatViewStateExtension on ChatViewState {
bool get hasMessages => this == ChatViewState.hasMessages;

Expand Down
16 changes: 16 additions & 0 deletions lib/src/values/typedefs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import 'package:cached_network_image/cached_network_image.dart';
import 'package:chatview/chatview.dart';
import 'package:flutter/material.dart';

Expand Down Expand Up @@ -67,3 +68,18 @@ typedef CustomViewForReplyMessage = Widget Function(
ReplyMessage state,
);
typedef GetMessageSeparator = (Map<int, DateTime>, DateTime);
typedef AssetImageErrorBuilder = Widget Function(
BuildContext context,
Object error,
StackTrace? stackTrace,
);
typedef NetworkImageErrorBuilder = Widget Function(
BuildContext context,
String url,
Object error,
);
typedef NetworkImageProgressIndicatorBuilder = Widget Function(
BuildContext context,
String url,
DownloadProgress progress,
);
16 changes: 14 additions & 2 deletions lib/src/widgets/chat_bubble_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,13 @@ class _ChatBubbleWidgetState extends State<ChatBubbleWidget> {
: profileCircleConfig?.bottomPadding ?? 2,
profileCirclePadding: profileCircleConfig?.padding,
imageUrl: messagedUser?.profilePhoto,
isProfilePhotoInBase64: messagedUser?.isProfilePhotoInBase64,
imageType: messagedUser?.imageType,
defaultAvatarImage:
messagedUser?.defaultAvatarImage ?? profileImage,
networkImageProgressIndicatorBuilder:
messagedUser?.networkImageProgressIndicatorBuilder,
assetImageErrorBuilder: messagedUser?.assetImageErrorBuilder,
networkImageErrorBuilder: messagedUser?.networkImageErrorBuilder,
circleRadius: profileCircleConfig?.circleRadius,
onTap: () => _onAvatarTap(messagedUser),
onLongPress: () => _onAvatarLongPress(messagedUser),
Expand Down Expand Up @@ -232,7 +238,13 @@ class _ChatBubbleWidgetState extends State<ChatBubbleWidget> {
: profileCircleConfig?.bottomPadding ?? 2,
profileCirclePadding: profileCircleConfig?.padding,
imageUrl: currentUser?.profilePhoto,
isProfilePhotoInBase64: currentUser?.isProfilePhotoInBase64,
imageType: currentUser?.imageType,
defaultAvatarImage:
currentUser?.defaultAvatarImage ?? profileImage,
networkImageProgressIndicatorBuilder:
currentUser?.networkImageProgressIndicatorBuilder,
networkImageErrorBuilder: currentUser?.networkImageErrorBuilder,
assetImageErrorBuilder: currentUser?.assetImageErrorBuilder,
circleRadius: profileCircleConfig?.circleRadius,
onTap: () => _onAvatarTap(messagedUser),
onLongPress: () => _onAvatarLongPress(messagedUser),
Expand Down
6 changes: 0 additions & 6 deletions lib/src/widgets/chat_groupedlist_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,6 @@ class _ChatGroupedListWidgetState extends State<ChatGroupedListWidget>
typeIndicatorConfig: widget.typeIndicatorConfig,
chatBubbleConfig: chatBubbleConfig?.inComingChatBubbleConfig,
showIndicator: widget.showTypingIndicator,
profilePic: profileCircleConfig?.profileImageUrl,
isProfilePhotoInBase64:
profileCircleConfig?.isProfilePhotoInBase64,
)
: ValueListenableBuilder(
valueListenable: ChatViewInheritedWidget.of(context)!
Expand All @@ -209,9 +206,6 @@ class _ChatGroupedListWidgetState extends State<ChatGroupedListWidget>
chatBubbleConfig:
chatBubbleConfig?.inComingChatBubbleConfig,
showIndicator: value,
profilePic: profileCircleConfig?.profileImageUrl,
isProfilePhotoInBase64:
profileCircleConfig?.isProfilePhotoInBase64,
)),
SizedBox(
height: (MediaQuery.of(context).size.width *
Expand Down
1 change: 1 addition & 0 deletions lib/src/widgets/chat_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ class _ChatViewState extends State<ChatView>
chatController: chatController,
featureActiveConfig: featureActiveConfig,
currentUser: widget.currentUser,
profileCircleConfiguration: widget.profileCircleConfig,
child: Container(
height:
chatBackgroundConfig.height ?? MediaQuery.of(context).size.height,
Expand Down
35 changes: 32 additions & 3 deletions lib/src/widgets/chat_view_appbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import 'package:flutter/foundation.dart' show kIsWeb;

import 'package:flutter/material.dart';

import '../values/typedefs.dart';
import '../../chatview.dart';
import '../utils/constants/constants.dart';
import 'profile_image_widget.dart';

class ChatViewAppBar extends StatelessWidget {
const ChatViewAppBar({
Expand All @@ -42,6 +44,11 @@ class ChatViewAppBar extends StatelessWidget {
this.padding,
this.leading,
this.showLeading = true,
this.defaultAvatarImage = profileImage,
this.assetImageErrorBuilder,
this.networkImageErrorBuilder,
this.imageType = ImageType.network,
this.networkImageProgressIndicatorBuilder,
}) : super(key: key);

/// Allow user to change colour of appbar.
Expand Down Expand Up @@ -83,6 +90,22 @@ class ChatViewAppBar extends StatelessWidget {
/// Allow user to turn on/off leading icon.
final bool showLeading;

/// Field to set default image if network url for profile image not provided
final String defaultAvatarImage;

/// Error builder to build error widget for asset image
final AssetImageErrorBuilder? assetImageErrorBuilder;

/// Error builder to build error widget for network image
final NetworkImageErrorBuilder? networkImageErrorBuilder;

/// Field to define image type [network, asset or base64]
final ImageType imageType;

/// Progress indicator builder for network image
final NetworkImageProgressIndicatorBuilder?
networkImageProgressIndicatorBuilder;

@override
Widget build(BuildContext context) {
return Material(
Expand Down Expand Up @@ -113,8 +136,14 @@ class ChatViewAppBar extends StatelessWidget {
if (profilePicture != null)
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: CircleAvatar(
backgroundImage: NetworkImage(profilePicture!)),
child: ProfileImageWidget(
imageUrl: profilePicture,
defaultAvatarImage: defaultAvatarImage,
assetImageErrorBuilder: assetImageErrorBuilder,
networkImageErrorBuilder: networkImageErrorBuilder,
imageType: imageType,
networkImageProgressIndicatorBuilder: networkImageProgressIndicatorBuilder,
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
Expand Down
Loading