diff --git a/lib/api/model/model.dart b/lib/api/model/model.dart index 22b4697642..94f948aebc 100644 --- a/lib/api/model/model.dart +++ b/lib/api/model/model.dart @@ -421,7 +421,7 @@ class Subscription extends ZulipStream { // TODO I'm not sure this is the right home for this; it seems like we might // instead have chosen to put it in more UI-centered code, like in a custom // material [ColorScheme] class or something. But it works for now. - StreamColorSwatch colorSwatch() => _swatch ??= StreamColorSwatch(color); + StreamColorSwatch colorSwatch() => _swatch ??= StreamColorSwatch.light(color); @visibleForTesting @JsonKey(includeToJson: false) @@ -463,16 +463,11 @@ class Subscription extends ZulipStream { /// Use this in UI code for colors related to [Subscription.color], /// such as the background of an unread count badge. class StreamColorSwatch extends ColorSwatch { - StreamColorSwatch(int base) : this._(base, _compute(base)); + StreamColorSwatch.light(int base) : this._(base, _computeLight(base)); + StreamColorSwatch.dark(int base) : this._(base, _computeDark(base)); const StreamColorSwatch._(int base, this._swatch) : super(base, _swatch); - /// A [StreamColorSwatch], from a [Map<_StreamColorVariant, Color>] - /// written manually. - @visibleForTesting - const StreamColorSwatch.debugFromBaseAndSwatch(int base, swatch) - : this._(base, swatch); - final Map _swatch; /// The [Subscription.color] int that the swatch is based on. @@ -498,7 +493,7 @@ class StreamColorSwatch extends ColorSwatch { /// Use this in the message list, the "Inbox" view, and the "Streams" view. Color get barBackground => this[StreamColorVariant.barBackground]!; - static Map _compute(int base) { + static Map _computeLight(int base) { final baseAsColor = Color(base); final clamped20to75 = clampLchLightness(baseAsColor, 20, 75); @@ -517,7 +512,7 @@ class StreamColorSwatch extends ColorSwatch { .withOpacity(0.3), // Follows `.sidebar-row__icon` in Vlad's replit: - // + // // // TODO fix bug where our results differ from the replit's (see unit tests) StreamColorVariant.iconOnPlainBackground: clamped20to75, @@ -529,7 +524,7 @@ class StreamColorSwatch extends ColorSwatch { // TODO fix bug where our results differ from the replit's (see unit tests) StreamColorVariant.iconOnBarBackground: clamped20to75AsHsl - .withLightness(clamped20to75AsHsl.lightness - 0.12) + .withLightness(clampDouble(clamped20to75AsHsl.lightness - 0.12, 0.0, 1.0)) .toColor(), // Follows `.recepient` in Vlad's replit: @@ -547,6 +542,44 @@ class StreamColorSwatch extends ColorSwatch { }; } + static Map _computeDark(int base) { + final baseAsColor = Color(base); + + final clamped20to75 = clampLchLightness(baseAsColor, 20, 75); + + return { + // See comments in [_computeLight] about what these computations are based + // on, and how the resulting values are a little off sometimes. The + // comments mostly apply here too. + + StreamColorVariant.base: baseAsColor, + StreamColorVariant.unreadCountBadgeBackground: + clampLchLightness(baseAsColor, 30, 70) + .withOpacity(0.3), + StreamColorVariant.iconOnPlainBackground: clamped20to75, + + // Follows the web app (as of zulip/zulip@db03369ac); see + // get_stream_privacy_icon_color in web/src/stream_color.ts. + // + // `.recepeient__icon` in Vlad's replit gives something different so we + // don't use that: + // + // + // But that's OK because Vlad said "I feel like current dark theme contrast + // is fine", and when he said that, this had been the web app's icon color + // for 6+ months (since zulip/zulip@023584e04): + // https://chat.zulip.org/#narrow/stream/101-design/topic/UI.20redesign.3A.20recipient.20bar.20colors/near/1675786 + // + // TODO fix bug where our results are unexpected (see unit tests) + StreamColorVariant.iconOnBarBackground: clamped20to75, + + StreamColorVariant.barBackground: + LabColor.fromColor(const Color(0xff000000)) + .interpolate(LabColor.fromColor(clamped20to75), 0.38) + .toColor(), + }; + } + /// Copied from [ColorSwatch.lerp]. static StreamColorSwatch? lerp(StreamColorSwatch? a, StreamColorSwatch? b, double t) { if (identical(a, b)) { diff --git a/lib/widgets/unread_count_badge.dart b/lib/widgets/unread_count_badge.dart index 45df67e80d..412ab5541c 100644 --- a/lib/widgets/unread_count_badge.dart +++ b/lib/widgets/unread_count_badge.dart @@ -47,6 +47,16 @@ class UnreadCountBadge extends StatelessWidget { fontSize: 16, height: (18 / 16), fontFeatures: [FontFeature.enable('smcp')], // small caps + + // From the Figma: + // https://www.figma.com/file/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?type=design&node-id=171-12359&mode=design&t=JKrw76SGUF51nSJG-0 + // TODO or, when background is stream-colored, follow Vlad's replit? + // https://replit.com/@VladKorobov/zulip-sidebar#script.js + // which would mean: + // - in light mode use `Color.fromRGBO(0, 0, 0, 0.9)` + // - in dark mode use `Color.fromRGBO(255, 255, 255, 0.9)` + // The web app doesn't (yet?) use stream-colored unread markers + // so we can't take direction from there. color: Color(0xFF222222), ).merge(weightVariableTextStyle(context, wght: bold ? 600 : null)), diff --git a/test/api/model/model_test.dart b/test/api/model/model_test.dart index 06331a2d93..cf6e6ff918 100644 --- a/test/api/model/model_test.dart +++ b/test/api/model/model_test.dart @@ -128,208 +128,396 @@ void main() { }); group('StreamColorSwatch', () { - test('base', () { - check(StreamColorSwatch(0xffffffff)).base.equals(const Color(0xffffffff)); - }); + group('light', () { + test('base', () { + check(StreamColorSwatch.light(0xffffffff)).base.equals(const Color(0xffffffff)); + }); - test('unreadCountBadgeBackground', () { - void runCheck(int base, Color expected) { - check(StreamColorSwatch(base)).unreadCountBadgeBackground.equals(expected); - } + test('unreadCountBadgeBackground', () { + void runCheck(int base, Color expected) { + check(StreamColorSwatch.light(base)).unreadCountBadgeBackground.equals(expected); + } - // Check against everything in ZULIP_ASSIGNMENT_COLORS and EXTREME_COLORS - // in . - // On how to extract expected results from the replit, see: - // https://github.com/zulip/zulip-flutter/pull/371#discussion_r1393643523 - - // TODO Fix bug causing our implementation's results to differ from the - // replit's. Where they differ, see comment with what the replit gives. - - // ZULIP_ASSIGNMENT_COLORS - runCheck(0xff76ce90, const Color(0x4d65bd80)); - runCheck(0xfffae589, const Color(0x4dbdab53)); // 0x4dbdaa52 - runCheck(0xffa6c7e5, const Color(0x4d8eafcc)); // 0x4d8fb0cd - runCheck(0xffe79ab5, const Color(0x4de295b0)); // 0x4de194af - runCheck(0xffbfd56f, const Color(0x4d9eb551)); // 0x4d9eb450 - runCheck(0xfff4ae55, const Color(0x4de19d45)); // 0x4de09c44 - runCheck(0xffb0a5fd, const Color(0x4daba0f8)); // 0x4daca2f9 - runCheck(0xffaddfe5, const Color(0x4d83b4b9)); // 0x4d83b4ba - runCheck(0xfff5ce6e, const Color(0x4dcba749)); // 0x4dcaa648 - runCheck(0xffc2726a, const Color(0x4dc2726a)); - runCheck(0xff94c849, const Color(0x4d86ba3c)); // 0x4d86ba3b - runCheck(0xffbd86e5, const Color(0x4dbd86e5)); - runCheck(0xffee7e4a, const Color(0x4dee7e4a)); - runCheck(0xffa6dcbf, const Color(0x4d82b69b)); // 0x4d82b79b - runCheck(0xff95a5fd, const Color(0x4d95a5fd)); - runCheck(0xff53a063, const Color(0x4d53a063)); - runCheck(0xff9987e1, const Color(0x4d9987e1)); - runCheck(0xffe4523d, const Color(0x4de4523d)); - runCheck(0xffc2c2c2, const Color(0x4dababab)); - runCheck(0xff4f8de4, const Color(0x4d4f8de4)); - runCheck(0xffc6a8ad, const Color(0x4dc2a4a9)); // 0x4dc1a4a9 - runCheck(0xffe7cc4d, const Color(0x4dc3ab2a)); // 0x4dc2aa28 - runCheck(0xffc8bebf, const Color(0x4db3a9aa)); - runCheck(0xffa47462, const Color(0x4da47462)); - - // EXTREME_COLORS - runCheck(0xFFFFFFFF, const Color(0x4dababab)); - runCheck(0xFF000000, const Color(0x4d474747)); - runCheck(0xFFD3D3D3, const Color(0x4dababab)); - runCheck(0xFFA9A9A9, const Color(0x4da9a9a9)); - runCheck(0xFF808080, const Color(0x4d808080)); - runCheck(0xFFFFFF00, const Color(0x4dacb300)); // 0x4dacb200 - runCheck(0xFFFF0000, const Color(0x4dff0000)); - runCheck(0xFF008000, const Color(0x4d008000)); - runCheck(0xFF0000FF, const Color(0x4d0000ff)); // 0x4d0902ff - runCheck(0xFFEE82EE, const Color(0x4dee82ee)); - runCheck(0xFFFFA500, const Color(0x4def9800)); // 0x4ded9600 - runCheck(0xFF800080, const Color(0x4d810181)); // 0x4d810281 - runCheck(0xFF00FFFF, const Color(0x4d00c2c3)); // 0x4d00c3c5 - runCheck(0xFFFF00FF, const Color(0x4dff00ff)); - runCheck(0xFF00FF00, const Color(0x4d00cb00)); - runCheck(0xFF800000, const Color(0x4d8d140c)); // 0x4d8b130b - runCheck(0xFF008080, const Color(0x4d008080)); - runCheck(0xFF000080, const Color(0x4d492bae)); // 0x4d4b2eb3 - runCheck(0xFFFFFFE0, const Color(0x4dadad90)); // 0x4dacad90 - runCheck(0xFFFF69B4, const Color(0x4dff69b4)); - }); + // Check against everything in ZULIP_ASSIGNMENT_COLORS and EXTREME_COLORS + // in . + // On how to extract expected results from the replit, see: + // https://github.com/zulip/zulip-flutter/pull/371#discussion_r1393643523 + + // TODO Fix bug causing our implementation's results to differ from the + // replit's. Where they differ, see comment with what the replit gives. + + // ZULIP_ASSIGNMENT_COLORS + runCheck(0xff76ce90, const Color(0x4d65bd80)); + runCheck(0xfffae589, const Color(0x4dbdab53)); // 0x4dbdaa52 + runCheck(0xffa6c7e5, const Color(0x4d8eafcc)); // 0x4d8fb0cd + runCheck(0xffe79ab5, const Color(0x4de295b0)); // 0x4de194af + runCheck(0xffbfd56f, const Color(0x4d9eb551)); // 0x4d9eb450 + runCheck(0xfff4ae55, const Color(0x4de19d45)); // 0x4de09c44 + runCheck(0xffb0a5fd, const Color(0x4daba0f8)); // 0x4daca2f9 + runCheck(0xffaddfe5, const Color(0x4d83b4b9)); // 0x4d83b4ba + runCheck(0xfff5ce6e, const Color(0x4dcba749)); // 0x4dcaa648 + runCheck(0xffc2726a, const Color(0x4dc2726a)); + runCheck(0xff94c849, const Color(0x4d86ba3c)); // 0x4d86ba3b + runCheck(0xffbd86e5, const Color(0x4dbd86e5)); + runCheck(0xffee7e4a, const Color(0x4dee7e4a)); + runCheck(0xffa6dcbf, const Color(0x4d82b69b)); // 0x4d82b79b + runCheck(0xff95a5fd, const Color(0x4d95a5fd)); + runCheck(0xff53a063, const Color(0x4d53a063)); + runCheck(0xff9987e1, const Color(0x4d9987e1)); + runCheck(0xffe4523d, const Color(0x4de4523d)); + runCheck(0xffc2c2c2, const Color(0x4dababab)); + runCheck(0xff4f8de4, const Color(0x4d4f8de4)); + runCheck(0xffc6a8ad, const Color(0x4dc2a4a9)); // 0x4dc1a4a9 + runCheck(0xffe7cc4d, const Color(0x4dc3ab2a)); // 0x4dc2aa28 + runCheck(0xffc8bebf, const Color(0x4db3a9aa)); + runCheck(0xffa47462, const Color(0x4da47462)); + + // EXTREME_COLORS + runCheck(0xFFFFFFFF, const Color(0x4dababab)); + runCheck(0xFF000000, const Color(0x4d474747)); + runCheck(0xFFD3D3D3, const Color(0x4dababab)); + runCheck(0xFFA9A9A9, const Color(0x4da9a9a9)); + runCheck(0xFF808080, const Color(0x4d808080)); + runCheck(0xFFFFFF00, const Color(0x4dacb300)); // 0x4dacb200 + runCheck(0xFFFF0000, const Color(0x4dff0000)); + runCheck(0xFF008000, const Color(0x4d008000)); + runCheck(0xFF0000FF, const Color(0x4d0000ff)); // 0x4d0902ff + runCheck(0xFFEE82EE, const Color(0x4dee82ee)); + runCheck(0xFFFFA500, const Color(0x4def9800)); // 0x4ded9600 + runCheck(0xFF800080, const Color(0x4d810181)); // 0x4d810281 + runCheck(0xFF00FFFF, const Color(0x4d00c2c3)); // 0x4d00c3c5 + runCheck(0xFFFF00FF, const Color(0x4dff00ff)); + runCheck(0xFF00FF00, const Color(0x4d00cb00)); + runCheck(0xFF800000, const Color(0x4d8d140c)); // 0x4d8b130b + runCheck(0xFF008080, const Color(0x4d008080)); + runCheck(0xFF000080, const Color(0x4d492bae)); // 0x4d4b2eb3 + runCheck(0xFFFFFFE0, const Color(0x4dadad90)); // 0x4dacad90 + runCheck(0xFFFF69B4, const Color(0x4dff69b4)); + }); - test('iconOnPlainBackground', () { - void runCheck(int base, Color expected) { - check(StreamColorSwatch(base)).iconOnPlainBackground.equals(expected); - } + test('iconOnPlainBackground', () { + void runCheck(int base, Color expected) { + check(StreamColorSwatch.light(base)).iconOnPlainBackground.equals(expected); + } - // Check against everything in ZULIP_ASSIGNMENT_COLORS - // in . - // (Skipping `streamColors` because there are 100+ of them.) - // On how to extract expected results from the replit, see: - // https://github.com/zulip/zulip-flutter/pull/381#discussion_r1399319296 - - // TODO Fix bug causing our implementation's results to differ from the - // replit's. Where they differ, see comment with what the replit gives. - - runCheck(0xff76ce90, const Color(0xff73cb8d)); - runCheck(0xfffae589, const Color(0xffccb95f)); // 0xffcbb85e - runCheck(0xffa6c7e5, const Color(0xff9cbcda)); // 0xff9cbddb - runCheck(0xffe79ab5, const Color(0xffe79ab5)); - runCheck(0xffbfd56f, const Color(0xffacc25d)); - runCheck(0xfff4ae55, const Color(0xfff0ab52)); // 0xffefa951 - runCheck(0xffb0a5fd, const Color(0xffb0a5fd)); - runCheck(0xffaddfe5, const Color(0xff90c1c7)); // 0xff90c2c8 - runCheck(0xfff5ce6e, const Color(0xffd9b456)); // 0xffd8b355 - runCheck(0xffc2726a, const Color(0xffc2726a)); - runCheck(0xff94c849, const Color(0xff94c849)); - runCheck(0xffbd86e5, const Color(0xffbd86e5)); - runCheck(0xffee7e4a, const Color(0xffee7e4a)); - runCheck(0xffa6dcbf, const Color(0xff8fc4a8)); - runCheck(0xff95a5fd, const Color(0xff95a5fd)); - runCheck(0xff53a063, const Color(0xff53a063)); - runCheck(0xff9987e1, const Color(0xff9987e1)); - runCheck(0xffe4523d, const Color(0xffe4523d)); - runCheck(0xffc2c2c2, const Color(0xffb9b9b9)); - runCheck(0xff4f8de4, const Color(0xff4f8de4)); - runCheck(0xffc6a8ad, const Color(0xffc6a8ad)); - runCheck(0xffe7cc4d, const Color(0xffd1b839)); // 0xffd0b737 - runCheck(0xffc8bebf, const Color(0xffc0b6b7)); - runCheck(0xffa47462, const Color(0xffa47462)); - runCheck(0xffacc25d, const Color(0xffacc25d)); - }); + // Check against everything in ZULIP_ASSIGNMENT_COLORS + // in . + // (Skipping `streamColors` because there are 100+ of them.) + // On how to extract expected results from the replit, see: + // https://github.com/zulip/zulip-flutter/pull/381#discussion_r1399319296 + + // TODO Fix bug causing our implementation's results to differ from the + // replit's. Where they differ, see comment with what the replit gives. + + runCheck(0xff76ce90, const Color(0xff73cb8d)); + runCheck(0xfffae589, const Color(0xffccb95f)); // 0xffcbb85e + runCheck(0xffa6c7e5, const Color(0xff9cbcda)); // 0xff9cbddb + runCheck(0xffe79ab5, const Color(0xffe79ab5)); + runCheck(0xffbfd56f, const Color(0xffacc25d)); + runCheck(0xfff4ae55, const Color(0xfff0ab52)); // 0xffefa951 + runCheck(0xffb0a5fd, const Color(0xffb0a5fd)); + runCheck(0xffaddfe5, const Color(0xff90c1c7)); // 0xff90c2c8 + runCheck(0xfff5ce6e, const Color(0xffd9b456)); // 0xffd8b355 + runCheck(0xffc2726a, const Color(0xffc2726a)); + runCheck(0xff94c849, const Color(0xff94c849)); + runCheck(0xffbd86e5, const Color(0xffbd86e5)); + runCheck(0xffee7e4a, const Color(0xffee7e4a)); + runCheck(0xffa6dcbf, const Color(0xff8fc4a8)); + runCheck(0xff95a5fd, const Color(0xff95a5fd)); + runCheck(0xff53a063, const Color(0xff53a063)); + runCheck(0xff9987e1, const Color(0xff9987e1)); + runCheck(0xffe4523d, const Color(0xffe4523d)); + runCheck(0xffc2c2c2, const Color(0xffb9b9b9)); + runCheck(0xff4f8de4, const Color(0xff4f8de4)); + runCheck(0xffc6a8ad, const Color(0xffc6a8ad)); + runCheck(0xffe7cc4d, const Color(0xffd1b839)); // 0xffd0b737 + runCheck(0xffc8bebf, const Color(0xffc0b6b7)); + runCheck(0xffa47462, const Color(0xffa47462)); + runCheck(0xffacc25d, const Color(0xffacc25d)); + }); - test('iconOnBarBackground', () { - void runCheck(int base, Color expected) { - check(StreamColorSwatch(base)).iconOnBarBackground.equals(expected); - } + test('iconOnBarBackground', () { + void runCheck(int base, Color expected) { + check(StreamColorSwatch.light(base)).iconOnBarBackground.equals(expected); + } - // Check against everything in ZULIP_ASSIGNMENT_COLORS - // in . - // (Skipping `streamColors` because there are 100+ of them.) - // On how to extract expected results from the replit, see: - // https://github.com/zulip/zulip-flutter/pull/381#discussion_r1399319296 - - // TODO Fix bug causing our implementation's results to differ from the - // replit's. Where they differ, see comment with what the replit gives. - - runCheck(0xff76ce90, const Color(0xff46ba69)); - runCheck(0xfffae589, const Color(0xffb49f39)); // 0xffb29d3a - runCheck(0xffa6c7e5, const Color(0xff6f9ec9)); // 0xff6f9fcb - runCheck(0xffe79ab5, const Color(0xffdb6991)); - runCheck(0xffbfd56f, const Color(0xff8ea43e)); - runCheck(0xfff4ae55, const Color(0xffeb901a)); // 0xffea8d19 - runCheck(0xffb0a5fd, const Color(0xff7b69fc)); - runCheck(0xffaddfe5, const Color(0xff67aab2)); // 0xff67acb4 - runCheck(0xfff5ce6e, const Color(0xffc59a2c)); // 0xffc3992d - runCheck(0xffc2726a, const Color(0xffa94e45)); - runCheck(0xff94c849, const Color(0xff74a331)); - runCheck(0xffbd86e5, const Color(0xffa254da)); - runCheck(0xffee7e4a, const Color(0xffe55716)); - runCheck(0xffa6dcbf, const Color(0xff67af89)); - runCheck(0xff95a5fd, const Color(0xff5972fc)); - runCheck(0xff53a063, const Color(0xff3e784a)); - runCheck(0xff9987e1, const Color(0xff6f56d5)); - runCheck(0xffe4523d, const Color(0xffc8311c)); - runCheck(0xffc2c2c2, const Color(0xff9a9a9a)); - runCheck(0xff4f8de4, const Color(0xff216cd5)); - runCheck(0xffc6a8ad, const Color(0xffae838a)); - runCheck(0xffe7cc4d, const Color(0xffa69127)); // 0xffa38f26 - runCheck(0xffc8bebf, const Color(0xffa49597)); - runCheck(0xffa47462, const Color(0xff7f584a)); - runCheck(0xffacc25d, const Color(0xff8ea43e)); - }); + // Check against everything in ZULIP_ASSIGNMENT_COLORS + // in . + // (Skipping `streamColors` because there are 100+ of them.) + // On how to extract expected results from the replit, see: + // https://github.com/zulip/zulip-flutter/pull/381#discussion_r1399319296 + + // TODO Fix bug causing our implementation's results to differ from the + // replit's. Where they differ, see comment with what the replit gives. + + runCheck(0xff76ce90, const Color(0xff46ba69)); + runCheck(0xfffae589, const Color(0xffb49f39)); // 0xffb29d3a + runCheck(0xffa6c7e5, const Color(0xff6f9ec9)); // 0xff6f9fcb + runCheck(0xffe79ab5, const Color(0xffdb6991)); + runCheck(0xffbfd56f, const Color(0xff8ea43e)); + runCheck(0xfff4ae55, const Color(0xffeb901a)); // 0xffea8d19 + runCheck(0xffb0a5fd, const Color(0xff7b69fc)); + runCheck(0xffaddfe5, const Color(0xff67aab2)); // 0xff67acb4 + runCheck(0xfff5ce6e, const Color(0xffc59a2c)); // 0xffc3992d + runCheck(0xffc2726a, const Color(0xffa94e45)); + runCheck(0xff94c849, const Color(0xff74a331)); + runCheck(0xffbd86e5, const Color(0xffa254da)); + runCheck(0xffee7e4a, const Color(0xffe55716)); + runCheck(0xffa6dcbf, const Color(0xff67af89)); + runCheck(0xff95a5fd, const Color(0xff5972fc)); + runCheck(0xff53a063, const Color(0xff3e784a)); + runCheck(0xff9987e1, const Color(0xff6f56d5)); + runCheck(0xffe4523d, const Color(0xffc8311c)); + runCheck(0xffc2c2c2, const Color(0xff9a9a9a)); + runCheck(0xff4f8de4, const Color(0xff216cd5)); + runCheck(0xffc6a8ad, const Color(0xffae838a)); + runCheck(0xffe7cc4d, const Color(0xffa69127)); // 0xffa38f26 + runCheck(0xffc8bebf, const Color(0xffa49597)); + runCheck(0xffa47462, const Color(0xff7f584a)); + runCheck(0xffacc25d, const Color(0xff8ea43e)); + }); - test('barBackground', () { - void runCheck(int base, Color expected) { - check(StreamColorSwatch(base)).barBackground.equals(expected); - } + test('barBackground', () { + void runCheck(int base, Color expected) { + check(StreamColorSwatch.light(base)).barBackground.equals(expected); + } - // Check against everything in ZULIP_ASSIGNMENT_COLORS - // in . - // (Skipping `streamColors` because there are 100+ of them.) - // On how to extract expected results from the replit, see: - // https://github.com/zulip/zulip-flutter/pull/381#discussion_r1399319296 - - // TODO Fix bug causing our implementation's results to differ from the - // replit's. Where they differ, see comment with what the replit gives. - - runCheck(0xff76ce90, const Color(0xffddefe1)); - runCheck(0xfffae589, const Color(0xfff1ead7)); // 0xfff0ead6 - runCheck(0xffa6c7e5, const Color(0xffe5ebf2)); // 0xffe5ecf2 - runCheck(0xffe79ab5, const Color(0xfff6e4ea)); - runCheck(0xffbfd56f, const Color(0xffe9edd6)); - runCheck(0xfff4ae55, const Color(0xfffbe7d4)); // 0xfffae7d4 - runCheck(0xffb0a5fd, const Color(0xffeae6fa)); - runCheck(0xffaddfe5, const Color(0xffe2edee)); - runCheck(0xfff5ce6e, const Color(0xfff5e9d5)); // 0xfff4e9d5 - runCheck(0xffc2726a, const Color(0xfff0dbd8)); // 0xffefdbd8 - runCheck(0xff94c849, const Color(0xffe5eed3)); // 0xffe4eed3 - runCheck(0xffbd86e5, const Color(0xffeddff5)); - runCheck(0xffee7e4a, const Color(0xfffdded1)); // 0xfffcded1 - runCheck(0xffa6dcbf, const Color(0xffe2ede7)); - runCheck(0xff95a5fd, const Color(0xffe5e6fa)); // 0xffe4e6fa - runCheck(0xff53a063, const Color(0xffd5e5d6)); - runCheck(0xff9987e1, const Color(0xffe5dff4)); - runCheck(0xffe4523d, const Color(0xfffcd6cd)); // 0xfffbd6cd - runCheck(0xffc2c2c2, const Color(0xffebebeb)); - runCheck(0xff4f8de4, const Color(0xffd9e0f5)); // 0xffd8e0f5 - runCheck(0xffc6a8ad, const Color(0xffeee7e8)); - runCheck(0xffe7cc4d, const Color(0xfff4ead0)); // 0xfff3eacf - runCheck(0xffc8bebf, const Color(0xffeceaea)); - runCheck(0xffa47462, const Color(0xffe7dad6)); - runCheck(0xffacc25d, const Color(0xffe9edd6)); + // Check against everything in ZULIP_ASSIGNMENT_COLORS + // in . + // (Skipping `streamColors` because there are 100+ of them.) + // On how to extract expected results from the replit, see: + // https://github.com/zulip/zulip-flutter/pull/381#discussion_r1399319296 + + // TODO Fix bug causing our implementation's results to differ from the + // replit's. Where they differ, see comment with what the replit gives. + + runCheck(0xff76ce90, const Color(0xffddefe1)); + runCheck(0xfffae589, const Color(0xfff1ead7)); // 0xfff0ead6 + runCheck(0xffa6c7e5, const Color(0xffe5ebf2)); // 0xffe5ecf2 + runCheck(0xffe79ab5, const Color(0xfff6e4ea)); + runCheck(0xffbfd56f, const Color(0xffe9edd6)); + runCheck(0xfff4ae55, const Color(0xfffbe7d4)); // 0xfffae7d4 + runCheck(0xffb0a5fd, const Color(0xffeae6fa)); + runCheck(0xffaddfe5, const Color(0xffe2edee)); + runCheck(0xfff5ce6e, const Color(0xfff5e9d5)); // 0xfff4e9d5 + runCheck(0xffc2726a, const Color(0xfff0dbd8)); // 0xffefdbd8 + runCheck(0xff94c849, const Color(0xffe5eed3)); // 0xffe4eed3 + runCheck(0xffbd86e5, const Color(0xffeddff5)); + runCheck(0xffee7e4a, const Color(0xfffdded1)); // 0xfffcded1 + runCheck(0xffa6dcbf, const Color(0xffe2ede7)); + runCheck(0xff95a5fd, const Color(0xffe5e6fa)); // 0xffe4e6fa + runCheck(0xff53a063, const Color(0xffd5e5d6)); + runCheck(0xff9987e1, const Color(0xffe5dff4)); + runCheck(0xffe4523d, const Color(0xfffcd6cd)); // 0xfffbd6cd + runCheck(0xffc2c2c2, const Color(0xffebebeb)); + runCheck(0xff4f8de4, const Color(0xffd9e0f5)); // 0xffd8e0f5 + runCheck(0xffc6a8ad, const Color(0xffeee7e8)); + runCheck(0xffe7cc4d, const Color(0xfff4ead0)); // 0xfff3eacf + runCheck(0xffc8bebf, const Color(0xffeceaea)); + runCheck(0xffa47462, const Color(0xffe7dad6)); + runCheck(0xffacc25d, const Color(0xffe9edd6)); + }); }); - test('lerp (different a, b)', () { - final swatchA = StreamColorSwatch(0xff76ce90); - - // TODO(#95) use something like StreamColorSwatch.dark(), once - // implemented, and remove debugFromBaseAndSwatch - const swatchB = StreamColorSwatch.debugFromBaseAndSwatch(0xff76ce90, { - StreamColorVariant.base: Color(0xff76ce90), - StreamColorVariant.unreadCountBadgeBackground: Color(0x4d65bd80), - StreamColorVariant.iconOnPlainBackground: Color(0xff73cb8d), - StreamColorVariant.iconOnBarBackground: Color(0xff73cb8d), - StreamColorVariant.barBackground: Color(0xff2e4935), + group('dark', () { + test('base', () { + check(StreamColorSwatch.dark(0xffffffff)) + .base.equals(const Color(0xffffffff)); }); + test('unreadCountBadgeBackground', () { + void runCheck(int base, Color expected) { + check(StreamColorSwatch.dark(base)) + .unreadCountBadgeBackground.equals(expected); + } + + // Check against everything in ZULIP_ASSIGNMENT_COLORS and EXTREME_COLORS + // in . + // On how to extract expected results from the replit, see: + // https://github.com/zulip/zulip-flutter/pull/643#issuecomment-2093940972 + + // TODO Fix bug causing our implementation's results to differ from the + // replit's. Where they differ, see comment with what the replit gives. + + // ZULIP_ASSIGNMENT_COLORS + runCheck(0xff76ce90, const Color(0x4d65bd80)); + runCheck(0xfffae589, const Color(0x4dbdab53)); // 0x4dbdaa52 + runCheck(0xffa6c7e5, const Color(0x4d8eafcc)); // 0x4d8fb0cd + runCheck(0xffe79ab5, const Color(0x4de295b0)); // 0x4de194af + runCheck(0xffbfd56f, const Color(0x4d9eb551)); // 0x4d9eb450 + runCheck(0xfff4ae55, const Color(0x4de19d45)); // 0x4de09c44 + runCheck(0xffb0a5fd, const Color(0x4daba0f8)); // 0x4daca2f9 + runCheck(0xffaddfe5, const Color(0x4d83b4b9)); // 0x4d83b4ba + runCheck(0xfff5ce6e, const Color(0x4dcba749)); // 0x4dcaa648 + runCheck(0xffc2726a, const Color(0x4dc2726a)); + runCheck(0xff94c849, const Color(0x4d86ba3c)); // 0x4d86ba3b + runCheck(0xffbd86e5, const Color(0x4dbd86e5)); + runCheck(0xffee7e4a, const Color(0x4dee7e4a)); + runCheck(0xffa6dcbf, const Color(0x4d82b69b)); // 0x4d82b79b + runCheck(0xff95a5fd, const Color(0x4d95a5fd)); + runCheck(0xff53a063, const Color(0x4d53a063)); + runCheck(0xff9987e1, const Color(0x4d9987e1)); + runCheck(0xffe4523d, const Color(0x4de4523d)); + runCheck(0xffc2c2c2, const Color(0x4dababab)); + runCheck(0xff4f8de4, const Color(0x4d4f8de4)); + runCheck(0xffc6a8ad, const Color(0x4dc2a4a9)); // 0x4dc1a4a9 + runCheck(0xffe7cc4d, const Color(0x4dc3ab2a)); // 0x4dc2aa28 + runCheck(0xffc8bebf, const Color(0x4db3a9aa)); + runCheck(0xffa47462, const Color(0x4da47462)); + + // EXTREME_COLORS + runCheck(0xFFFFFFFF, const Color(0x4dababab)); + runCheck(0xFF000000, const Color(0x4d474747)); + runCheck(0xFFD3D3D3, const Color(0x4dababab)); + runCheck(0xFFA9A9A9, const Color(0x4da9a9a9)); + runCheck(0xFF808080, const Color(0x4d808080)); + runCheck(0xFFFFFF00, const Color(0x4dacb300)); // 0x4dacb200 + runCheck(0xFFFF0000, const Color(0x4dff0000)); + runCheck(0xFF008000, const Color(0x4d008000)); + runCheck(0xFF0000FF, const Color(0x4d0000ff)); // 0x4d0902ff + runCheck(0xFFEE82EE, const Color(0x4dee82ee)); + runCheck(0xFFFFA500, const Color(0x4def9800)); // 0x4ded9600 + runCheck(0xFF800080, const Color(0x4d810181)); // 0x4d810281 + runCheck(0xFF00FFFF, const Color(0x4d00c2c3)); // 0x4d00c3c5 + runCheck(0xFFFF00FF, const Color(0x4dff00ff)); + runCheck(0xFF00FF00, const Color(0x4d00cb00)); + runCheck(0xFF800000, const Color(0x4d8d140c)); // 0x4d8b130b + runCheck(0xFF008080, const Color(0x4d008080)); + runCheck(0xFF000080, const Color(0x4d492bae)); // 0x4d4b2eb3 + runCheck(0xFFFFFFE0, const Color(0x4dadad90)); // 0x4dacad90 + runCheck(0xFFFF69B4, const Color(0x4dff69b4)); + }); + + test('iconOnPlainBackground', () { + void runCheck(int base, Color expected) { + check(StreamColorSwatch.dark(base)) + .iconOnPlainBackground.equals(expected); + } + + // Check against everything in ZULIP_ASSIGNMENT_COLORS + // in . + // (Skipping `streamColors` because there are 100+ of them.) + // On how to extract expected results from the replit, see: + // https://github.com/zulip/zulip-flutter/pull/643#issuecomment-2093940972 + + // TODO Fix bug causing our implementation's results to differ from the + // replit's. Where they differ, see comment with what the replit gives. + + runCheck(0xff76ce90, const Color(0xff73cb8d)); + runCheck(0xfffae589, const Color(0xffccb95f)); // 0xffcbb85e + runCheck(0xffa6c7e5, const Color(0xff9cbcda)); // 0xff9cbddb + runCheck(0xffe79ab5, const Color(0xffe79ab5)); + runCheck(0xffbfd56f, const Color(0xffacc25d)); + runCheck(0xfff4ae55, const Color(0xfff0ab52)); // 0xffefa951 + runCheck(0xffb0a5fd, const Color(0xffb0a5fd)); + runCheck(0xffaddfe5, const Color(0xff90c1c7)); // 0xff90c2c8 + runCheck(0xfff5ce6e, const Color(0xffd9b456)); // 0xffd8b355 + runCheck(0xffc2726a, const Color(0xffc2726a)); + runCheck(0xff94c849, const Color(0xff94c849)); + runCheck(0xffbd86e5, const Color(0xffbd86e5)); + runCheck(0xffee7e4a, const Color(0xffee7e4a)); + runCheck(0xffa6dcbf, const Color(0xff8fc4a8)); + runCheck(0xff95a5fd, const Color(0xff95a5fd)); + runCheck(0xff53a063, const Color(0xff53a063)); + runCheck(0xff9987e1, const Color(0xff9987e1)); + runCheck(0xffe4523d, const Color(0xffe4523d)); + runCheck(0xffc2c2c2, const Color(0xffb9b9b9)); + runCheck(0xff4f8de4, const Color(0xff4f8de4)); + runCheck(0xffc6a8ad, const Color(0xffc6a8ad)); + runCheck(0xffe7cc4d, const Color(0xffd1b839)); // 0xffd0b737 + runCheck(0xffc8bebf, const Color(0xffc0b6b7)); + runCheck(0xffa47462, const Color(0xffa47462)); + runCheck(0xffacc25d, const Color(0xffacc25d)); + }); + + test('iconOnBarBackground', () { + void runCheck(int base, Color expected) { + check(StreamColorSwatch.dark(base)) + .iconOnBarBackground.equals(expected); + } + + // Check against everything in ZULIP_ASSIGNMENT_COLORS + // in . + // (Skipping `streamColors` because there are 100+ of them.) + // On how to generate expected results, see: + // https://github.com/zulip/zulip-flutter/pull/643#issuecomment-2093940972 + + // TODO Fix bug causing our implementation's results to differ from the + // web app's. Where they differ, see comment with what web uses. + + runCheck(0xff76ce90, const Color(0xff73cb8d)); + runCheck(0xfffae589, const Color(0xffccb95f)); // 0xffcbb85e + runCheck(0xffa6c7e5, const Color(0xff9cbcda)); // 0xff9cbddb + runCheck(0xffe79ab5, const Color(0xffe79ab5)); + runCheck(0xffbfd56f, const Color(0xffacc25d)); + runCheck(0xfff4ae55, const Color(0xfff0ab52)); // 0xffefa951 + runCheck(0xffb0a5fd, const Color(0xffb0a5fd)); + runCheck(0xffaddfe5, const Color(0xff90c1c7)); // 0xff90c2c8 + runCheck(0xfff5ce6e, const Color(0xffd9b456)); // 0xffd8b355 + runCheck(0xffc2726a, const Color(0xffc2726a)); + runCheck(0xff94c849, const Color(0xff94c849)); + runCheck(0xffbd86e5, const Color(0xffbd86e5)); + runCheck(0xffee7e4a, const Color(0xffee7e4a)); + runCheck(0xffa6dcbf, const Color(0xff8fc4a8)); + runCheck(0xff95a5fd, const Color(0xff95a5fd)); + runCheck(0xff53a063, const Color(0xff53a063)); + runCheck(0xff9987e1, const Color(0xff9987e1)); + runCheck(0xffe4523d, const Color(0xffe4523d)); + runCheck(0xffc2c2c2, const Color(0xffb9b9b9)); + runCheck(0xff4f8de4, const Color(0xff4f8de4)); + runCheck(0xffc6a8ad, const Color(0xffc6a8ad)); + runCheck(0xffe7cc4d, const Color(0xffd1b839)); // 0xffd0b737 + runCheck(0xffc8bebf, const Color(0xffc0b6b7)); + runCheck(0xffa47462, const Color(0xffa47462)); + runCheck(0xffacc25d, const Color(0xffacc25d)); + }); + + test('barBackground', () { + void runCheck(int base, Color expected) { + check(StreamColorSwatch.dark(base)) + .barBackground.equals(expected); + } + + // Check against everything in ZULIP_ASSIGNMENT_COLORS + // in . + // (Skipping `streamColors` because there are 100+ of them.) + // On how to extract expected results from the replit, see: + // https://github.com/zulip/zulip-flutter/pull/643#issuecomment-2093940972 + + // TODO Fix bug causing our implementation's results to differ from the + // replit's. Where they differ, see comment with what the replit gives. + + runCheck(0xff76ce90, const Color(0xff2e4935)); + runCheck(0xfffae589, const Color(0xff4a4327)); + runCheck(0xffa6c7e5, const Color(0xff3a444e)); // 0xff3a454e + runCheck(0xffe79ab5, const Color(0xff523a42)); + runCheck(0xffbfd56f, const Color(0xff404627)); + runCheck(0xfff4ae55, const Color(0xff563f23)); // 0xff553e23 + runCheck(0xffb0a5fd, const Color(0xff413d59)); + runCheck(0xffaddfe5, const Color(0xff374648)); + runCheck(0xfff5ce6e, const Color(0xff4e4224)); // 0xff4e4124 + runCheck(0xffc2726a, const Color(0xff472d2a)); + runCheck(0xff94c849, const Color(0xff394821)); // 0xff384821 + runCheck(0xffbd86e5, const Color(0xff453351)); + runCheck(0xffee7e4a, const Color(0xff563120)); + runCheck(0xffa6dcbf, const Color(0xff36473e)); + runCheck(0xff95a5fd, const Color(0xff393d59)); + runCheck(0xff53a063, const Color(0xff243c28)); + runCheck(0xff9987e1, const Color(0xff3a3350)); + runCheck(0xffe4523d, const Color(0xff53241c)); // 0xff53241b + runCheck(0xffc2c2c2, const Color(0xff434343)); + runCheck(0xff4f8de4, const Color(0xff263551)); // 0xff253551 + runCheck(0xffc6a8ad, const Color(0xff483e40)); + runCheck(0xffe7cc4d, const Color(0xff4c431d)); // 0xff4c431c + runCheck(0xffc8bebf, const Color(0xff464243)); + runCheck(0xffa47462, const Color(0xff3d2d27)); + runCheck(0xffacc25d, const Color(0xff404627)); + }); + }); + + test('lerp (different a, b)', () { + final swatchA = StreamColorSwatch.light(0xff76ce90); + final swatchB = StreamColorSwatch.dark(0xff76ce90); for (final t in [0.0, 0.5, 1.0, -0.1, 1.1]) { final result = StreamColorSwatch.lerp(swatchA, swatchB, t)!; for (final variant in StreamColorVariant.values) { @@ -353,7 +541,7 @@ void main() { test('lerp (identical a, b)', () { check(StreamColorSwatch.lerp(null, null, 0.0)).isNull(); - final swatch = StreamColorSwatch(0xff76ce90); + final swatch = StreamColorSwatch.light(0xff76ce90); check(StreamColorSwatch.lerp(swatch, swatch, 0.5)).isNotNull() ..identicalTo(swatch) ..base.equals(const Color(0xff76ce90)); diff --git a/test/widgets/unread_count_badge_test.dart b/test/widgets/unread_count_badge_test.dart index 848372b976..a763edeb47 100644 --- a/test/widgets/unread_count_badge_test.dart +++ b/test/widgets/unread_count_badge_test.dart @@ -38,7 +38,7 @@ void main() { }); testWidgets('stream color', (WidgetTester tester) async { - final swatch = StreamColorSwatch(0xff76ce90); + final swatch = StreamColorSwatch.light(0xff76ce90); await prepare(tester, swatch); check(findBackgroundColor(tester)).equals(swatch.unreadCountBadgeBackground); });