Skip to content

Commit

Permalink
feat: ✨ text scale addon
Browse files Browse the repository at this point in the history
  • Loading branch information
jenshor committed Aug 24, 2022
1 parent 8cfd368 commit db2a2b5
Show file tree
Hide file tree
Showing 15 changed files with 346 additions and 107 deletions.
1 change: 1 addition & 0 deletions examples/knobs_example/lib/widgetbook.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class KnobsExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Widgetbook.material(
addons: [],
devices: const [
Apple.iPhone11,
],
Expand Down
51 changes: 3 additions & 48 deletions examples/widgetbook_annotation_example/lib/app.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:meal_app/themes/dark_theme.dart';
import 'package:meal_app/widgets/dashboard.dart';
import 'package:widgetbook_annotation/widgetbook_annotation.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:meal_app/themes/dark_theme.dart';
import 'package:meal_app/widgets/dashboard.dart';
import 'package:widgetbook/widgetbook.dart';
import 'package:widgetbook_annotation/widgetbook_annotation.dart';

@WidgetbookDeviceFrameBuilder()
DeviceFrameBuilderFunction frameBuilder = (
Expand Down Expand Up @@ -35,25 +34,6 @@ DeviceFrameBuilderFunction frameBuilder = (
return child;
};

@WidgetbookLocalizationBuilder()
LocalizationBuilderFunction localizationBuilder = (
BuildContext context,
List<Locale> supportedLocales,
List<LocalizationsDelegate<dynamic>>? localizationsDelegates,
Locale activeLocale,
Widget child,
) {
if (localizationsDelegates != null) {
return Localizations(
locale: activeLocale,
delegates: localizationsDelegates,
child: child,
);
}

return child;
};

@WidgetbookScaffoldBuilder()
ScaffoldBuilderFunction scaffoldBuilder = (
BuildContext context,
Expand All @@ -69,31 +49,6 @@ ScaffoldBuilderFunction scaffoldBuilder = (
return child;
};

@WidgetbookThemeBuilder()
ThemeBuilderFunction<CustomTheme> themeBuilder<CustomTheme>() => (
BuildContext context,
CustomTheme theme,
Widget child,
) {
if (theme is ThemeData) {
return Theme(
data: theme,
child: child,
);
}
if (theme is CupertinoThemeData) {
return CupertinoTheme(
data: theme,
child: child,
);
}

throw Exception(
'You are using Widgetbook with custom theme data. '
'Please provide an implementation for themeBuilder.',
);
};

@WidgetbookLocales()
final locales = <Locale>[
Locale('en'),
Expand Down
9 changes: 9 additions & 0 deletions examples/widgetbook_example/widgetbook/widgetbook.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ class HotreloadWidgetbook extends StatelessWidget {
darkTheme,
],
),
TextScaleAddon(
data: TextScaleSelection(
activeTextScales: {
1,
2,
},
textScales: [1, 2, 3],
),
),
LocalizationAddon(
data: LocalizationSelection(
activeLocales: {
Expand Down
1 change: 1 addition & 0 deletions packages/widgetbook/lib/src/addons/addons.dart
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export './localization_addon/localization_addon.dart';
export './text_scale_addon/text_scale_addon.dart';
export './theme_addon/theme_addon.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import 'package:flutter/material.dart';
import 'package:nested/nested.dart';
import 'package:provider/provider.dart';
import 'package:widgetbook/src/addons/addon.dart';
import 'package:widgetbook/src/addons/addon_provider.dart';
import 'package:widgetbook/src/addons/text_scale_addon/text_scale_provider.dart';
import 'package:widgetbook/src/addons/text_scale_addon/text_scale_selection.dart';
import 'package:widgetbook/src/addons/text_scale_addon/text_scale_selection_provider.dart';
import 'package:widgetbook/src/navigation/router.dart';

export './text_scale_selection.dart';

class TextScaleAddon extends WidgetbookAddOn {
TextScaleAddon({
required TextScaleSelection data,
}) : super(
icon: const Icon(Icons.text_fields_outlined),
name: 'text-scales',
wrapperBuilder: (context, routerData, child) =>
_wrapperBuilder(context, child, routerData, data),
builder: _builder,
providerBuilder: _providerBuilder,
selectionCount: _selectionCount,
getQueryParameter: _getQueryParameter,
);
}

String _getQueryParameter(BuildContext context) {
final selectedItems =
context.read<TextScaleSelectionProvider>().value.activeTextScales;

return selectedItems
.map(
(e) => e.toStringAsExponential(2),
)
.join(',');
}

int _selectionCount(BuildContext context) {
return context
.read<TextScaleSelectionProvider>()
.value
.activeTextScales
.length;
}

Widget _builder(BuildContext context) {
final data = context.watch<TextScaleSelectionProvider>().value;
final textScales = data.textScales;

return ListView.separated(
itemBuilder: (context, index) {
final item = textScales[index];
return ListTile(
title: Text(item.toString()),
onTap: () {
context.read<TextScaleSelectionProvider>().tapped(item);
context.read<AddOnProvider>().update();
navigate(context);
},
);
},
separatorBuilder: (_, __) {
// TODO improve this
return const SizedBox(
height: 8,
);
},
itemCount: textScales.length,
);
}

Widget _wrapperBuilder(
BuildContext context,
Widget child,
Map<String, dynamic> routerData,
TextScaleSelection data,
) {
final activeTextScalesString = routerData['text-scales'] as String?;
final selectedTextScales = <double>[];
if (activeTextScalesString != null) {
final activeTextScales = activeTextScalesString.split(',');
final mapTextScales = {
for (var e in data.textScales) e.toStringAsExponential(2): e
};

for (final activeTextScale in activeTextScales) {
if (mapTextScales.containsKey(activeTextScale)) {
selectedTextScales.add(mapTextScales[activeTextScale]!);
}
}
}

final initialData = selectedTextScales.isNotEmpty
? data.copyWith(activeTextScales: selectedTextScales.toSet())
: data;

return ChangeNotifierProvider(
create: (_) => TextScaleSelectionProvider(initialData),
child: child,
);
}

SingleChildWidget _providerBuilder(
BuildContext context,
int index,
) {
final selection = context.watch<TextScaleSelectionProvider>().value;
final textScale = selection.activeTextScales.isEmpty
? selection.textScales.first
: selection.textScales.elementAt(index);
return ChangeNotifierProvider(
create: (context) => TextScaleProvider(textScale),
);
}

extension TextScaleExtension on BuildContext {
/// Creates adjustable parameters for the WidgetbookUseCase
double get textScale => watch<TextScaleProvider>().value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import 'package:flutter/material.dart';

class TextScaleProvider extends ValueNotifier<double> {
TextScaleProvider(double data) : super(data);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'text_scale_selection.freezed.dart';

@freezed
class TextScaleSelection with _$TextScaleSelection {
factory TextScaleSelection({
required Set<double> activeTextScales,
required List<double> textScales,
}) = _TextScaleSelection;
}
Loading

0 comments on commit db2a2b5

Please sign in to comment.