From 1939cc1bc8ef1f225e68cb69879f23b605452782 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Tue, 20 Jul 2021 13:46:53 +0530 Subject: [PATCH] feat: Added gradient avatar --- .../lib/src/gradient_avatar.dart | 199 ++++++++++++++++++ .../lib/src/stream_chat_theme.dart | 8 +- 2 files changed, 203 insertions(+), 4 deletions(-) create mode 100644 packages/stream_chat_flutter/lib/src/gradient_avatar.dart diff --git a/packages/stream_chat_flutter/lib/src/gradient_avatar.dart b/packages/stream_chat_flutter/lib/src/gradient_avatar.dart new file mode 100644 index 00000000..afc02fb6 --- /dev/null +++ b/packages/stream_chat_flutter/lib/src/gradient_avatar.dart @@ -0,0 +1,199 @@ +import 'dart:math'; +import 'dart:ui'; +import 'dart:ui' as ui; + +import 'package:flutter/material.dart'; + +class GradientAvatar extends StatefulWidget { + final String name; + final String userId; + + const GradientAvatar({ + Key? key, + required this.name, + required this.userId, + }) : super(key: key); + + @override + _GradientAvatarState createState() => _GradientAvatarState(); +} + +class _GradientAvatarState extends State { + @override + Widget build(BuildContext context) { + return Center( + child: RepaintBoundary( + child: Container( + width: 100.0, + height: 100.0, + child: Stack( + alignment: Alignment.center, + children: [ + CustomPaint( + painter: DemoPainter(widget.userId), + child: SizedBox.expand(), + ), + FittedBox( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: Opacity( + opacity: 0.8, + child: Text( + getShortenedName(widget.name), + style: TextStyle( + color: Colors.white, + fontSize: 112.0, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ), + ], + ), + ), + ), + ); + } + + String getShortenedName(String name) { + List parts = name.split(' ')..removeWhere((e) => e == ''); + + if (parts.length > 2) { + parts = parts.take(2).toList(); + } + + String result = ''; + + for (int i = 0; i < parts.length; i++) { + result = result + parts[i][0]; + } + + return result; + } +} + +class DemoPainter extends CustomPainter { + static const int rowCount = 5; + static const int columnCount = 5; + + String userId; + + DemoPainter(this.userId); + + @override + void paint(Canvas canvas, Size size) { + var rowUnit = size.width / columnCount; + var columnUnit = size.height / rowCount; + var rand = Random(userId.length); + + List squares = []; + Set points = {}; + List gradient = colorGradients[rand.nextInt(colorGradients.length)]; + + for (int i = 0; i < rowCount; i++) { + for (int j = 0; j < columnCount; j++) { + var off1 = Offset(rowUnit * j, columnUnit * i); + var off2 = Offset(rowUnit * (j + 1), columnUnit * i); + var off3 = Offset(rowUnit * (j + 1), columnUnit * (i + 1)); + var off4 = Offset(rowUnit * j, columnUnit * (i + 1)); + + points.addAll([off1, off2, off3, off4]); + + var p1 = points.toList().indexOf(off1); + var p2 = points.toList().indexOf(off2); + var p3 = points.toList().indexOf(off3); + var p4 = points.toList().indexOf(off4); + + squares.add( + Offset4(p1, p2, p3, p4, i, j, rowCount, columnCount, gradient)); + } + } + + var list = transformPoints(points, size); + squares.forEach((e) => e.draw(canvas, list)); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) { + return false; + } + + List transformPoints(Set points, Size size) { + List transformedList = []; + var orgList = points.toList(); + var rand = Random(userId.length); + + for (int i = 0; i < points.length; i++) { + var orgDx = orgList[i].dx; + var orgDy = orgList[i].dy; + + if (orgDx == 0 || + orgDy == 0 || + orgDx == size.width || + orgDy == size.height) { + transformedList.add(Offset(orgDx, orgDy)); + continue; + } + + int sign1 = rand.nextInt(2) == 1 ? 1 : -1; + int sign2 = rand.nextInt(2) == 1 ? 1 : -1; + + double dx = 0.6 * sign1 * rand.nextInt(size.width ~/ columnCount); + double dy = 0.6 * sign2 * rand.nextInt(size.height ~/ rowCount); + + transformedList.add(Offset(orgDx + dx, orgDy + dy)); + } + + return transformedList; + } +} + +class Offset4 { + int p1; + int p2; + int p3; + int p4; + int row; + int column; + int rowSize; + int colSize; + List gradient; + + Offset4(this.p1, this.p2, this.p3, this.p4, this.row, this.column, + this.rowSize, this.colSize, this.gradient); + + void draw(Canvas canvas, List points) { + Paint paint = Paint() + ..color = Color.fromARGB(255, Random().nextInt(255), + Random().nextInt(255), Random().nextInt(255)) + ..shader = ui.Gradient.linear( + points[p1], + points[p3], + gradient, + ); + + final backgroundPath = Path() + ..moveTo(points[p1].dx, points[p1].dy) + ..lineTo(points[p2].dx, points[p2].dy) + ..lineTo(points[p3].dx, points[p3].dy) + ..lineTo(points[p4].dx, points[p4].dy) + ..lineTo(points[p1].dx, points[p1].dy) + ..close(); + + canvas.drawPath(backgroundPath, paint); + } +} + +const colorGradients = [ + [Color(0xffffafbd), Color(0xffffc3a0)], + [Color(0xff2193b0), Color(0xff6dd5ed)], + [Color(0xffcc2b5e), Color(0xff753a88)], + [Color(0xffee9ca7), Color(0xffffdde1)], + [Color(0xff42275a), Color(0xff734b6d)], + [Color(0xffde6262), Color(0xffffb88c)], + [Color(0xff56ab2f), Color(0xffa8e063)], + [Color(0xff614385), Color(0xff516395)], + [Color(0xffeacda3), Color(0xffd6ae7b)], + [Color(0xff02aab0), Color(0xff00cdac)], +]; diff --git a/packages/stream_chat_flutter/lib/src/stream_chat_theme.dart b/packages/stream_chat_flutter/lib/src/stream_chat_theme.dart index c62e92ec..74976e07 100644 --- a/packages/stream_chat_flutter/lib/src/stream_chat_theme.dart +++ b/packages/stream_chat_flutter/lib/src/stream_chat_theme.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/src/channel_header.dart'; import 'package:stream_chat_flutter/src/channel_preview.dart'; import 'package:stream_chat_flutter/src/extension.dart'; +import 'package:stream_chat_flutter/src/gradient_avatar.dart'; import 'package:stream_chat_flutter/src/message_input.dart'; import 'package:stream_chat_flutter/src/reaction_icon.dart'; import 'package:stream_chat_flutter/src/utils.dart'; @@ -270,10 +271,9 @@ class StreamChatThemeData { colorTheme: colorTheme, primaryIconTheme: iconTheme, defaultUserImage: (context, user) => Center( - child: CachedNetworkImage( - filterQuality: FilterQuality.high, - imageUrl: getRandomPicUrl(user), - fit: BoxFit.cover, + child: GradientAvatar( + name: user.name, + userId: user.id, ), ), channelPreviewTheme: channelPreviewTheme,