1
+ import 'dart:async' ;
2
+
1
3
import 'package:bloc/bloc.dart' ;
2
4
import 'package:core/core.dart' ;
3
5
import 'package:data_repository/data_repository.dart' ;
@@ -15,9 +17,18 @@ class ArchivedHeadlinesBloc
15
17
on < LoadArchivedHeadlinesRequested > (_onLoadArchivedHeadlinesRequested);
16
18
on < RestoreHeadlineRequested > (_onRestoreHeadlineRequested);
17
19
on < DeleteHeadlineForeverRequested > (_onDeleteHeadlineForeverRequested);
20
+ on < UndoDeleteHeadlineRequested > (_onUndoDeleteHeadlineRequested);
21
+ on < _ConfirmDeleteHeadlineRequested > (_onConfirmDeleteHeadlineRequested);
18
22
}
19
23
20
24
final DataRepository <Headline > _headlinesRepository;
25
+ Timer ? _deleteTimer;
26
+
27
+ @override
28
+ Future <void > close () {
29
+ _deleteTimer? .cancel ();
30
+ return super .close ();
31
+ }
21
32
22
33
Future <void > _onLoadArchivedHeadlinesRequested (
23
34
LoadArchivedHeadlinesRequested event,
@@ -96,22 +107,83 @@ class ArchivedHeadlinesBloc
96
107
DeleteHeadlineForeverRequested event,
97
108
Emitter <ArchivedHeadlinesState > emit,
98
109
) async {
99
- final originalHeadlines = List <Headline >.from (state.headlines);
100
- final headlineIndex = originalHeadlines.indexWhere ((h) => h.id == event.id);
110
+ _deleteTimer? .cancel ();
111
+
112
+ final headlineIndex = state.headlines.indexWhere ((h) => h.id == event.id);
101
113
if (headlineIndex == - 1 ) return ;
102
114
103
- final updatedHeadlines = originalHeadlines..removeAt (headlineIndex);
104
- emit (state.copyWith (headlines: updatedHeadlines));
115
+ final headlineToDelete = state.headlines[headlineIndex];
116
+ final updatedHeadlines = List <Headline >.from (state.headlines)
117
+ ..removeAt (headlineIndex);
118
+
119
+ emit (
120
+ state.copyWith (
121
+ headlines: updatedHeadlines,
122
+ lastDeletedHeadline: headlineToDelete,
123
+ ),
124
+ );
125
+
126
+ _deleteTimer = Timer (
127
+ const Duration (seconds: 5 ),
128
+ () => add (_ConfirmDeleteHeadlineRequested (event.id)),
129
+ );
130
+ }
105
131
132
+ Future <void > _onConfirmDeleteHeadlineRequested (
133
+ _ConfirmDeleteHeadlineRequested event,
134
+ Emitter <ArchivedHeadlinesState > emit,
135
+ ) async {
106
136
try {
107
137
await _headlinesRepository.delete (id: event.id);
138
+ emit (state.copyWith (lastDeletedHeadline: null ));
108
139
} on HttpException catch (e) {
109
- emit (state.copyWith (headlines: originalHeadlines, exception: e));
140
+ // If deletion fails, restore the headline to the list
141
+ final originalHeadlines = List <Headline >.from (state.headlines)
142
+ ..add (state.lastDeletedHeadline! );
143
+ emit (
144
+ state.copyWith (
145
+ headlines: originalHeadlines,
146
+ exception: e,
147
+ lastDeletedHeadline: null ,
148
+ ),
149
+ );
110
150
} catch (e) {
151
+ final originalHeadlines = List <Headline >.from (state.headlines)
152
+ ..add (state.lastDeletedHeadline! );
111
153
emit (
112
154
state.copyWith (
113
155
headlines: originalHeadlines,
114
156
exception: UnknownException ('An unexpected error occurred: $e ' ),
157
+ lastDeletedHeadline: null ,
158
+ ),
159
+ );
160
+ }
161
+ }
162
+
163
+ void _onUndoDeleteHeadlineRequested (
164
+ UndoDeleteHeadlineRequested event,
165
+ Emitter <ArchivedHeadlinesState > emit,
166
+ ) {
167
+ _deleteTimer? .cancel ();
168
+ if (state.lastDeletedHeadline != null ) {
169
+ final updatedHeadlines = List <Headline >.from (state.headlines)
170
+ ..insert (
171
+ state.headlines.indexWhere (
172
+ (h) =>
173
+ h.updatedAt.isBefore (state.lastDeletedHeadline! .updatedAt),
174
+ ) !=
175
+ - 1
176
+ ? state.headlines.indexWhere (
177
+ (h) =>
178
+ h.updatedAt.isBefore (state.lastDeletedHeadline! .updatedAt),
179
+ )
180
+ : state.headlines.length,
181
+ state.lastDeletedHeadline! ,
182
+ );
183
+ emit (
184
+ state.copyWith (
185
+ headlines: updatedHeadlines,
186
+ lastDeletedHeadline: null ,
115
187
),
116
188
);
117
189
}
0 commit comments