Skip to content

Commit 96a793c

Browse files
committed
spoiler: abstract spoiler widget as modal
1 parent 7e60c74 commit 96a793c

File tree

1 file changed

+79
-49
lines changed

1 file changed

+79
-49
lines changed

lib/widgets/content.dart

Lines changed: 79 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -528,16 +528,29 @@ class ListNodeWidget extends StatelessWidget {
528528
}
529529
}
530530

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+
});
533541

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;
535548

536549
@override
537-
State<Spoiler> createState() => _SpoilerState();
550+
State<Modal> createState() => _ModalState();
538551
}
539552

540-
class _SpoilerState extends State<Spoiler> with TickerProviderStateMixin {
553+
class _ModalState extends State<Modal> with TickerProviderStateMixin {
541554
bool expanded = false;
542555

543556
late final AnimationController _controller = AnimationController(
@@ -565,56 +578,73 @@ class _SpoilerState extends State<Spoiler> with TickerProviderStateMixin {
565578

566579
@override
567580
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)])];
574581
return Padding(
575582
padding: const EdgeInsets.fromLTRB(0, 5, 0, 15),
576583
child: DecoratedBox(
577584
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,
580587
borderRadius: BorderRadius.circular(10),
581588
),
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+
);
618648
}
619649
}
620650

0 commit comments

Comments
 (0)