Line data Source code
1 : import 'package:flutter/cupertino.dart';
2 : import 'package:flutter/material.dart';
3 : import 'package:widgetbook/src/models/app_info.dart';
4 : import 'package:widgetbook/src/models/device.dart';
5 : import 'package:widgetbook/src/models/organizers/organizer_helper/organizer_helper.dart';
6 : import 'package:widgetbook/src/models/organizers/organizers.dart';
7 : import 'package:widgetbook/src/providers/canvas_provider.dart';
8 : import 'package:widgetbook/src/providers/canvas_state.dart';
9 : import 'package:widgetbook/src/providers/device_provider.dart';
10 : import 'package:widgetbook/src/providers/device_state.dart';
11 : import 'package:widgetbook/src/providers/injected_theme_provider.dart';
12 : import 'package:widgetbook/src/providers/injected_theme_state.dart';
13 : import 'package:widgetbook/src/providers/organizer_provider.dart';
14 : import 'package:widgetbook/src/providers/organizer_state.dart';
15 : import 'package:widgetbook/src/providers/theme_provider.dart';
16 : import 'package:widgetbook/src/providers/zoom_provider.dart';
17 : import 'package:widgetbook/src/providers/zoom_state.dart';
18 : import 'package:widgetbook/src/repositories/selected_story_repository.dart';
19 : import 'package:widgetbook/src/repositories/story_repository.dart';
20 : import 'package:widgetbook/src/routing/route_information_parser.dart';
21 : import 'package:widgetbook/src/routing/story_router_delegate.dart';
22 : import 'package:widgetbook/src/utils/utils.dart';
23 : import 'configure_non_web.dart' if (dart.library.html) 'configure_web.dart';
24 :
25 : class Widgetbook extends StatefulWidget {
26 : /// Categories which host Folders and WidgetElements.
27 : /// This can be used to organize the structure of the Widgetbook on a large scale.
28 : final List<Category> categories;
29 :
30 : /// The devices on which Stories are previewed.
31 : final List<Device> devices;
32 :
33 : /// Information about the app that is catalogued in the Widgetbook.
34 : final AppInfo appInfo;
35 :
36 : /// The `ThemeData` that is shown when the light theme is active.
37 : final ThemeData? lightTheme;
38 :
39 : /// The `ThemeData` that is shown when the dark theme is active.
40 : final ThemeData? darkTheme;
41 :
42 0 : const Widgetbook({
43 : Key? key,
44 : required this.categories,
45 : this.devices = const [
46 : Apple.iPhone11,
47 : Apple.iPhone12,
48 : Apple.iPhone12mini,
49 : Apple.iPhone12pro,
50 : Samsung.s10,
51 : Samsung.s21ultra,
52 : ],
53 : required this.appInfo,
54 : this.lightTheme,
55 : this.darkTheme,
56 0 : }) : super(key: key);
57 :
58 0 : @override
59 0 : _WidgetbookState createState() => _WidgetbookState();
60 : }
61 :
62 : class _WidgetbookState extends State<Widgetbook> {
63 : // TODO ugly hack
64 : late BuildContext contextWithProviders;
65 :
66 : SelectedStoryRepository selectedStoryRepository = SelectedStoryRepository();
67 : StoryRepository storyRepository = StoryRepository();
68 :
69 : ZoomState zoomState = ZoomState.normal();
70 : CanvasState canvasState = CanvasState.unselected();
71 : ThemeMode themeMode = ThemeMode.dark;
72 : late DeviceState deviceState;
73 : late OrganizerState organizerState;
74 : late InjectedThemeState injectedThemeState;
75 :
76 0 : @override
77 : void initState() {
78 0 : configureApp();
79 :
80 0 : deviceState = DeviceState(
81 0 : availableDevices: widget.devices,
82 0 : currentDevice: widget.devices.first,
83 : );
84 0 : organizerState = OrganizerState.unfiltered(categories: widget.categories);
85 0 : injectedThemeState = InjectedThemeState(
86 0 : darkTheme: widget.darkTheme,
87 0 : lightTheme: widget.lightTheme,
88 : );
89 0 : super.initState();
90 : }
91 :
92 0 : @override
93 : void didUpdateWidget(covariant Widgetbook oldWidget) {
94 0 : OrganizerProvider.of(contextWithProviders)!.update(widget.categories);
95 0 : DeviceProvider.of(contextWithProviders)!.update(widget.devices);
96 0 : InjectedThemeProvider.of(contextWithProviders)!.themesChanged(
97 0 : lightTheme: widget.lightTheme,
98 0 : darkTheme: widget.darkTheme,
99 : );
100 :
101 0 : super.didUpdateWidget(oldWidget);
102 : }
103 :
104 0 : @override
105 : Widget build(BuildContext context) {
106 0 : return OrganizerProvider(
107 0 : selectedStoryRepository: selectedStoryRepository,
108 0 : storyRepository: storyRepository,
109 0 : state: organizerState,
110 0 : onStateChanged: (OrganizerState state) {
111 0 : setState(() {
112 0 : organizerState = state;
113 : });
114 : },
115 0 : child: CanvasProvider(
116 0 : selectedStoryRepository: selectedStoryRepository,
117 0 : storyRepository: storyRepository,
118 0 : state: canvasState,
119 0 : onStateChanged: (CanvasState state) {
120 0 : setState(() {
121 0 : canvasState = state;
122 : });
123 : },
124 0 : child: ZoomProvider(
125 0 : state: zoomState,
126 0 : onStateChanged: (ZoomState state) {
127 0 : setState(() {
128 0 : zoomState = state;
129 : });
130 : },
131 0 : child: ThemeProvider(
132 0 : state: themeMode,
133 0 : onStateChanged: (ThemeMode mode) {
134 0 : setState(() {
135 0 : themeMode = mode;
136 : });
137 : },
138 0 : child: DeviceProvider(
139 0 : state: deviceState,
140 0 : onStateChanged: (DeviceState state) {
141 0 : setState(() {
142 0 : deviceState = state;
143 : });
144 : },
145 0 : child: InjectedThemeProvider(
146 0 : state: injectedThemeState,
147 0 : onStateChanged: (InjectedThemeState state) {
148 0 : setState(() {
149 0 : injectedThemeState = state;
150 : });
151 : },
152 0 : child: Builder(builder: (context) {
153 0 : contextWithProviders = context;
154 0 : var canvasState = CanvasProvider.of(context)!.state;
155 0 : var storiesState = OrganizerProvider.of(context)!.state;
156 0 : return MaterialApp.router(
157 0 : routeInformationParser: StoryRouteInformationParser(
158 0 : onRoute: (path) {
159 0 : var stories = StoryHelper.getAllStoriesFromCategories(
160 0 : storiesState.allCategories,
161 : );
162 0 : var selectedStory = selectStoryFromPath(path, stories);
163 0 : CanvasProvider.of(context)!.selectStory(selectedStory);
164 : },
165 : ),
166 0 : routerDelegate: StoryRouterDelegate(
167 : canvasState: canvasState,
168 0 : appInfo: widget.appInfo,
169 : ),
170 0 : title: widget.appInfo.name,
171 : debugShowCheckedModeBanner: false,
172 0 : themeMode: themeMode,
173 0 : darkTheme: Styles.darkTheme,
174 0 : theme: Styles.lightTheme,
175 : );
176 : }),
177 : ),
178 : ),
179 : ),
180 : ),
181 : ),
182 : );
183 : }
184 :
185 0 : Story? selectStoryFromPath(
186 : String? path,
187 : List<Story> stories,
188 : ) {
189 0 : String storyPath = path?.replaceFirst('/stories/', '') ?? '';
190 : Story? story;
191 0 : for (final element in stories) {
192 0 : if (element.path == storyPath) {
193 : story = element;
194 : }
195 : }
196 : return story;
197 : }
198 : }
|