Skip to content
Open
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
13 changes: 8 additions & 5 deletions lib/app/animations/balloon_classes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class BalloonController implements Listenable {
final Random random = Random();
Size windowSize;

late Ticker ticker;
Ticker? ticker;

bool isPlaying = false;
bool requestedToStop = false;
Expand All @@ -28,6 +28,7 @@ class BalloonController implements Listenable {
isPlaying = true;
autoLaunchDuration = const Duration(milliseconds: 100);
lastAutoLaunch = Duration.zero;
ticker?.dispose();
ticker = vsync.createTicker(update)..start();
}

Expand All @@ -53,7 +54,8 @@ class BalloonController implements Listenable {

void dispose() {
listeners.clear();
ticker.dispose();
ticker?.dispose();
ticker = null;
}

void update(Duration elapsedDuration) {
Expand Down Expand Up @@ -82,8 +84,9 @@ class BalloonController implements Listenable {
return element.position.y < -100 || element.position.x < -100;
});
if (balloons.isEmpty && requestedToStop) {
ticker.stop();
ticker.dispose();
ticker?.stop();
ticker?.dispose();
ticker = null;
isPlaying = false;
requestedToStop = false;
stopFunc?.call();
Expand Down Expand Up @@ -132,4 +135,4 @@ const List<MaterialColor> primaries = <MaterialColor>[
Colors.lightGreen,
Colors.orange,
Colors.yellow,
];
];
11 changes: 7 additions & 4 deletions lib/app/animations/celebration_class.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class CelebrationController extends FireworkController {
isPlaying = true;
autoLaunchDuration = const Duration(milliseconds: 100);
lastAutoLaunch = Duration.zero;
ticker?.dispose();
ticker = vsync.createTicker(update)..start();
}

Expand Down Expand Up @@ -41,7 +42,8 @@ class CelebrationController extends FireworkController {
@override
void dispose() {
listeners.clear();
ticker.dispose();
ticker?.dispose();
ticker = null;
}

@override
Expand All @@ -63,8 +65,9 @@ class CelebrationController extends FireworkController {

particles.removeWhere((element) => element.alpha <= 0);
if (particles.isEmpty && requestedToStop) {
ticker.stop();
ticker.dispose();
ticker?.stop();
ticker?.dispose();
ticker = null;
isPlaying = false;
requestedToStop = false;
hasCreatedParticles = false;
Expand Down Expand Up @@ -94,4 +97,4 @@ class CelebrationController extends FireworkController {
));
}
}
}
}
13 changes: 8 additions & 5 deletions lib/app/animations/fireworks_classes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class FireworkController implements Listenable {
Size windowSize;
double globalHue = 42;

late Ticker ticker;
Ticker? ticker;

bool hasCreatedParticles = false;
bool isPlaying = false;
Expand All @@ -41,6 +41,7 @@ class FireworkController implements Listenable {
isPlaying = true;
autoLaunchDuration = const Duration(milliseconds: 100);
lastAutoLaunch = Duration.zero;
ticker?.dispose();
ticker = vsync.createTicker(update)..start();
}

Expand All @@ -66,7 +67,8 @@ class FireworkController implements Listenable {

void dispose() {
listeners.clear();
ticker.dispose();
ticker?.dispose();
ticker = null;
}

void update(Duration elapsedDuration) {
Expand Down Expand Up @@ -113,8 +115,9 @@ class FireworkController implements Listenable {
});
particles.removeWhere((element) => element.alpha <= 0);
if (particles.isEmpty && requestedToStop && hasCreatedParticles) {
ticker.stop();
ticker.dispose();
ticker?.stop();
ticker?.dispose();
ticker = null;
isPlaying = false;
requestedToStop = false;
hasCreatedParticles = false;
Expand Down Expand Up @@ -283,4 +286,4 @@ class FireworkRocket extends FireworkObjectWithTrail {
position += vp;
}
}
}
}
13 changes: 8 additions & 5 deletions lib/app/animations/laser_classes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class LaserController implements Listenable {
final Random random = Random();
Size windowSize;

late Ticker ticker;
Ticker? ticker;
late Point<double> position;
late double size;
double globalHue = 42;
Expand All @@ -34,6 +34,7 @@ class LaserController implements Listenable {
autoLaunchDuration = const Duration(milliseconds: 500);
lastAutoLaunch = Duration.zero;
position = Point((bubbleDimensions.left + bubbleDimensions.right) / 2, (bubbleDimensions.top + bubbleDimensions.bottom) / 2);
ticker?.dispose();
ticker = vsync.createTicker(update)..start();
}

Expand All @@ -58,7 +59,8 @@ class LaserController implements Listenable {

void dispose() {
listeners.clear();
ticker.dispose();
ticker?.dispose();
ticker = null;
}

void update(Duration elapsedDuration) {
Expand Down Expand Up @@ -103,8 +105,9 @@ class LaserController implements Listenable {
}

if (elapsedDuration.inSeconds > 5 && requestedToStop) {
ticker.stop();
ticker.dispose();
ticker?.stop();
ticker?.dispose();
ticker = null;
isPlaying = false;
requestedToStop = false;
laser = null;
Expand Down Expand Up @@ -199,4 +202,4 @@ class LaserBeam {
}
}

enum Direction {up, down}
enum Direction {up, down}
13 changes: 8 additions & 5 deletions lib/app/animations/love_classes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class LoveController implements Listenable {
final Random random = Random();
Size windowSize;

late Ticker ticker;
Ticker? ticker;
late Point<double> position;

bool isPlaying = false;
Expand All @@ -30,6 +30,7 @@ class LoveController implements Listenable {
autoLaunchDuration = const Duration(milliseconds: 100);
lastAutoLaunch = Duration.zero;
position = startPos;
ticker?.dispose();
ticker = vsync.createTicker(update)..start();
}

Expand All @@ -55,7 +56,8 @@ class LoveController implements Listenable {

void dispose() {
listeners.clear();
ticker.dispose();
ticker?.dispose();
ticker = null;
}

void update(Duration elapsedDuration) {
Expand All @@ -75,8 +77,9 @@ class LoveController implements Listenable {
heart!.update();

if (heart!.position.y < -200 && requestedToStop) {
ticker.stop();
ticker.dispose();
ticker?.stop();
ticker?.dispose();
ticker = null;
isPlaying = false;
requestedToStop = false;
heart = null;
Expand Down Expand Up @@ -128,4 +131,4 @@ class LoveObject {
velocity *= acceleration;
velocity.clamp(0.5, 2);
}
}
}
13 changes: 8 additions & 5 deletions lib/app/animations/spotlight_classes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class SpotlightController implements Listenable {
final Random random = Random();
Size windowSize;

late Ticker ticker;
Ticker? ticker;
late Point<double> position;
late double size;

Expand All @@ -32,6 +32,7 @@ class SpotlightController implements Listenable {
lastAutoLaunch = Duration.zero;
position = Point((bubbleDimensions.left + bubbleDimensions.right) / 2, (bubbleDimensions.top + bubbleDimensions.bottom) / 2);
size = max(bubbleDimensions.width, bubbleDimensions.height) + 50;
ticker?.dispose();
ticker = vsync.createTicker(update)..start();
}

Expand All @@ -57,7 +58,8 @@ class SpotlightController implements Listenable {

void dispose() {
listeners.clear();
ticker.dispose();
ticker?.dispose();
ticker = null;
}

void update(Duration elapsedDuration) {
Expand All @@ -76,8 +78,9 @@ class SpotlightController implements Listenable {
spotlight!.update(elapsedDuration);

if (spotlight!.stop < 0 && requestedToStop) {
ticker.stop();
ticker.dispose();
ticker?.stop();
ticker?.dispose();
ticker = null;
isPlaying = false;
requestedToStop = false;
spotlight = null;
Expand Down Expand Up @@ -116,4 +119,4 @@ class SpotlightObject {
stop = stop - 0.05;
}
}
}
}
16 changes: 15 additions & 1 deletion lib/app/components/avatars/contact_avatar_group_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ContactAvatarGroupWidget extends StatefulWidget {
}

class _ContactAvatarGroupWidgetState extends OptimizedState<ContactAvatarGroupWidget> {
late final List<Handle> participants = widget.chat?.participants ?? widget.participants ?? [];
late List<Handle> participants;
final Map materialGeneration = {
2: [24.5/40, 10.5/40, [Alignment.topRight, Alignment.bottomLeft]],
3: [21.5/40, 9/40, [Alignment.bottomRight, Alignment.bottomLeft, Alignment.topCenter]],
Expand All @@ -41,6 +41,20 @@ class _ContactAvatarGroupWidgetState extends OptimizedState<ContactAvatarGroupWi
@override
void initState() {
super.initState();
_syncParticipants();
}

@override
void didUpdateWidget(covariant ContactAvatarGroupWidget oldWidget) {
super.didUpdateWidget(oldWidget);
_syncParticipants();
}

void _syncParticipants() {
// Copy before sorting. Chat.participants is backed by the persisted
// relation, so sorting it in place can make participant order appear to
// change as a side effect of rendering.
participants = List<Handle>.from(widget.chat?.participants ?? widget.participants ?? []);
participants.sort((a, b) {
bool avatarA = a.contact?.avatar?.isNotEmpty ?? false;
bool avatarB = b.contact?.avatar?.isNotEmpty ?? false;
Expand Down
16 changes: 14 additions & 2 deletions lib/app/components/avatars/contact_avatar_widget.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:bluebubbles/helpers/helpers.dart';
import 'package:bluebubbles/app/wrappers/stateful_boilerplate.dart';
import 'package:bluebubbles/database/models.dart';
Expand Down Expand Up @@ -36,19 +38,29 @@ class ContactAvatarWidget extends StatefulWidget {

class _ContactAvatarWidgetState extends OptimizedState<ContactAvatarWidget> {
Contact? get contact => widget.contact ?? widget.handle?.contact;
String get keyPrefix => widget.handle?.address ?? randomString(8);
late final String _keyPrefix;
String get keyPrefix => _keyPrefix;
StreamSubscription? _avatarRefreshSubscription;

@override
void initState() {
super.initState();
eventDispatcher.stream.listen((event) {
_keyPrefix = widget.handle?.address ?? randomString(8);
_avatarRefreshSubscription = eventDispatcher.stream.listen((event) {
if (!mounted) return;
if (event.item1 != 'refresh-avatar') return;
if (event.item2[0] != widget.handle?.address) return;
widget.handle?.color = event.item2[1];
setState(() {});
});
}

@override
void dispose() {
_avatarRefreshSubscription?.cancel();
super.dispose();
}

void onAvatarTap() async {
if (!ss.settings.colorfulAvatars.value && !ss.settings.colorfulBubbles.value) return;

Expand Down
Loading