feat: add GalleryHeader/GalleryFooter theme classes (#546)
* chore: Add ImageHeaderTheme and ImageHeaderThemeData to stream_chat_theme.dart This commit adds the following classes to `stream_chat_theme.dart`: 1. `ImageHeaderTheme`, an `InheritedTheme` widget that can wrap other widgets and provide that sub-tree with an `ImageHeaderThemeData` 2. `ImageHeaderThemeData`, a class that allows for the customization of `ImageHeader` widgets * Make ImageHeaderThemeData constructor const * test: initial ImageHeaderThemeData tests Tests the copyWith, ==, and hashcode functions * test: add tests for default ImageHeaderThemeData values Tests the default values of ImageHeaderThemeData that gets built in a StreamChatThemeData against control values. * Update test name and add comments describing control * fix: use ImageHeaderTheme.of(context) instead of StreamChatTheme.of(context) This ensures that ImageHeader will always look for the closest ImageHeaderThemeData in the widget tree. * test: add dark theme default values test * run dartfmt on test file * test: lerping between ImageHeaderThemeData Added tests that lerp from one ImageHeaderThemeData to another (light to dark and dark to light) * test: merging ImageHeaderThemeData Added tests that merge light and dark ImageHeaderThemeData together (light + dark = dark, dark + light = light) * test: add a half-lerp test Added a test that lerps halway between light and dark ImageHeaderThemeData * chore: Add ImageFooterTheme and ImageFooterThemeData to stream_chat_theme.dart This commit adds the following classes to `stream_chat_theme.dart`: 1. `ImageFooterTheme`, an `InheritedTheme` widget that can wrap other widgets and provide that sub-tree with an `ImageFooterThemeData` 2. `ImageFooterThemeData`, a class that allows for the customization of `ImageFooter` widget * chore: apply ImageFooterThemeData to image_footer.dart * fix: make ImageFooterThemeData constructor const * test: add tests for ImageFooterThemeData * add a missing trailing comma * chore: rename ImageHeader & ImageFooter to GalleryHeader and GalleryFooter The respective theme classes and tests have also been renamed * Run dartfmt on test * test: fix failing tests due to renaming
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
import 'package:flutter/material.dart' hide TextTheme;
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
class MockStreamChatClient extends Mock implements StreamChatClient {}
|
||||
|
||||
void main() {
|
||||
test('GalleryFooterThemeData copyWith, ==, hashCode basics', () {
|
||||
expect(const GalleryFooterThemeData(),
|
||||
const GalleryFooterThemeData().copyWith());
|
||||
expect(const GalleryFooterThemeData().hashCode,
|
||||
const GalleryFooterThemeData().copyWith().hashCode);
|
||||
});
|
||||
|
||||
test(
|
||||
'Light GalleryFooterThemeData lerps completely to dark GalleryFooterThemeData',
|
||||
() {
|
||||
expect(
|
||||
const GalleryFooterThemeData().lerp(_galleryFooterThemeDataControl,
|
||||
_galleryFooterThemeDataControlDark, 1),
|
||||
_galleryFooterThemeDataControlDark);
|
||||
});
|
||||
|
||||
test(
|
||||
'Light GalleryFooterThemeData lerps halfway to dark GalleryFooterThemeData',
|
||||
() {
|
||||
expect(
|
||||
const GalleryFooterThemeData().lerp(_galleryFooterThemeDataControl,
|
||||
_galleryFooterThemeDataControlDark, 0.5),
|
||||
_galleryFooterThemeDataControlMidLerp);
|
||||
});
|
||||
|
||||
test(
|
||||
'Dark GalleryFooterThemeData lerps completely to light GalleryFooterThemeData',
|
||||
() {
|
||||
expect(
|
||||
const GalleryFooterThemeData().lerp(_galleryFooterThemeDataControlDark,
|
||||
_galleryFooterThemeDataControl, 1),
|
||||
_galleryFooterThemeDataControl);
|
||||
});
|
||||
|
||||
test('Merging dark and light themes results in a dark theme', () {
|
||||
expect(
|
||||
_galleryFooterThemeDataControl
|
||||
.merge(_galleryFooterThemeDataControlDark),
|
||||
_galleryFooterThemeDataControlDark);
|
||||
});
|
||||
|
||||
test('Merging dark and light themes results in a dark theme', () {
|
||||
expect(
|
||||
_galleryFooterThemeDataControlDark
|
||||
.merge(_galleryFooterThemeDataControl),
|
||||
_galleryFooterThemeDataControl);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'Passing no GalleryFooterThemeData returns default light theme values',
|
||||
(WidgetTester tester) async {
|
||||
late BuildContext _context;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
builder: (context, child) => StreamChat(
|
||||
client: MockStreamChatClient(),
|
||||
child: child,
|
||||
),
|
||||
home: Builder(
|
||||
builder: (context) {
|
||||
_context = context;
|
||||
return Scaffold(
|
||||
appBar: GalleryFooter(
|
||||
message: Message(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final imageFooterTheme = GalleryFooterTheme.of(_context);
|
||||
expect(imageFooterTheme.backgroundColor,
|
||||
_galleryFooterThemeDataControl.backgroundColor);
|
||||
expect(imageFooterTheme.shareIconColor,
|
||||
_galleryFooterThemeDataControl.shareIconColor);
|
||||
expect(imageFooterTheme.titleTextStyle,
|
||||
_galleryFooterThemeDataControl.titleTextStyle);
|
||||
expect(imageFooterTheme.gridIconButtonColor,
|
||||
_galleryFooterThemeDataControl.gridIconButtonColor);
|
||||
expect(imageFooterTheme.bottomSheetBarrierColor,
|
||||
_galleryFooterThemeDataControl.bottomSheetBarrierColor);
|
||||
expect(imageFooterTheme.bottomSheetBackgroundColor,
|
||||
_galleryFooterThemeDataControl.bottomSheetBackgroundColor);
|
||||
expect(imageFooterTheme.bottomSheetCloseIconColor,
|
||||
_galleryFooterThemeDataControl.bottomSheetCloseIconColor);
|
||||
expect(imageFooterTheme.bottomSheetPhotosTextStyle,
|
||||
_galleryFooterThemeDataControl.bottomSheetPhotosTextStyle);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'Passing no GalleryFooterThemeData returns default dark theme values',
|
||||
(WidgetTester tester) async {
|
||||
late BuildContext _context;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
builder: (context, child) => StreamChat(
|
||||
client: MockStreamChatClient(),
|
||||
streamChatThemeData: StreamChatThemeData.dark(),
|
||||
child: child,
|
||||
),
|
||||
home: Builder(
|
||||
builder: (context) {
|
||||
_context = context;
|
||||
return Scaffold(
|
||||
appBar: GalleryFooter(
|
||||
message: Message(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final imageFooterTheme = GalleryFooterTheme.of(_context);
|
||||
expect(imageFooterTheme.backgroundColor,
|
||||
_galleryFooterThemeDataControlDark.backgroundColor);
|
||||
expect(imageFooterTheme.shareIconColor,
|
||||
_galleryFooterThemeDataControlDark.shareIconColor);
|
||||
expect(imageFooterTheme.titleTextStyle,
|
||||
_galleryFooterThemeDataControlDark.titleTextStyle);
|
||||
expect(imageFooterTheme.gridIconButtonColor,
|
||||
_galleryFooterThemeDataControlDark.gridIconButtonColor);
|
||||
expect(imageFooterTheme.bottomSheetBarrierColor,
|
||||
_galleryFooterThemeDataControlDark.bottomSheetBarrierColor);
|
||||
expect(imageFooterTheme.bottomSheetBackgroundColor,
|
||||
_galleryFooterThemeDataControlDark.bottomSheetBackgroundColor);
|
||||
expect(imageFooterTheme.bottomSheetCloseIconColor,
|
||||
_galleryFooterThemeDataControlDark.bottomSheetCloseIconColor);
|
||||
expect(imageFooterTheme.bottomSheetPhotosTextStyle,
|
||||
_galleryFooterThemeDataControlDark.bottomSheetPhotosTextStyle);
|
||||
});
|
||||
}
|
||||
|
||||
// Light theme control
|
||||
final _galleryFooterThemeDataControl = GalleryFooterThemeData(
|
||||
backgroundColor: ColorTheme.light().barsBg,
|
||||
shareIconColor: ColorTheme.light().textHighEmphasis,
|
||||
titleTextStyle: TextTheme.light().headlineBold,
|
||||
gridIconButtonColor: ColorTheme.light().textHighEmphasis,
|
||||
bottomSheetBackgroundColor: ColorTheme.light().barsBg,
|
||||
bottomSheetBarrierColor: ColorTheme.light().overlay,
|
||||
bottomSheetCloseIconColor: ColorTheme.light().textHighEmphasis,
|
||||
bottomSheetPhotosTextStyle: TextTheme.light().headlineBold,
|
||||
);
|
||||
|
||||
// Mid-lerp theme control
|
||||
const _galleryFooterThemeDataControlMidLerp = GalleryFooterThemeData(
|
||||
backgroundColor: Color(0xff87898b),
|
||||
shareIconColor: Color(0xff7f7f7f),
|
||||
titleTextStyle: TextStyle(
|
||||
color: Color(0xff7f7f7f),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
gridIconButtonColor: Color(0xff7f7f7f),
|
||||
bottomSheetBarrierColor: Color(0x4c000000),
|
||||
bottomSheetBackgroundColor: Color(0xff87898b),
|
||||
bottomSheetPhotosTextStyle: TextStyle(
|
||||
color: Color(0xff7f7f7f),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
bottomSheetCloseIconColor: Color(0xff7f7f7f),
|
||||
);
|
||||
|
||||
// Dark theme control
|
||||
final _galleryFooterThemeDataControlDark = GalleryFooterThemeData(
|
||||
backgroundColor: ColorTheme.dark().barsBg,
|
||||
shareIconColor: ColorTheme.dark().textHighEmphasis,
|
||||
titleTextStyle: TextTheme.dark().headlineBold,
|
||||
gridIconButtonColor: ColorTheme.dark().textHighEmphasis,
|
||||
bottomSheetBackgroundColor: ColorTheme.dark().barsBg,
|
||||
bottomSheetBarrierColor: ColorTheme.dark().overlay,
|
||||
bottomSheetCloseIconColor: ColorTheme.dark().textHighEmphasis,
|
||||
bottomSheetPhotosTextStyle: TextTheme.dark().headlineBold,
|
||||
);
|
||||
@@ -0,0 +1,190 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
class MockStreamChatClient extends Mock implements StreamChatClient {}
|
||||
|
||||
void main() {
|
||||
test('GalleryHeaderThemeData copyWith, ==, hashCode basics', () {
|
||||
expect(const GalleryHeaderThemeData(),
|
||||
const GalleryHeaderThemeData().copyWith());
|
||||
expect(const GalleryHeaderThemeData().hashCode,
|
||||
const GalleryHeaderThemeData().copyWith().hashCode);
|
||||
});
|
||||
|
||||
test(
|
||||
'Light GalleryHeaderThemeData lerps completely to dark GalleryHeaderThemeData',
|
||||
() {
|
||||
expect(
|
||||
const GalleryHeaderThemeData().lerp(_galleryHeaderThemeDataControl,
|
||||
_galleryHeaderThemeDataDarkControl, 1),
|
||||
_galleryHeaderThemeDataDarkControl);
|
||||
});
|
||||
|
||||
test(
|
||||
'Light GalleryHeaderThemeData lerps halfway to dark GalleryHeaderThemeData',
|
||||
() {
|
||||
expect(
|
||||
const GalleryHeaderThemeData().lerp(_galleryHeaderThemeDataControl,
|
||||
_galleryHeaderThemeDataDarkControl, 0.5),
|
||||
_galleryHeaderThemeDataHalfLerpControl);
|
||||
});
|
||||
|
||||
test(
|
||||
'Dark GalleryHeaderThemeData lerps completely to light GalleryHeaderThemeData',
|
||||
() {
|
||||
expect(
|
||||
const GalleryHeaderThemeData().lerp(_galleryHeaderThemeDataDarkControl,
|
||||
_galleryHeaderThemeDataControl, 1),
|
||||
_galleryHeaderThemeDataControl);
|
||||
});
|
||||
|
||||
test('Merging dark and light themes results in a dark theme', () {
|
||||
expect(
|
||||
_galleryHeaderThemeDataControl
|
||||
.merge(_galleryHeaderThemeDataDarkControl),
|
||||
_galleryHeaderThemeDataDarkControl);
|
||||
});
|
||||
|
||||
test('Merging dark and light themes results in a dark theme', () {
|
||||
expect(
|
||||
_galleryHeaderThemeDataDarkControl
|
||||
.merge(_galleryHeaderThemeDataControl),
|
||||
_galleryHeaderThemeDataControl);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'Passing no GalleryHeaderThemeData returns default light theme values',
|
||||
(WidgetTester tester) async {
|
||||
late BuildContext _context;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
builder: (context, child) => StreamChat(
|
||||
client: MockStreamChatClient(),
|
||||
child: child,
|
||||
),
|
||||
home: Builder(
|
||||
builder: (context) {
|
||||
_context = context;
|
||||
return Scaffold(
|
||||
appBar: GalleryHeader(
|
||||
message: Message(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final imageHeaderTheme = GalleryHeaderTheme.of(_context);
|
||||
expect(imageHeaderTheme.closeButtonColor,
|
||||
_galleryHeaderThemeDataControl.closeButtonColor);
|
||||
expect(imageHeaderTheme.backgroundColor,
|
||||
_galleryHeaderThemeDataControl.backgroundColor);
|
||||
expect(imageHeaderTheme.iconMenuPointColor,
|
||||
_galleryHeaderThemeDataControl.iconMenuPointColor);
|
||||
expect(imageHeaderTheme.titleTextStyle,
|
||||
_galleryHeaderThemeDataControl.titleTextStyle);
|
||||
expect(imageHeaderTheme.subtitleTextStyle,
|
||||
_galleryHeaderThemeDataControl.subtitleTextStyle);
|
||||
expect(imageHeaderTheme.bottomSheetBarrierColor,
|
||||
_galleryHeaderThemeDataControl.bottomSheetBarrierColor);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'Passing no GalleryHeaderThemeData returns default dark theme values',
|
||||
(WidgetTester tester) async {
|
||||
late BuildContext _context;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
builder: (context, child) => StreamChat(
|
||||
client: MockStreamChatClient(),
|
||||
streamChatThemeData: StreamChatThemeData.dark(),
|
||||
child: child,
|
||||
),
|
||||
home: Builder(
|
||||
builder: (context) {
|
||||
_context = context;
|
||||
return Scaffold(
|
||||
appBar: GalleryHeader(
|
||||
message: Message(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final imageHeaderTheme = GalleryHeaderTheme.of(_context);
|
||||
expect(imageHeaderTheme.closeButtonColor,
|
||||
_galleryHeaderThemeDataDarkControl.closeButtonColor);
|
||||
expect(imageHeaderTheme.backgroundColor,
|
||||
_galleryHeaderThemeDataDarkControl.backgroundColor);
|
||||
expect(imageHeaderTheme.iconMenuPointColor,
|
||||
_galleryHeaderThemeDataDarkControl.iconMenuPointColor);
|
||||
expect(imageHeaderTheme.titleTextStyle,
|
||||
_galleryHeaderThemeDataDarkControl.titleTextStyle);
|
||||
expect(imageHeaderTheme.subtitleTextStyle,
|
||||
_galleryHeaderThemeDataDarkControl.subtitleTextStyle);
|
||||
expect(imageHeaderTheme.bottomSheetBarrierColor,
|
||||
_galleryHeaderThemeDataDarkControl.bottomSheetBarrierColor);
|
||||
});
|
||||
}
|
||||
|
||||
// Light theme test control.
|
||||
final _galleryHeaderThemeDataControl = GalleryHeaderThemeData(
|
||||
closeButtonColor: const Color(0xff000000),
|
||||
backgroundColor: const Color(0xffffffff),
|
||||
iconMenuPointColor: const Color(0xff000000),
|
||||
titleTextStyle: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
),
|
||||
subtitleTextStyle: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
).copyWith(
|
||||
color: const Color(0xff7A7A7A),
|
||||
),
|
||||
bottomSheetBarrierColor: const Color.fromRGBO(0, 0, 0, 0.2),
|
||||
);
|
||||
|
||||
// Light theme test control.
|
||||
final _galleryHeaderThemeDataHalfLerpControl = GalleryHeaderThemeData(
|
||||
closeButtonColor: const Color(0xff7f7f7f),
|
||||
backgroundColor: const Color(0xff87898b),
|
||||
iconMenuPointColor: const Color(0xff7f7f7f),
|
||||
titleTextStyle: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xff7f7f7f),
|
||||
),
|
||||
subtitleTextStyle: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Color(0xff7a7a7a),
|
||||
).copyWith(
|
||||
color: const Color(0xff7A7A7A),
|
||||
),
|
||||
bottomSheetBarrierColor: const Color(0x4c000000),
|
||||
);
|
||||
|
||||
// Dark theme test control.
|
||||
final _galleryHeaderThemeDataDarkControl = GalleryHeaderThemeData(
|
||||
closeButtonColor: const Color(0xffffffff),
|
||||
backgroundColor: const Color(0xff101418),
|
||||
iconMenuPointColor: const Color(0xffffffff),
|
||||
titleTextStyle: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
subtitleTextStyle: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.white,
|
||||
).copyWith(
|
||||
color: const Color(0xff7A7A7A),
|
||||
),
|
||||
bottomSheetBarrierColor: const Color.fromRGBO(0, 0, 0, 0.4),
|
||||
);
|
||||
@@ -37,7 +37,7 @@ void main() {
|
||||
child: WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
child: Scaffold(
|
||||
body: ImageFooter(
|
||||
body: GalleryFooter(
|
||||
message: Message(),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user