Skip to content

Commit 3124110

Browse files
committed
model: Cache stream-color swatch on Subscription object
As mentioned in a TODO, I'm not sure it makes sense to deal with package:flutter/painting.dart from within our lib/api/model/ code. We might end up factoring that out somewhere else. Next, we'll have our UnreadCountBadge widget optionally consume one of these swatches.
1 parent fcc1744 commit 3124110

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

lib/api/model/model.dart

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'package:flutter/foundation.dart';
2+
import 'package:flutter/painting.dart';
13
import 'package:json_annotation/json_annotation.dart';
24

35
import 'reaction.dart';
@@ -321,14 +323,25 @@ class Subscription {
321323
/// As an int that dart:ui's Color constructor will take:
322324
/// <https://api.flutter.dev/flutter/dart-ui/Color/Color.html>
323325
@JsonKey(readValue: _readColor)
324-
final int color;
325-
326+
final int color; // TODO(#135) Clear out _swatch cache on changes to this
326327
static Object? _readColor(Map json, String key) {
327328
final str = (json[key] as String);
328329
assert(RegExp(r'^#[0-9a-f]{6}$').hasMatch(str));
329330
return 0xff000000 | int.parse(str.substring(1), radix: 16);
330331
}
331332

333+
@JsonKey(includeToJson: false)
334+
StreamColorSwatch? _swatch;
335+
/// A [StreamColorSwatch] for the subscription, memoized.
336+
// TODO I'm not sure this is the right home for this; it seems like we might
337+
// instead have chosen to put it in more UI-centered code, like in a custom
338+
// material [ColorScheme] class or something. But it works for now.
339+
StreamColorSwatch colorSwatch() => _swatch ??= StreamColorSwatch(color);
340+
341+
@visibleForTesting
342+
@JsonKey(includeToJson: false)
343+
StreamColorSwatch? get debugCachedSwatchValue => _swatch;
344+
332345
Subscription({
333346
required this.streamId,
334347
required this.name,
@@ -359,6 +372,29 @@ class Subscription {
359372
Map<String, dynamic> toJson() => _$SubscriptionToJson(this);
360373
}
361374

375+
/// A [ColorSwatch] with colors related to a base stream color.
376+
///
377+
/// Use this in UI code for colors related to [Subscription.color],
378+
/// such as the background of an unread count badge.
379+
class StreamColorSwatch extends ColorSwatch<_StreamColorVariant> {
380+
StreamColorSwatch(int base) : super(base, _compute(base));
381+
382+
Color get base => this[_StreamColorVariant.base]!;
383+
384+
static Map<_StreamColorVariant, Color> _compute(int base) {
385+
final baseAsColor = Color(base);
386+
387+
return {
388+
_StreamColorVariant.base: baseAsColor,
389+
};
390+
}
391+
}
392+
393+
enum _StreamColorVariant {
394+
base,
395+
// TODO more, like the unread-count badge background color
396+
}
397+
362398
/// As in the get-messages response.
363399
///
364400
/// https://zulip.com/api/get-messages#response

test/api/model/model_checks.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1+
import 'dart:ui';
2+
13
import 'package:checks/checks.dart';
24
import 'package:zulip/api/model/model.dart';
35

6+
extension StreamColorSwatchChecks on Subject<StreamColorSwatch> {
7+
Subject<Color> get base => has((s) => s.base, 'base');
8+
}
9+
410
extension MessageChecks on Subject<Message> {
511
Subject<String> get content => has((e) => e.content, 'content');
612
Subject<bool> get isMeMessage => has((e) => e.isMeMessage, 'isMeMessage');

test/api/model/model_test.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:convert';
2+
import 'dart:ui';
23

34
import 'package:checks/checks.dart';
45
import 'package:test/scaffolding.dart';
@@ -77,6 +78,19 @@ void main() {
7778
check(subWithColor('#ffffff').color).equals(0xffffffff);
7879
check(subWithColor('#000000').color).equals(0xff000000);
7980
});
81+
82+
test('colorSwatch caching', () {
83+
final sub = eg.subscription(stream: eg.stream(), color: 0xffffffff);
84+
check(sub.debugCachedSwatchValue).isNull();
85+
sub.colorSwatch();
86+
check(sub.debugCachedSwatchValue).isNotNull().base.equals(const Color(0xffffffff));
87+
});
88+
89+
group('StreamColorSwatch', () {
90+
test('base', () {
91+
check(StreamColorSwatch(0xffffffff)).base.equals(const Color(0xffffffff));
92+
});
93+
});
8094
});
8195

8296
group('Message', () {

0 commit comments

Comments
 (0)