feat: Display presences in the app
This commit is contained in:
parent
a3db754b85
commit
7930150cb4
12 changed files with 187 additions and 33 deletions
|
|
@ -4,6 +4,7 @@ import 'package:matrix/matrix.dart';
|
|||
|
||||
import 'package:fluffychat/utils/string_color.dart';
|
||||
import 'package:fluffychat/widgets/mxc_image.dart';
|
||||
import 'package:fluffychat/widgets/presence_builder.dart';
|
||||
|
||||
class Avatar extends StatelessWidget {
|
||||
final Uri? mxContent;
|
||||
|
|
@ -13,6 +14,8 @@ class Avatar extends StatelessWidget {
|
|||
static const double defaultSize = 44;
|
||||
final Client? client;
|
||||
final double fontSize;
|
||||
final String? presenceUserId;
|
||||
final Color? presenceBackgroundColor;
|
||||
|
||||
const Avatar({
|
||||
this.mxContent,
|
||||
|
|
@ -21,6 +24,8 @@ class Avatar extends StatelessWidget {
|
|||
this.onTap,
|
||||
this.client,
|
||||
this.fontSize = 18,
|
||||
this.presenceUserId,
|
||||
this.presenceBackgroundColor,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
|
@ -48,26 +53,64 @@ class Avatar extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
final borderRadius = BorderRadius.circular(size / 2);
|
||||
final container = ClipRRect(
|
||||
borderRadius: borderRadius,
|
||||
child: Container(
|
||||
width: size,
|
||||
height: size,
|
||||
color: noPic
|
||||
? name?.lightColorAvatar
|
||||
: Theme.of(context).secondaryHeaderColor,
|
||||
child: noPic
|
||||
? textWidget
|
||||
: MxcImage(
|
||||
key: Key(mxContent.toString()),
|
||||
uri: mxContent,
|
||||
fit: BoxFit.cover,
|
||||
width: size,
|
||||
height: size,
|
||||
placeholder: (_) => textWidget,
|
||||
cacheKey: mxContent.toString(),
|
||||
final presenceUserId = this.presenceUserId;
|
||||
final color =
|
||||
noPic ? name?.lightColorAvatar : Theme.of(context).secondaryHeaderColor;
|
||||
final container = Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: borderRadius,
|
||||
child: Container(
|
||||
width: size,
|
||||
height: size,
|
||||
color: color,
|
||||
child: noPic
|
||||
? textWidget
|
||||
: MxcImage(
|
||||
key: Key(mxContent.toString()),
|
||||
uri: mxContent,
|
||||
fit: BoxFit.cover,
|
||||
width: size,
|
||||
height: size,
|
||||
placeholder: (_) => textWidget,
|
||||
cacheKey: mxContent.toString(),
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceBuilder(
|
||||
userId: presenceUserId,
|
||||
builder: (context, presence) {
|
||||
if (presence == null) return const SizedBox.shrink();
|
||||
final dotColor = presence.presence.isOnline
|
||||
? Colors.green
|
||||
: presence.presence.isUnavailable
|
||||
? Colors.orange
|
||||
: Colors.red;
|
||||
return Positioned(
|
||||
bottom: -4,
|
||||
right: -4,
|
||||
child: Container(
|
||||
width: 16,
|
||||
height: 16,
|
||||
decoration: BoxDecoration(
|
||||
color: presenceBackgroundColor ??
|
||||
Theme.of(context).colorScheme.background,
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
width: 8,
|
||||
height: 8,
|
||||
decoration: BoxDecoration(
|
||||
color: dotColor,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
if (onTap == null) return container;
|
||||
return InkWell(
|
||||
|
|
|
|||
34
lib/widgets/presence_builder.dart
Normal file
34
lib/widgets/presence_builder.dart
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class PresenceBuilder extends StatelessWidget {
|
||||
final Widget Function(BuildContext context, CachedPresence? presence) builder;
|
||||
final String? userId;
|
||||
final Client? client;
|
||||
|
||||
const PresenceBuilder({
|
||||
required this.builder,
|
||||
this.userId,
|
||||
this.client,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final userId = this.userId;
|
||||
if (userId == null) return builder(context, null);
|
||||
|
||||
final client = this.client ?? Matrix.of(context).client;
|
||||
return StreamBuilder(
|
||||
stream: client.onPresenceChanged.stream
|
||||
.where((cachedPresence) => cachedPresence.userid == userId),
|
||||
builder: (context, snapshot) => builder(
|
||||
context,
|
||||
snapshot.data ?? client.presences[userId],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue