Skip to content

Commit

Permalink
fix(spoiler): keep collapse state in document
Browse files Browse the repository at this point in the history
This commit allows to save and load spoiler card collapse state in delta
document. A new field `collapsed` indicates the spoiler area is
collapsed or not. Fixed the spoiler collapse state not persist when
rebuilds where user added new line above the spoiler card.

The new field `collapsed` is optional to keep compatible with documents
generated by former versions. Default value is `true`.
  • Loading branch information
realth000 committed Dec 17, 2024
1 parent 1e41afc commit 61244ca
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 4 deletions.
11 changes: 9 additions & 2 deletions lib/src/tags/spoiler/spoiler_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class _SpoilerCardState extends State<_SpoilerCard> {
late BBCodeSpoilerInfo data;

/// Flag indicating body is visible or not.
bool _visible = false;
late bool _visible;

Future<void> editSpoiler() async {
final data = await Navigator.push<BBCodeSpoilerInfo>(
Expand All @@ -198,7 +198,8 @@ class _SpoilerCardState extends State<_SpoilerCard> {
);
if (data != null) {
setState(() {
this.data = data;
// Keep collapsed state.
this.data = data.copyWith(collapsed: !_visible);
bodyController.setDocumentFromJson(
jsonDecode(data.body) as List<dynamic>,
);
Expand Down Expand Up @@ -315,6 +316,8 @@ class _SpoilerCardState extends State<_SpoilerCard> {
});
});
}
// Restore the spoiler body visibility.
_visible = !data.collapsed;
}

@override
Expand Down Expand Up @@ -350,9 +353,12 @@ class _SpoilerCardState extends State<_SpoilerCard> {
: const Icon(Icons.expand_more_outlined),
label: Text(data.title),
onPressed: () {
widget.onTap.call();
setState(() {
_visible = !_visible;
});
data = data.copyWith(collapsed: !_visible);
widget.onEdited(data);
},
),
if (_visible) ...[
Expand Down Expand Up @@ -459,6 +465,7 @@ class _SpoilerEditPageState extends State<_SpoilerEditPage> {
BBCodeSpoilerInfo(
title: titleController.text,
body: bodyController.toQuillDelta(),
collapsed: widget.initialData?.collapsed ?? true,
),
),
),
Expand Down
36 changes: 34 additions & 2 deletions lib/src/tags/spoiler/spoiler_embed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ final class BBCodeSpoilerInfo {
const BBCodeSpoilerInfo({
required this.title,
required this.body,
required this.collapsed,
});

/// Construct from [json] string.
Expand All @@ -38,10 +39,15 @@ final class BBCodeSpoilerInfo {
{BBCodeSpoilerKeys.body: final String data} => data,
_ => throw Exception('bbcode spoiler body not found'),
};
final collapsed = switch (data) {
{BBCodeSpoilerKeys.collapsed: final bool data} => data,
_ => true,
};

return BBCodeSpoilerInfo(
title: title,
body: body,
collapsed: collapsed,
);
}

Expand All @@ -52,7 +58,7 @@ final class BBCodeSpoilerInfo {
/// The [title] should be constructed according to current locale and built to
/// be a default value, usually injected with l10n on build context.
factory BBCodeSpoilerInfo.buildEmpty(String title) =>
BBCodeSpoilerInfo(title: title, body: '');
BBCodeSpoilerInfo(title: title, body: '', collapsed: true);

/// Parse a current type [embed] and add bbcode to [out].
static void toBBCode(Embed embed, StringSink out) {
Expand All @@ -68,13 +74,39 @@ final class BBCodeSpoilerInfo {
/// Raw bbcode body in the spoiler area
final String body;

/// Spoiler is collapsed or not
///
/// Only a flag indicating should expand the spoiler card or not when
/// rendering into an editor. Not be into the generated bbcode.
///
/// This field is optional, meaning it's a field added later in release, make
/// it optional to keep compatible with old version documents.
///
/// Default value is true.
final bool collapsed;

/// Convert to json map string.
String toJson() => jsonEncode(<String, dynamic>{
BBCodeSpoilerKeys.title: title,
BBCodeSpoilerKeys.body: body,
BBCodeSpoilerKeys.collapsed: collapsed,
});

/// The copy with method.
BBCodeSpoilerInfo copyWith({
String? title,
String? body,
bool? collapsed,
}) {
return BBCodeSpoilerInfo(
title: title ?? this.title,
body: body ?? this.body,
collapsed: collapsed ?? this.collapsed,
);
}

@override
String toString() => '${BBCodeSpoilerKeys.title}=$title, '
'${BBCodeSpoilerKeys.body}=$body';
'${BBCodeSpoilerKeys.body}=$body, '
'${BBCodeSpoilerKeys.collapsed}=$collapsed';
}
3 changes: 3 additions & 0 deletions lib/src/tags/spoiler/spoiler_keys.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ final class BBCodeSpoilerKeys {

/// Raw bbcode body inside the spoiler block.
static const String body = 'data';

/// Spoiler should be rendered in collapsed state or not.
static const String collapsed = 'collapsed';
}

0 comments on commit 61244ca

Please sign in to comment.