From 8df2680eacbb9877566be9513a8e01889f287620 Mon Sep 17 00:00:00 2001
From: Dani Palou <dani@moodle.com>
Date: Thu, 17 Feb 2022 12:37:59 +0100
Subject: [PATCH] MOBILE-3833 course: Fix refresh course when manual compl
 changes

---
 .../module-completion-legacy.ts               |  7 +--
 .../module-manual-completion.ts               |  8 ++--
 .../course/pages/contents/contents.html       |  3 +-
 .../course/pages/contents/contents.ts         | 48 +++++++++++--------
 src/core/features/course/pages/index/index.ts |  2 +-
 src/core/features/course/services/course.ts   |  5 --
 .../components/course-format/course-format.ts |  3 +-
 src/core/singletons/events.ts                 | 10 ----
 8 files changed, 36 insertions(+), 50 deletions(-)

diff --git a/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts b/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts
index 3f10eefa4..f7c5b55e8 100644
--- a/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts
+++ b/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts
@@ -16,7 +16,6 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
 
 import { CoreUser } from '@features/user/services/user';
 import {
-    CoreCourseCompletionType,
     CoreCourseModuleCompletionStatus,
     CoreCourseModuleCompletionTracking,
 } from '@features/course/services/course';
@@ -52,8 +51,8 @@ export class CoreCourseModuleCompletionLegacyComponent extends CoreCourseModuleC
      * @inheritdoc
      */
     ngOnInit(): void {
-        this.completionObserver = CoreEvents.on(CoreEvents.COMPLETION_CHANGED, (data) => {
-            if (!this.completion || this.completion.cmid != data.completion.cmid || data.type != CoreCourseCompletionType.MANUAL) {
+        this.completionObserver = CoreEvents.on(CoreEvents.MANUAL_COMPLETION_CHANGED, (data) => {
+            if (!this.completion || this.completion.cmid != data.completion.cmid) {
                 return;
             }
 
@@ -149,9 +148,7 @@ export class CoreCourseModuleCompletionLegacyComponent extends CoreCourseModuleC
 
         await CoreCourseHelper.changeManualCompletion(this.completion, event);
 
-        // @deprecated MANUAL_COMPLETION_CHANGED is deprecated since 4.0 use COMPLETION_CHANGED instead.
         CoreEvents.trigger(CoreEvents.MANUAL_COMPLETION_CHANGED, { completion: this.completion });
-        CoreEvents.trigger(CoreEvents.COMPLETION_CHANGED, { completion: this.completion, type: CoreCourseCompletionType.MANUAL });
     }
 
     /**
diff --git a/src/core/features/course/components/module-manual-completion/module-manual-completion.ts b/src/core/features/course/components/module-manual-completion/module-manual-completion.ts
index f2468cdab..5d3c51f4f 100644
--- a/src/core/features/course/components/module-manual-completion/module-manual-completion.ts
+++ b/src/core/features/course/components/module-manual-completion/module-manual-completion.ts
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChange } from '@angular/core';
-import { CoreCourseCompletionMode, CoreCourseCompletionType } from '@features/course/services/course';
+import { CoreCourseCompletionMode } from '@features/course/services/course';
 import { CoreCourseHelper, CoreCourseModuleCompletionData } from '@features/course/services/course-helper';
 import { CoreUser } from '@features/user/services/user';
 import { Translate } from '@singletons';
@@ -41,8 +41,8 @@ export class CoreCourseModuleManualCompletionComponent implements OnInit, OnChan
      * @inheritdoc
      */
     ngOnInit(): void {
-        this.completionObserver = CoreEvents.on(CoreEvents.COMPLETION_CHANGED, (data) => {
-            if (!this.completion || this.completion.cmid != data.completion.cmid || data.type != CoreCourseCompletionType.MANUAL) {
+        this.completionObserver = CoreEvents.on(CoreEvents.MANUAL_COMPLETION_CHANGED, (data) => {
+            if (!this.completion || this.completion.cmid != data.completion.cmid) {
                 return;
             }
 
@@ -102,9 +102,7 @@ export class CoreCourseModuleManualCompletionComponent implements OnInit, OnChan
 
         await CoreCourseHelper.changeManualCompletion(this.completion, event);
 
-        // @deprecated MANUAL_COMPLETION_CHANGED is deprecated since 4.0 use COMPLETION_CHANGED instead.
         CoreEvents.trigger(CoreEvents.MANUAL_COMPLETION_CHANGED, { completion: this.completion });
-        CoreEvents.trigger(CoreEvents.COMPLETION_CHANGED, { completion: this.completion, type: CoreCourseCompletionType.MANUAL });
     }
 
     /**
diff --git a/src/core/features/course/pages/contents/contents.html b/src/core/features/course/pages/contents/contents.html
index b12da3cc6..64ff48a05 100644
--- a/src/core/features/course/pages/contents/contents.html
+++ b/src/core/features/course/pages/contents/contents.html
@@ -7,8 +7,7 @@
 
     <core-loading [hideUntil]="dataLoaded">
         <core-course-format [course]="course" [sections]="sections" [initialSectionId]="sectionId" [initialSectionNumber]="sectionNumber"
-            [moduleId]="moduleId" (completionChanged)="onCompletionChange($event)" class="core-course-format-{{course.format}}"
-            *ngIf="dataLoaded">
+            [moduleId]="moduleId" class="core-course-format-{{course.format}}" *ngIf="dataLoaded">
         </core-course-format>
     </core-loading>
 </ion-content>
diff --git a/src/core/features/course/pages/contents/contents.ts b/src/core/features/course/pages/contents/contents.ts
index 26c407028..77d752743 100644
--- a/src/core/features/course/pages/contents/contents.ts
+++ b/src/core/features/course/pages/contents/contents.ts
@@ -63,6 +63,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
 
     protected formatOptions?: Record<string, unknown>;
     protected completionObserver?: CoreEventObserver;
+    protected manualCompletionObserver?: CoreEventObserver;
     protected syncObserver?: CoreEventObserver;
     protected isDestroyed = false;
     protected modulesHaveCompletion = false;
@@ -114,36 +115,40 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
      * @return Promise resolved when done.
      */
     protected async initListeners(): Promise<void> {
+        if (this.completionObserver) {
+            return; // Already initialized.
+        }
+
         // Check if the course format requires the view to be refreshed when completion changes.
         const shouldRefresh = await CoreCourseFormatDelegate.shouldRefreshWhenCompletionChanges(this.course);
         if (!shouldRefresh) {
             return;
         }
 
-        if (!this.completionObserver) {
-            this.completionObserver = CoreEvents.on(
-                CoreEvents.COMPLETION_MODULE_VIEWED,
-                (data) => {
-                    if (data && data.courseId == this.course.id) {
-                        this.refreshAfterCompletionChange(true);
-                    }
-                },
-            );
-        }
-
-        if (!this.syncObserver) {
-            this.syncObserver = CoreEvents.on(CoreCourseSyncProvider.AUTO_SYNCED, (data) => {
-                if (!data || data.courseId != this.course.id) {
-                    return;
+        this.completionObserver = CoreEvents.on(
+            CoreEvents.COMPLETION_MODULE_VIEWED,
+            (data) => {
+                if (data && data.courseId == this.course.id) {
+                    this.refreshAfterCompletionChange(true);
                 }
+            },
+        );
 
-                this.refreshAfterCompletionChange(false);
+        this.manualCompletionObserver = CoreEvents.on(CoreEvents.MANUAL_COMPLETION_CHANGED, (data) => {
+            this.onCompletionChange(data.completion);
+        });
 
-                if (data.warnings && data.warnings[0]) {
-                    CoreDomUtils.showErrorModal(data.warnings[0]);
-                }
-            });
-        }
+        this.syncObserver = CoreEvents.on(CoreCourseSyncProvider.AUTO_SYNCED, (data) => {
+            if (!data || data.courseId != this.course.id) {
+                return;
+            }
+
+            this.refreshAfterCompletionChange(false);
+
+            if (data.warnings && data.warnings[0]) {
+                CoreDomUtils.showErrorModal(data.warnings[0]);
+            }
+        });
     }
 
     /**
@@ -369,6 +374,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
     ngOnDestroy(): void {
         this.isDestroyed = true;
         this.completionObserver?.off();
+        this.manualCompletionObserver?.off();
         this.syncObserver?.off();
     }
 
diff --git a/src/core/features/course/pages/index/index.ts b/src/core/features/course/pages/index/index.ts
index 9991c008d..56e10b136 100644
--- a/src/core/features/course/pages/index/index.ts
+++ b/src/core/features/course/pages/index/index.ts
@@ -88,7 +88,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
         });
 
         // The completion of any of the modules have changed.
-        this.completionObserver = CoreEvents.on(CoreEvents.COMPLETION_CHANGED, (data) => {
+        this.completionObserver = CoreEvents.on(CoreEvents.MANUAL_COMPLETION_CHANGED, (data) => {
             if (data.completion.courseId != this.course?.id) {
                 return;
             }
diff --git a/src/core/features/course/services/course.ts b/src/core/features/course/services/course.ts
index 5e1496358..55c7fc262 100644
--- a/src/core/features/course/services/course.ts
+++ b/src/core/features/course/services/course.ts
@@ -75,11 +75,6 @@ export enum CoreCourseModuleCompletionStatus {
     COMPLETION_COMPLETE_FAIL = 3,
 }
 
-export enum CoreCourseCompletionType {
-    MANUAL = 0,
-    AUTO = 1,
-}
-
 export enum CoreCourseCompletionMode {
     FULL = 'full',
     BASIC = 'basic',
diff --git a/src/core/features/siteplugins/components/course-format/course-format.ts b/src/core/features/siteplugins/components/course-format/course-format.ts
index 3f87875e8..d2bc5c401 100644
--- a/src/core/features/siteplugins/components/course-format/course-format.ts
+++ b/src/core/features/siteplugins/components/course-format/course-format.ts
@@ -37,7 +37,8 @@ export class CoreSitePluginsCourseFormatComponent implements OnChanges {
     @Input() initialSectionId?: number; // The section to load first (by ID).
     @Input() initialSectionNumber?: number; // The section to load first (by number).
     @Input() moduleId?: number; // The module ID to scroll to. Must be inside the initial selected section.
-    @Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>(); // Notify when any module completion changes.
+    // Notify when any module completion changes. @deprecated since 4.0, now we use CoreEvents.
+    @Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>();
 
     // Special input, allows access to the parent instance properties and methods.
     // Please notice that all the other inputs/outputs are also accessible through this instance, so they could be removed.
diff --git a/src/core/singletons/events.ts b/src/core/singletons/events.ts
index 84b8522d3..57d112fd8 100644
--- a/src/core/singletons/events.ts
+++ b/src/core/singletons/events.ts
@@ -20,7 +20,6 @@ import { CoreFilepoolComponentFileEventData } from '@services/filepool';
 import { CoreRedirectPayload } from '@services/navigator';
 import { CoreCourseModuleCompletionData } from '@features/course/services/course-helper';
 import { CoreScreenOrientation } from '@services/screen';
-import { CoreCourseCompletionType } from '@features/course/services/course';
 
 /**
  * Observer instance to stop listening to an event.
@@ -51,7 +50,6 @@ export interface CoreEventsData {
     [CoreEvents.SELECT_COURSE_TAB]: CoreEventSelectCourseTabData;
     [CoreEvents.COMPLETION_MODULE_VIEWED]: CoreEventCompletionModuleViewedData;
     [CoreEvents.MANUAL_COMPLETION_CHANGED]: CoreEventManualCompletionChangedData;
-    [CoreEvents.COMPLETION_CHANGED]: CoreEventCompletionChangedData;
     [CoreEvents.SECTION_STATUS_CHANGED]: CoreEventSectionStatusChangedData;
     [CoreEvents.ACTIVITY_DATA_SENT]: CoreEventActivityDataSentData;
     [CoreEvents.IAB_LOAD_START]: InAppBrowserEvent;
@@ -371,14 +369,6 @@ export type CoreEventManualCompletionChangedData = {
     completion: CoreCourseModuleCompletionData;
 };
 
-/**
- * Data passed to COMPLETION_CHANGED event.
- */
-export type CoreEventCompletionChangedData = {
-    completion: CoreCourseModuleCompletionData;
-    type: CoreCourseCompletionType;
-};
-
 /**
  * Data passed to SECTION_STATUS_CHANGED event.
  */