@@ -528,16 +528,29 @@ class ListNodeWidget extends StatelessWidget {
528
528
}
529
529
}
530
530
531
- class Spoiler extends StatefulWidget {
532
- const Spoiler ({super .key, required this .node});
531
+ class Modal extends StatefulWidget {
532
+ const Modal ({
533
+ super .key,
534
+ required this .header,
535
+ required this .content,
536
+ required this .borderColor,
537
+ required this .expandIconColor,
538
+ this .bgColor,
539
+ this .textColor,
540
+ });
533
541
534
- final SpoilerNode node;
542
+ final List <BlockContentNode > header;
543
+ final List <BlockContentNode > content;
544
+ final Color borderColor;
545
+ final Color expandIconColor;
546
+ final Color ? bgColor;
547
+ final Color ? textColor;
535
548
536
549
@override
537
- State <Spoiler > createState () => _SpoilerState ();
550
+ State <Modal > createState () => _ModalState ();
538
551
}
539
552
540
- class _SpoilerState extends State <Spoiler > with TickerProviderStateMixin {
553
+ class _ModalState extends State <Modal > with TickerProviderStateMixin {
541
554
bool expanded = false ;
542
555
543
556
late final AnimationController _controller = AnimationController (
@@ -565,56 +578,73 @@ class _SpoilerState extends State<Spoiler> with TickerProviderStateMixin {
565
578
566
579
@override
567
580
Widget build (BuildContext context) {
568
- final zulipLocalizations = ZulipLocalizations .of (context);
569
- final header = widget.node.header;
570
- final effectiveHeader = header.isNotEmpty
571
- ? header
572
- : [ParagraphNode (links: null ,
573
- nodes: [TextNode (zulipLocalizations.spoilerDefaultHeaderText)])];
574
581
return Padding (
575
582
padding: const EdgeInsets .fromLTRB (0 , 5 , 0 , 15 ),
576
583
child: DecoratedBox (
577
584
decoration: BoxDecoration (
578
- // Web has the same color in light and dark mode.
579
- border : Border . all ( color: const Color ( 0xff808080 )) ,
585
+ border : Border . all ( color: widget.borderColor),
586
+ color: widget.bgColor ,
580
587
borderRadius: BorderRadius .circular (10 ),
581
588
),
582
- child: Padding (padding: const EdgeInsetsDirectional .fromSTEB (10 , 2 , 8 , 2 ),
583
- child: Column (
584
- children: [
585
- GestureDetector (
586
- behavior: HitTestBehavior .translucent,
587
- onTap: _handleTap,
588
- child: Padding (
589
- padding: const EdgeInsets .all (5 ),
590
- child: Row (crossAxisAlignment: CrossAxisAlignment .end, children: [
591
- Expanded (
592
- child: DefaultTextStyle .merge (
593
- style: weightVariableTextStyle (context, wght: 700 ),
594
- child: BlockContentList (
595
- nodes: effectiveHeader))),
596
- RotationTransition (
597
- turns: _animation.drive (Tween (begin: 0 , end: 0.5 )),
598
- // Web has the same color in light and dark mode.
599
- child: const Icon (color: Color (0xffd4d4d4 ), size: 25 ,
600
- Icons .expand_more)),
601
- ]))),
602
- FadeTransition (
603
- opacity: _animation,
604
- child: const SizedBox (height: 0 , width: double .infinity,
605
- child: DecoratedBox (
606
- decoration: BoxDecoration (
607
- border: Border (
608
- // Web has the same color in light and dark mode.
609
- bottom: BorderSide (width: 1 , color: Color (0xff808080 ))))))),
610
- SizeTransition (
611
- sizeFactor: _animation,
612
- axis: Axis .vertical,
613
- axisAlignment: - 1 ,
614
- child: Padding (
615
- padding: const EdgeInsets .all (5 ),
616
- child: BlockContentList (nodes: widget.node.content))),
617
- ]))));
589
+ child: DefaultTextStyle .merge (
590
+ style: TextStyle (color: widget.textColor),
591
+ child: Padding (padding: const EdgeInsetsDirectional .fromSTEB (10 , 2 , 8 , 2 ),
592
+ child: Column (
593
+ children: [
594
+ GestureDetector (
595
+ behavior: HitTestBehavior .translucent,
596
+ onTap: _handleTap,
597
+ child: Padding (
598
+ padding: const EdgeInsets .all (5 ),
599
+ child: Row (crossAxisAlignment: CrossAxisAlignment .end, children: [
600
+ Expanded (
601
+ child: DefaultTextStyle .merge (
602
+ style: weightVariableTextStyle (context, wght: 700 ),
603
+ child: BlockContentList (
604
+ nodes: widget.header))),
605
+ RotationTransition (
606
+ turns: _animation.drive (Tween (begin: 0 , end: 0.5 )),
607
+ child: Icon (color: widget.expandIconColor, size: 25 ,
608
+ Icons .expand_more)),
609
+ ]))),
610
+ FadeTransition (
611
+ opacity: _animation,
612
+ child: SizedBox (height: 0 , width: double .infinity,
613
+ child: DecoratedBox (
614
+ decoration: BoxDecoration (
615
+ border: Border (
616
+ bottom: BorderSide (width: 1 , color: widget.borderColor)))))),
617
+ SizeTransition (
618
+ sizeFactor: _animation,
619
+ axis: Axis .vertical,
620
+ axisAlignment: - 1 ,
621
+ child: Padding (
622
+ padding: const EdgeInsets .all (5 ),
623
+ child: BlockContentList (nodes: widget.content))),
624
+ ])),
625
+ )));
626
+ }
627
+ }
628
+
629
+ class Spoiler extends StatelessWidget {
630
+ const Spoiler ({super .key, required this .node});
631
+
632
+ final SpoilerNode node;
633
+
634
+ @override
635
+ Widget build (BuildContext context) {
636
+ final zulipLocalizations = ZulipLocalizations .of (context);
637
+ final header = node.header;
638
+ final effectiveHeader = header.isNotEmpty
639
+ ? header
640
+ : [ParagraphNode (links: null ,
641
+ nodes: [TextNode (zulipLocalizations.spoilerDefaultHeaderText)])];
642
+ return Modal (
643
+ header: effectiveHeader,
644
+ content: node.content,
645
+ borderColor: const Color (0xff808080 ), // Web has the same color in light and dark mode.
646
+ expandIconColor: const Color (0xffd4d4d4 ), // Web has the same color in light and dark mode.
647
+ );
618
648
}
619
649
}
620
650
0 commit comments