11import 'package:flutter/material.dart' ;
22import 'package:flutter_bloc/flutter_bloc.dart' ;
3- import 'package:flutter_star/flutter_star.dart' ;
43import 'package:flutter_unit/app/blocs/global/global_bloc.dart' ;
54import 'package:flutter_unit/app/blocs/global/global_state.dart' ;
65import 'package:flutter_unit/app/res/cons.dart' ;
6+ import 'package:flutter_unit/app/res/style/unit_text_style.dart' ;
77import 'package:flutter_unit/app/res/toly_icon.dart' ;
88import 'package:flutter_unit/app/utils/Toast.dart' ;
9+ import 'package:flutter_unit/components/permanent/code/highlighter_style.dart' ;
910import 'package:flutter_unit/components/permanent/feedback_widget.dart' ;
10- import 'package:flutter_unit/components/permanent/panel.dart' ;
1111import 'package:flutter_unit/components/project/widget_node_panel.dart' ;
1212import 'package:flutter_unit/widget_system/blocs/widget_system_bloc.dart' ;
1313import 'package:flutter_unit/widget_system/repositories/model/node_model.dart' ;
1414import 'package:flutter_unit/widget_system/repositories/model/widget_model.dart' ;
1515
1616import '../../widgets/widgets_map.dart' ;
1717import 'category_end_drawer.dart' ;
18+ import 'widget_detail_panel.dart' ;
1819
1920class WidgetDetailPage extends StatefulWidget {
2021 final WidgetModel model;
@@ -40,39 +41,62 @@ class _WidgetDetailPageState extends State<WidgetDetailPage> {
4041
4142 @override
4243 Widget build (BuildContext context) {
43- return Scaffold (
44- endDrawer: CategoryEndDrawer (widget: _modelStack.last),
45- appBar: AppBar (
46- title: Text (_modelStack.last.name),
47- leading: const BackButton (),
48- actions: < Widget > [
49- _buildToHome (),
50- FeedbackWidget (
51- onPressed: () => _toggleLikeState (context),
52- child: BlocConsumer <LikeWidgetBloc , LikeWidgetState >(
53- listener: _listenLikeStateChange,
54- builder: _buildByLikeState,
55- ),
56- )
57- ],
44+ return BlocBuilder <WidgetDetailBloc , DetailState >(
45+ builder: (_, state) => Scaffold (
46+ endDrawer: CategoryEndDrawer (widget: currentWidgetModel),
47+ appBar: AppBar (
48+ title: Text (currentWidgetModel.name),
49+ leading: const BackButton (),
50+ actions: < Widget > [
51+ _buildToHome (),
52+ FeedbackWidget (
53+ onPressed: () => _toggleLikeState (context),
54+ child: BlocConsumer <LikeWidgetBloc , LikeWidgetState >(
55+ listener: _listenLikeStateChange,
56+ builder: _buildByLikeState,
57+ ),
58+ )
59+ ],
60+ ),
61+ body: Builder (builder: (ctx) {
62+ return _buildContent (ctx, state);
63+ }),
5864 ),
59- body: Builder (builder: _buildContent),
6065 );
6166 }
6267
63- Widget _buildContent (BuildContext context) => WillPopScope (
64- onWillPop: () => _whenPop (context),
65- child: SingleChildScrollView (
66- child: Column (
67- crossAxisAlignment: CrossAxisAlignment .start,
68- children: < Widget > [
69- WidgetDetailTitle (
70- model: _modelStack.last,
68+ Widget get linkText => Row (
69+ children: const [
70+ Padding (
71+ padding: EdgeInsets .only (left: 15 , right: 5 ),
72+ child: Icon (Icons .link, color: Colors .blue),
73+ ),
74+ Text ('相关组件' , style: TStyleUnit .labelBold),
75+ ],
76+ );
77+
78+ Widget _buildContent (BuildContext context, DetailState state) {
79+ return WillPopScope (
80+ onWillPop: () => _whenPop (context),
81+ child: CustomScrollView (
82+ slivers: [
83+ SliverToBoxAdapter (
84+ child: Column (
85+ crossAxisAlignment: CrossAxisAlignment .start,
86+ children: [
87+ WidgetDetailPanel (model: _modelStack.last),
88+ linkText,
89+ if (state is DetailWithData )
90+ _buildLinkTo (context, state.links),
91+ const Divider (),
92+ ],
93+ ),
7194 ),
72- BlocBuilder <WidgetDetailBloc , DetailState >(builder: _buildDetail)
95+ if (state is DetailWithData )
96+ _buildSliverNodeList (state.nodes, state.widgetModel.name)
7397 ],
74- ),
75- ));
98+ ));
99+ }
76100
77101 Widget _buildToHome () => Builder (
78102 builder: (ctx) => GestureDetector (
@@ -117,66 +141,24 @@ class _WidgetDetailPageState extends State<WidgetDetailPage> {
117141
118142
119143 void _toggleLikeState (BuildContext context) {
120- BlocProvider .of <LikeWidgetBloc >(context)
121- .add (ToggleLikeWidgetEvent (id: currentWidgetModel.id));
122- }
123-
124- Widget _buildNodes (List <NodeModel > nodes, String name) {
125- GlobalState globalState = BlocProvider .of <GlobalBloc >(context).state;
126- return Column (
127- children: nodes
128- .asMap ()
129- .keys
130- .map ((i) => WidgetNodePanel (
131- codeStyle: Cons .codeThemeSupport.keys.toList ()[globalState.codeStyleIndex],
132- codeFamily: 'Inconsolata' ,
133- text: nodes[i].name,
134- subText: nodes[i].subtitle,
135- code: nodes[i].code,
136- show: WidgetsMap .map (name)[i],
137- ))
138- .toList ());
144+ BlocProvider .of <LikeWidgetBloc >(context).add (
145+ ToggleLikeWidgetEvent (id: currentWidgetModel.id),
146+ );
139147 }
140148
141149 Future <bool > _whenPop (BuildContext context) async {
142150 if (Scaffold .of (context).isEndDrawerOpen) return true ;
143151 _modelStack.removeLast ();
144152 if (_modelStack.isNotEmpty) {
145- setState (() {
146- BlocProvider . of < WidgetDetailBloc >(context). add ( FetchWidgetDetail (_modelStack.last));
147- } );
153+ BlocProvider . of < WidgetDetailBloc >(context). add (
154+ FetchWidgetDetail (currentWidgetModel),
155+ );
148156 return false ;
149157 } else {
150158 return true ;
151159 }
152160 }
153161
154- Widget _buildDetail (BuildContext context, DetailState state) {
155- if (state is DetailWithData ) {
156- return Column (
157- crossAxisAlignment: CrossAxisAlignment .start,
158- children: [
159- Row (
160- children: const [
161- Padding (
162- padding: EdgeInsets .only (left: 15 , right: 5 ),
163- child: Icon (Icons .link, color: Colors .blue),
164- ),
165- Text (
166- '相关组件' ,
167- style: TextStyle (fontWeight: FontWeight .bold, fontSize: 16 ),
168- ),
169- ],
170- ),
171- _buildLinkTo (context, state.links),
172- const Divider (),
173- _buildNodes (state.nodes, state.widgetModel.name)
174- ],
175- );
176- }
177- return Container ();
178- }
179-
180162 Color ? get chipColor => isDark
181163 ? Theme .of (context).floatingActionButtonTheme.backgroundColor
182164 : Theme .of (context).primaryColor;
@@ -196,103 +178,43 @@ class _WidgetDetailPageState extends State<WidgetDetailPage> {
196178 child: Wrap (
197179 spacing: 5 ,
198180 children: links
199- .map ((e) => ActionChip (
200- onPressed: () {
201- BlocProvider .of <WidgetDetailBloc >(context)
202- .add (FetchWidgetDetail (e));
203- setState (() {
204- _modelStack.add (e);
205- });
206- },
181+ .map ((WidgetModel model) => ActionChip (
182+ onPressed: () => _toLinkWidget (model),
207183 elevation: 2 ,
208184 shadowColor: chipColor,
209185 backgroundColor: chipColor,
210- labelStyle: TextStyle (
211- fontSize: 12 ,
212- color: Colors .white,
213- decoration: (e.deprecated)
214- ? TextDecoration .lineThrough
215- : TextDecoration .none,
216- decorationThickness: 2 ,
217- ),
218- label: Text (e.name),
186+ labelStyle: model.deprecated
187+ ? TStyleUnit .deprecatedChip
188+ : TStyleUnit .commonChip,
189+ label: Text (model.name),
219190 ))
220191 .toList (),
221192 ),
222193 );
223194 }
224195 }
225- }
226-
227- class WidgetDetailTitle extends StatelessWidget {
228- final WidgetModel model;
229196
230- const WidgetDetailTitle ({Key ? key, required this .model}) : super (key: key);
231-
232- @override
233- Widget build (BuildContext context) {
234- return Column (
235- crossAxisAlignment: CrossAxisAlignment .start,
236- children: < Widget > [
237- Row (
238- children: < Widget > [
239- _buildLeft (model, context),
240- _buildRight (model),
241- ],
242- ),
243- const Divider (),
244- ],
245- );
197+ void _toLinkWidget (WidgetModel model) {
198+ BlocProvider .of <WidgetDetailBloc >(context).add (FetchWidgetDetail (model));
199+ _modelStack.add (model);
246200 }
247201
248- Widget _buildLeft (WidgetModel model, BuildContext context) => Expanded (
249- child: Column (
250- crossAxisAlignment: CrossAxisAlignment .start,
251- children: < Widget > [
252- Padding (
253- padding: const EdgeInsets .only (top: 20.0 , left: 20 ),
254- child: Text (
255- model.nameCN,
256- style: TextStyle (
257- fontSize: 20 ,
258- decoration: (model.deprecated)
259- ? TextDecoration .lineThrough
260- : TextDecoration .none,
261- decorationThickness: 2 ,
262- color: const Color (0xff1EBBFD ),
263- fontWeight: FontWeight .bold),
264- ),
265- ),
266- Padding (
267- padding: const EdgeInsets .all (8.0 ),
268- child: Panel (
269- color: Theme .of (context).appBarTheme.backgroundColor,
270- child: Text (model.info)),
271- )
272- ],
273- ),
274- );
275-
276- Widget _buildRight (WidgetModel model) => Column (
277- mainAxisSize: MainAxisSize .min,
278- children: < Widget > [
279- SizedBox (
280- height: 100 ,
281- child: Padding (
282- padding: const EdgeInsets .all (8.0 ),
283- child: Hero (
284- tag: "hero_widget_image_${model .id }" ,
285- child: ClipRRect (
286- borderRadius: const BorderRadius .all (Radius .circular (8 )),
287- child: model.image == null
288- ? Image .asset ('assets/images/caver.webp' )
289- : Image (image: model.image! ))),
290- ),
291- ),
292- StarScore (
293- score: model.lever,
294- star: const Star (size: 15 , fillColor: Colors .blue),
295- )
296- ],
297- );
202+ Widget _buildSliverNodeList (List <NodeModel > nodes, String name) {
203+ GlobalState globalState = BlocProvider .of <GlobalBloc >(context).state;
204+ HighlighterStyle codeStyle =
205+ Cons .codeThemeSupport.keys.toList ()[globalState.codeStyleIndex];
206+ return SliverList (
207+ delegate: SliverChildBuilderDelegate (
208+ (_, i) => WidgetNodePanel (
209+ codeStyle: codeStyle,
210+ codeFamily: 'Inconsolata' ,
211+ text: nodes[i].name,
212+ subText: nodes[i].subtitle,
213+ code: nodes[i].code,
214+ show: WidgetsMap .map (name)[i],
215+ ),
216+ childCount: nodes.length,
217+ ));
218+ }
298219}
220+
0 commit comments