From 0425ea8ab8511ba45a1b7272e9d6bc53c8b11b35 Mon Sep 17 00:00:00 2001
From: Inex Code <inex.code@selfprivacy.org>
Date: Mon, 19 Sep 2022 03:42:00 +0300
Subject: [PATCH] Add a button to remove all removable server jobs

---
 .../cubit/server_jobs/server_jobs_cubit.dart  | 43 ++++++++-----------
 .../cubit/server_jobs/server_jobs_state.dart  |  8 +++-
 .../components/jobs_content/jobs_content.dart | 23 ++++++++--
 3 files changed, 45 insertions(+), 29 deletions(-)

diff --git a/lib/logic/cubit/server_jobs/server_jobs_cubit.dart b/lib/logic/cubit/server_jobs/server_jobs_cubit.dart
index 43b2b2d5..1e808956 100644
--- a/lib/logic/cubit/server_jobs/server_jobs_cubit.dart
+++ b/lib/logic/cubit/server_jobs/server_jobs_cubit.dart
@@ -72,42 +72,35 @@ class ServerJobsCubit
     return job;
   }
 
-  /// Get the job object and change its isHidden to true.
-  /// Emit the new state.
-  /// Call the api to remove the job.
-  /// If the api call fails, change the isHidden to false and emit the new state.
-  /// If the api call succeeds, remove the job from the list and emit the new state.
   Future<void> removeServerJob(final String uid) async {
-    final ServerJob? job = getServerJobByUid(uid);
-    if (job == null) {
-      return;
-    }
-
-    job.isHidden = true;
-    emit(
-      ServerJobsState(
-        serverJobList: state.serverJobList,
-      ),
-    );
-
     final result = await api.removeApiJob(uid);
     if (!result.success) {
-      job.isHidden = false;
-      emit(
-        ServerJobsState(
-          serverJobList: state.serverJobList,
-        ),
-      );
       getIt<NavigationService>().showSnackBar(result.message!);
       return;
     }
 
-    state.serverJobList.remove(job);
     emit(
       ServerJobsState(
-        serverJobList: state.serverJobList,
+        serverJobList: [
+          for (final ServerJob job in state.serverJobList)
+            if (job.uid != uid) job
+        ],
       ),
     );
+    print('removed job $uid');
+  }
+
+  Future<void> removeAllFinishedJobs() async {
+    final List<ServerJob> finishedJobs = state.serverJobList
+        .where(
+          (final ServerJob job) =>
+              job.status == JobStatusEnum.finished ||
+              job.status == JobStatusEnum.error,
+        )
+        .toList();
+    for (final ServerJob job in finishedJobs) {
+      await removeServerJob(job.uid);
+    }
   }
 
   Future<void> reload({final bool useTimer = false}) async {
diff --git a/lib/logic/cubit/server_jobs/server_jobs_state.dart b/lib/logic/cubit/server_jobs/server_jobs_state.dart
index cf9cb8e0..2acc487c 100644
--- a/lib/logic/cubit/server_jobs/server_jobs_state.dart
+++ b/lib/logic/cubit/server_jobs/server_jobs_state.dart
@@ -17,8 +17,14 @@ class ServerJobsState extends ServerInstallationDependendState {
     return list;
   }
 
+  bool get hasRemovableJobs => serverJobList.any(
+        (final job) =>
+            job.status == JobStatusEnum.finished ||
+            job.status == JobStatusEnum.error,
+      );
+
   @override
-  List<Object?> get props => [migrationJobUid, ..._serverJobList];
+  List<Object?> get props => [migrationJobUid, _serverJobList];
 
   ServerJobsState copyWith({
     final List<ServerJob>? serverJobList,
diff --git a/lib/ui/components/jobs_content/jobs_content.dart b/lib/ui/components/jobs_content/jobs_content.dart
index d43a194c..877770dc 100644
--- a/lib/ui/components/jobs_content/jobs_content.dart
+++ b/lib/ui/components/jobs_content/jobs_content.dart
@@ -23,6 +23,9 @@ class JobsContent extends StatelessWidget {
     final List<ServerJob> serverJobs =
         context.watch<ServerJobsCubit>().state.serverJobList;
 
+    final bool hasRemovableJobs =
+        context.watch<ServerJobsCubit>().state.hasRemovableJobs;
+
     return BlocBuilder<JobsCubit, JobsState>(
       builder: (final context, final state) {
         late List<Widget> widgets;
@@ -129,9 +132,23 @@ class JobsContent extends StatelessWidget {
             if (serverJobs.isNotEmpty)
               Padding(
                 padding: const EdgeInsets.all(8.0),
-                child: Text(
-                  'jobs.server_jobs'.tr(),
-                  style: Theme.of(context).textTheme.titleMedium,
+                child: Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  children: [
+                    Text(
+                      'jobs.server_jobs'.tr(),
+                      style: Theme.of(context).textTheme.titleMedium,
+                    ),
+                    IconButton(
+                      onPressed: hasRemovableJobs
+                          ? () => context
+                              .read<ServerJobsCubit>()
+                              .removeAllFinishedJobs()
+                          : null,
+                      icon: const Icon(Icons.clear_all),
+                      color: Theme.of(context).colorScheme.onBackground,
+                    ),
+                  ],
                 ),
               ),
             ...serverJobs.map(