Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add text style editing support to tab bar theme editor #548

Merged
merged 1 commit into from
Dec 18, 2022
Merged
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
11 changes: 10 additions & 1 deletion lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,14 @@ class MyApp extends StatelessWidget {
toolbarTextStyleCubit: appBarToolbarTextStyleCubit,
);

final tabBarThemeCubit = TabBarThemeCubit();
final tabBarLabelTextStyleCubit = TabBarLabelTextStyleCubit();
final tabBarUnselectedLabelTextStyleCubit =
TabBarUnselectedLabelTextStyleCubit();
final tabBarThemeCubit = TabBarThemeCubit(
labelTextStyleCubit: tabBarLabelTextStyleCubit,
unselectedLabelTextStyleCubit: tabBarUnselectedLabelTextStyleCubit,
);

final bottomNavigationBarThemeCubit = BottomNavigationBarThemeCubit();

final floatingActionButtonThemeCubit = FloatingActionButtonThemeCubit();
Expand Down Expand Up @@ -146,6 +153,8 @@ class MyApp extends StatelessWidget {
BlocProvider(create: (_) => appBarTitleTextStyleCubit),
BlocProvider(create: (_) => appBarToolbarTextStyleCubit),
BlocProvider(create: (_) => tabBarThemeCubit),
BlocProvider(create: (_) => tabBarLabelTextStyleCubit),
BlocProvider(create: (_) => tabBarUnselectedLabelTextStyleCubit),
BlocProvider(create: (_) => bottomNavigationBarThemeCubit),
BlocProvider(create: (_) => floatingActionButtonThemeCubit),
BlocProvider(create: (_) => elevatedButtonThemeCubit),
Expand Down
10 changes: 2 additions & 8 deletions lib/app_bar_theme/cubit/app_bar_theme_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,10 @@ class AppBarIconThemeCubit extends AbstractIconThemeCubit {}

class AppBarTitleTextStyleCubit extends AbstractTextStyleCubit {
AppBarTitleTextStyleCubit()
: super(
typeScale: _titleTypeScale,
isBaseStyleBlack: false,
);
: super(typeScale: _titleTypeScale, isBaseStyleBlack: false);
}

class AppBarToolbarTextStyleCubit extends AbstractTextStyleCubit {
AppBarToolbarTextStyleCubit()
: super(
typeScale: _toolbarTypeScale,
isBaseStyleBlack: false,
);
: super(typeScale: _toolbarTypeScale, isBaseStyleBlack: false);
}
2 changes: 1 addition & 1 deletion lib/app_bar_theme/view/app_bar_theme_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class AppBarThemeEditor extends ExpansionPanelItem {
TitleTextStyleCard(),
ToolbarTextStyleCard(),
],
)
),
],
);
}
Expand Down
61 changes: 58 additions & 3 deletions lib/tab_bar_theme/cubit/tab_bar_theme_cubit.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,63 @@
import 'dart:async';

import 'package:appainter/abstract_text_style/abstract_text_style.dart';
import 'package:appainter/services/services.dart';
import 'package:appainter_annotations/annotations.dart';
import 'package:bloc/bloc.dart';
import 'package:copy_with_extension/copy_with_extension.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:appainter/services/services.dart';

part 'tab_bar_theme_cubit.g.dart';
part 'tab_bar_theme_state.dart';

const _labelTypeScale = TypeScale.bodyText1;

@ThemeDocs(extraPropertyTypes: {'TabBarIndicatorSize'})
class TabBarThemeCubit extends Cubit<TabBarThemeState> {
TabBarThemeCubit() : super(const TabBarThemeState());
TabBarThemeCubit({
required this.labelTextStyleCubit,
required this.unselectedLabelTextStyleCubit,
}) : super(const TabBarThemeState()) {
labelTextStyleCubitSubscription = labelTextStyleCubit.stream.listen(
(otherState) {
final theme = state.theme.copyWith(labelStyle: otherState.style);
emit(state.copyWith(theme: theme));
},
);
unselectedLabelTextStyleCubitSubscription =
unselectedLabelTextStyleCubit.stream.listen(
(otherState) {
final theme = state.theme.copyWith(
unselectedLabelStyle: otherState.style,
);
emit(state.copyWith(theme: theme));
},
);
}

final TabBarLabelTextStyleCubit labelTextStyleCubit;
final TabBarUnselectedLabelTextStyleCubit unselectedLabelTextStyleCubit;

late final StreamSubscription labelTextStyleCubitSubscription;
late final StreamSubscription unselectedLabelTextStyleCubitSubscription;

static final defaultLabelTextStyle = kWhiteTextStyles[_labelTypeScale]!;

void themeChanged(TabBarTheme theme) => emit(state.copyWith(theme: theme));
@override
Future<void> close() {
labelTextStyleCubitSubscription.cancel();
unselectedLabelTextStyleCubitSubscription.cancel();
return super.close();
}

void themeChanged(TabBarTheme theme) {
labelTextStyleCubit.styleChanged(theme.labelStyle ?? defaultLabelTextStyle);
unselectedLabelTextStyleCubit.styleChanged(
theme.unselectedLabelStyle ?? defaultLabelTextStyle,
);
emit(state.copyWith(theme: theme));
}

void labelColorChanged(Color color) {
final theme = state.theme.copyWith(labelColor: color);
Expand All @@ -32,3 +77,13 @@ class TabBarThemeCubit extends Cubit<TabBarThemeState> {
}
}
}

class TabBarLabelTextStyleCubit extends AbstractTextStyleCubit {
TabBarLabelTextStyleCubit()
: super(typeScale: _labelTypeScale, isBaseStyleBlack: false);
}

class TabBarUnselectedLabelTextStyleCubit extends AbstractTextStyleCubit {
TabBarUnselectedLabelTextStyleCubit()
: super(typeScale: _labelTypeScale, isBaseStyleBlack: false);
}
51 changes: 44 additions & 7 deletions lib/tab_bar_theme/view/tab_bar_theme_editor.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:appainter/abstract_text_style/abstract_text_style.dart';
import 'package:appainter/color_theme/color_theme.dart';
import 'package:appainter/common/common.dart';
import 'package:appainter/services/services.dart';
import 'package:appainter/tab_bar_theme/tab_bar_theme.dart';
import 'package:appainter/widgets/widgets.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class TabBarThemeEditor extends ExpansionPanelItem {
const TabBarThemeEditor({Key? key}) : super(key: key);
Expand All @@ -14,12 +15,26 @@ class TabBarThemeEditor extends ExpansionPanelItem {

@override
Widget build(BuildContext context) {
return SideBySideList(
padding: kPaddingAll,
return NestedListView(
children: [
_LabelColorPicker(),
_UnselectedLabelColorPicker(),
_IndicatorSizeDropdown(),
SideBySideList(
padding: kPaddingAll,
children: [
_LabelColorPicker(),
_UnselectedLabelColorPicker(),
_IndicatorSizeDropdown(),
],
),
MyExpansionPanelList(
items: const [
_LabelTextStyleCard(
key: Key('tabBarThemeEditor_labelTextStyleCard'),
),
_UnselectedLabelTextStyleCard(
key: Key('tabBarThemeEditor_unselectedLabelTextStyleCard'),
),
],
)
],
);
}
Expand Down Expand Up @@ -91,3 +106,25 @@ class _IndicatorSizeDropdown extends StatelessWidget {
);
}
}

class _LabelTextStyleCard
extends AbstractTextStyleEditor<TabBarLabelTextStyleCubit> {
const _LabelTextStyleCard({Key? key}) : super(key: key);

@override
String get header => 'Label text style';

@override
String? get tooltip => TabBarThemeDocs.labelStyle;
}

class _UnselectedLabelTextStyleCard
extends AbstractTextStyleEditor<TabBarUnselectedLabelTextStyleCubit> {
const _UnselectedLabelTextStyleCard({Key? key}) : super(key: key);

@override
String get header => 'Unselected label text style';

@override
String? get tooltip => TabBarThemeDocs.unselectedLabelStyle;
}
6 changes: 6 additions & 0 deletions test/mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ class MockTabBarThemeCubit extends MockCubit<TabBarThemeState>

class FakeTabBarThemeState extends Fake implements TabBarThemeState {}

class MockTabBarLabelTextStyleCubit extends MockCubit<TextStyleState>
implements TabBarLabelTextStyleCubit {}

class MockTabBarUnselectedLabelTextStyleCubit extends MockCubit<TextStyleState>
implements TabBarUnselectedLabelTextStyleCubit {}

class MockBottomNavigationBarThemeCubit
extends MockCubit<BottomNavigationBarThemeState>
implements BottomNavigationBarThemeCubit {}
Expand Down
15 changes: 15 additions & 0 deletions test/pump_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ extension PumpApp on WidgetTester {
MockAppBarToolbarTextStyleCubit();

final TabBarThemeCubit tabBarThemeCubit = MockTabBarThemeCubit();
final TabBarLabelTextStyleCubit tabBarLabelTextStyleCubit =
MockTabBarLabelTextStyleCubit();
final TabBarUnselectedLabelTextStyleCubit
tabBarUnselectedLabelTextStyleCubit =
MockTabBarUnselectedLabelTextStyleCubit();

final BottomNavigationBarThemeCubit bottomNavigationBarThemeCubit =
MockBottomNavigationBarThemeCubit();

Expand Down Expand Up @@ -126,6 +132,13 @@ extension PumpApp on WidgetTester {
);

when(() => tabBarThemeCubit.state).thenReturn(const TabBarThemeState());
when(() => tabBarLabelTextStyleCubit.state).thenReturn(
TextStyleState(style: TabBarThemeCubit.defaultLabelTextStyle),
);
when(() => tabBarUnselectedLabelTextStyleCubit.state).thenReturn(
TextStyleState(style: TabBarThemeCubit.defaultLabelTextStyle),
);

when(() => bottomNavigationBarThemeCubit.state).thenReturn(
const BottomNavigationBarThemeState(),
);
Expand Down Expand Up @@ -185,6 +198,8 @@ extension PumpApp on WidgetTester {
BlocProvider.value(value: appBarTitleTextStyleCubit),
BlocProvider.value(value: appBarToolbarTextStyleCubit),
BlocProvider.value(value: tabBarThemeCubit),
BlocProvider.value(value: tabBarLabelTextStyleCubit),
BlocProvider.value(value: tabBarUnselectedLabelTextStyleCubit),
BlocProvider.value(value: bottomNavigationBarThemeCubit),
BlocProvider.value(value: floatingActionButtonThemeCubit),
BlocProvider.value(value: elevatedButtonThemeCubit),
Expand Down
60 changes: 47 additions & 13 deletions test/tab_bar_theme/tab_bar_theme_cubit_test.dart
Original file line number Diff line number Diff line change
@@ -1,42 +1,64 @@
import 'package:appainter/abstract_text_style/abstract_text_style.dart';
import 'package:appainter/services/services.dart';
import 'package:appainter/tab_bar_theme/tab_bar_theme.dart';
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:appainter/services/services.dart';
import 'package:appainter/tab_bar_theme/tab_bar_theme.dart';
import 'package:random_color_scheme/random_color_scheme.dart';

import '../utils.dart';

void main() {
late TabBarThemeCubit cubit;
late TabBarThemeCubit themeCubit;
late TabBarLabelTextStyleCubit labelTextStyleCubit;
late TabBarUnselectedLabelTextStyleCubit unselectedLabelTextStyleCubit;

late TabBarTheme theme;
late Color color;

setUp(() {
cubit = TabBarThemeCubit();
labelTextStyleCubit = TabBarLabelTextStyleCubit();
unselectedLabelTextStyleCubit = TabBarUnselectedLabelTextStyleCubit();
themeCubit = TabBarThemeCubit(
labelTextStyleCubit: labelTextStyleCubit,
unselectedLabelTextStyleCubit: unselectedLabelTextStyleCubit,
);
color = getRandomColor();

final colorScheme = randomColorSchemeLight(shouldPrint: false);
theme = ThemeData.from(colorScheme: colorScheme).tabBarTheme;
});

blocTest<TabBarThemeCubit, TabBarThemeState>(
'should emit theme',
build: () => cubit,
'emit theme',
build: () => themeCubit,
act: (cubit) => cubit.themeChanged(theme),
expect: () => [TabBarThemeState(theme: theme)],
expect: () => [
TabBarThemeState(theme: theme),
TabBarThemeState(
theme: theme.copyWith(
labelStyle: TabBarThemeCubit.defaultLabelTextStyle,
),
),
TabBarThemeState(
theme: theme.copyWith(
labelStyle: TabBarThemeCubit.defaultLabelTextStyle,
unselectedLabelStyle: TabBarThemeCubit.defaultLabelTextStyle,
),
),
],
);

blocTest<TabBarThemeCubit, TabBarThemeState>(
'should emit label color',
build: () => cubit,
'emit label color',
build: () => themeCubit,
act: (cubit) => cubit.labelColorChanged(color),
expect: () => [TabBarThemeState(theme: TabBarTheme(labelColor: color))],
);

blocTest<TabBarThemeCubit, TabBarThemeState>(
'should emit unselected label color',
build: () => cubit,
'emit unselected label color',
build: () => themeCubit,
act: (cubit) => cubit.unselectedLabelColorChanged(color),
expect: () {
return [
Expand All @@ -48,8 +70,8 @@ void main() {
group('test indicator size', () {
for (var size in TabBarIndicatorSize.values) {
blocTest<TabBarThemeCubit, TabBarThemeState>(
'should emit $size',
build: () => cubit,
'emit $size',
build: () => themeCubit,
act: (cubit) {
cubit.indicatorSizeChanged(UtilService.enumToString(size));
},
Expand All @@ -59,4 +81,16 @@ void main() {
);
}
});

test('initialise label text style cubit', () {
final cubit = TabBarLabelTextStyleCubit();
expect(cubit.typeScale, equals(TypeScale.bodyText1));
expect(cubit.isBaseStyleBlack, equals(false));
});

test('initialise unselected label text style cubit', () {
final cubit = TabBarUnselectedLabelTextStyleCubit();
expect(cubit.typeScale, equals(TypeScale.bodyText1));
expect(cubit.isBaseStyleBlack, equals(false));
});
}
Loading