From 973bc5fcb3294b3e5b1ae1b7770186e9905ac7b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= <crazyserver@gmail.com>
Date: Mon, 5 Nov 2018 12:16:35 +0100
Subject: [PATCH 1/3] MOBILE-2688 courses: Add options menu

---
 .../components/myoverview/myoverview.ts       |  6 ++
 src/assets/lang/en.json                       |  2 +
 .../courses/components/components.module.ts   | 10 ++-
 .../core-courses-course-options-menu.html     | 13 ++++
 .../course-options-menu.ts                    | 51 +++++++++++++++
 .../core-courses-course-progress.html         | 14 ++++-
 .../course-progress/course-progress.scss      |  4 ++
 .../course-progress/course-progress.ts        | 63 ++++++++++++++++++-
 src/core/courses/lang/en.json                 |  2 +
 .../pages/course-preview/course-preview.ts    |  2 +-
 10 files changed, 160 insertions(+), 7 deletions(-)
 create mode 100644 src/core/courses/components/course-options-menu/core-courses-course-options-menu.html
 create mode 100644 src/core/courses/components/course-options-menu/course-options-menu.ts

diff --git a/src/addon/block/myoverview/components/myoverview/myoverview.ts b/src/addon/block/myoverview/components/myoverview/myoverview.ts
index 690c590a8..7e1668566 100644
--- a/src/addon/block/myoverview/components/myoverview/myoverview.ts
+++ b/src/addon/block/myoverview/components/myoverview/myoverview.ts
@@ -66,6 +66,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem
     protected prefetchIconsInitialized = false;
     protected isDestroyed;
     protected updateSiteObserver;
+    protected coursesObserver;
     protected courseIds = [];
     protected fetchContentDefaultError = 'Error getting my overview data.';
 
@@ -96,6 +97,10 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem
             }
         });
 
+        this.coursesObserver = this.eventsProvider.on(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, () => {
+            this.refreshContent();
+        }, this.sitesProvider.getCurrentSiteId());
+
         this.currentSite = this.sitesProvider.getCurrentSite();
 
         const promises = [];
@@ -326,6 +331,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem
      */
     ngOnDestroy(): void {
         this.isDestroyed = true;
+        this.coursesObserver && this.coursesObserver.off();
         this.updateSiteObserver && this.updateSiteObserver.off();
     }
 }
diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json
index 78a3ff5f5..1b99a5363 100644
--- a/src/assets/lang/en.json
+++ b/src/assets/lang/en.json
@@ -1188,6 +1188,7 @@
     "core.courses.errorselfenrol": "An error occurred while self enrolling.",
     "core.courses.filtermycourses": "Filter my courses",
     "core.courses.frontpage": "Front page",
+    "core.courses.hidecourse": "Hide from view",
     "core.courses.mycourses": "My courses",
     "core.courses.mymoodle": "Dashboard",
     "core.courses.nocourses": "No course information to show.",
@@ -1203,6 +1204,7 @@
     "core.courses.searchcoursesadvice": "You can use the search courses button to find courses to access as a  guest or enrol yourself in courses that allow it.",
     "core.courses.selfenrolment": "Self enrolment",
     "core.courses.sendpaymentbutton": "Send payment via PayPal",
+    "core.courses.show": "Show this course",
     "core.courses.totalcoursesearchresults": "Total courses: {{$a}}",
     "core.currentdevice": "Current device",
     "core.datastoredoffline": "Data stored in the device because it couldn't be sent. It will be sent automatically later.",
diff --git a/src/core/courses/components/components.module.ts b/src/core/courses/components/components.module.ts
index 14ce35cbc..45b2671cb 100644
--- a/src/core/courses/components/components.module.ts
+++ b/src/core/courses/components/components.module.ts
@@ -21,11 +21,13 @@ import { CoreDirectivesModule } from '@directives/directives.module';
 import { CorePipesModule } from '@pipes/pipes.module';
 import { CoreCoursesCourseProgressComponent } from '../components/course-progress/course-progress';
 import { CoreCoursesCourseListItemComponent } from '../components/course-list-item/course-list-item';
+import { CoreCoursesCourseOptionsMenuComponent } from '../components/course-options-menu/course-options-menu';
 
 @NgModule({
     declarations: [
         CoreCoursesCourseProgressComponent,
-        CoreCoursesCourseListItemComponent
+        CoreCoursesCourseListItemComponent,
+        CoreCoursesCourseOptionsMenuComponent
     ],
     imports: [
         CommonModule,
@@ -39,7 +41,11 @@ import { CoreCoursesCourseListItemComponent } from '../components/course-list-it
     ],
     exports: [
         CoreCoursesCourseProgressComponent,
-        CoreCoursesCourseListItemComponent
+        CoreCoursesCourseListItemComponent,
+        CoreCoursesCourseOptionsMenuComponent
+    ],
+    entryComponents: [
+        CoreCoursesCourseOptionsMenuComponent
     ]
 })
 export class CoreCoursesComponentsModule {}
diff --git a/src/core/courses/components/course-options-menu/core-courses-course-options-menu.html b/src/core/courses/components/course-options-menu/core-courses-course-options-menu.html
new file mode 100644
index 000000000..ffe8a19dd
--- /dev/null
+++ b/src/core/courses/components/course-options-menu/core-courses-course-options-menu.html
@@ -0,0 +1,13 @@
+<ion-item text-wrap (click)="action('download')" *ngIf="downloadCourseEnabled">
+    <ion-icon [name]="prefetch.prefetchCourseIcon" item-start></ion-icon>
+    <h2>{{ prefetch.title | translate }}</h2>
+</ion-item>
+<ion-item text-wrap (click)="action('hide')" *ngIf="!course.hidden">
+    <core-icon name="fa-eye" item-start></core-icon>
+    <h2>{{ 'core.courses.hidecourse' | translate }}</h2>
+</ion-item>
+<ion-item text-wrap (click)="action('show')" *ngIf="course.hidden">
+    <core-icon name="fa-eye-slash" item-start></core-icon>
+    <h2>{{ 'core.courses.show' | translate }}</h2>
+</ion-item>
+
diff --git a/src/core/courses/components/course-options-menu/course-options-menu.ts b/src/core/courses/components/course-options-menu/course-options-menu.ts
new file mode 100644
index 000000000..a63dbedf5
--- /dev/null
+++ b/src/core/courses/components/course-options-menu/course-options-menu.ts
@@ -0,0 +1,51 @@
+// (C) Copyright 2015 Martin Dougiamas
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { Component, OnInit } from '@angular/core';
+import { NavParams, ViewController } from 'ionic-angular';
+import { CoreCoursesProvider } from '../../providers/courses';
+
+/**
+ * This component is meant to display a popover with the course options.
+ */
+@Component({
+    selector: 'core-courses-course-options-menu',
+    templateUrl: 'core-courses-course-options-menu.html'
+})
+export class CoreCoursesCourseOptionsMenuComponent implements OnInit {
+    course: any; // The course.
+    prefetch: any; // The prefecth info.
+
+    downloadCourseEnabled: boolean;
+
+    constructor(navParams: NavParams, private viewCtrl: ViewController, private coursesProvider: CoreCoursesProvider) {
+        this.course = navParams.get('course') || {};
+        this.prefetch = navParams.get('prefetch') || {};
+    }
+
+    /**
+     * Component being initialized.
+     */
+    ngOnInit(): void {
+        this.downloadCourseEnabled = !this.coursesProvider.isDownloadCourseDisabledInSite();
+    }
+
+    /**
+     * Do an action over the course.
+     * @param {string} action Action name to take.
+     */
+    action(action: string): void {
+        this.viewCtrl.dismiss(action);
+    }
+}
diff --git a/src/core/courses/components/course-progress/core-courses-course-progress.html b/src/core/courses/components/course-progress/core-courses-course-progress.html
index df001f2b0..55339fdfa 100644
--- a/src/core/courses/components/course-progress/core-courses-course-progress.html
+++ b/src/core/courses/components/course-progress/core-courses-course-progress.html
@@ -3,10 +3,10 @@
         <img *ngIf="course.courseImage" [src]="course.courseImage" core-external-content alt=""/>
         <core-icon name="fa-star" *ngIf="course.isfavourite"></core-icon>
     </div>
-    <ion-item tappable text-wrap detail-none (click)="openCourse(course)" [title]="course.displayname || course.fullname" class="core-course-link" [class.item-disabled]="course.visible == 0">
+    <ion-item tappable text-wrap detail-none (click)="openCourse(course)" [title]="course.displayname || course.fullname" class="core-course-link" [class.item-disabled]="course.visible == 0" [class.core-course-more-than-title]="(course.summary && course.summary.length) || (course.progress != null && course.progress >= 0)">
         <h2><core-format-text [text]="course.displayname || course.fullname"></core-format-text></h2>
 
-        <div class="core-button-spinner" *ngIf="downloadCourseEnabled">
+        <div class="core-button-spinner" *ngIf="downloadCourseEnabled && !courseOptionMenuEnabled">
             <!-- Download course. -->
             <button *ngIf="prefetchCourseData.prefetchCourseIcon != 'spinner'" ion-button icon-only clear color="dark" (click)="prefetchCourse($event)" [attr.aria-label]="prefetchCourseData.title | translate">
                 <core-icon [name]="prefetchCourseData.prefetchCourseIcon"></core-icon>
@@ -14,6 +14,16 @@
             <!-- Download course spinner. -->
             <ion-spinner *ngIf="prefetchCourseData.prefetchCourseIcon == 'spinner'"></ion-spinner>
         </div>
+
+        <div class="core-button-spinner" *ngIf="courseOptionMenuEnabled">
+            <!-- Options menu. -->
+            <button ion-button icon-only clear color="dark" (click)="showCourseOptionsMenu($event)" *ngIf="prefetchCourseData.prefetchCourseIcon != 'spinner' && !showSpinner">
+                <core-icon name="more"></core-icon>
+            </button>
+
+            <!-- Download course spinner. -->
+            <ion-spinner *ngIf="prefetchCourseData.prefetchCourseIcon == 'spinner' || showSpinner"></ion-spinner>
+        </div>
     </ion-item>
     <ion-item text-wrap *ngIf="course.summary && course.summary.length" [class.item-disabled]="course.visible == 0">
         <p>
diff --git a/src/core/courses/components/course-progress/course-progress.scss b/src/core/courses/components/course-progress/course-progress.scss
index e99d46143..ca366793b 100644
--- a/src/core/courses/components/course-progress/course-progress.scss
+++ b/src/core/courses/components/course-progress/course-progress.scss
@@ -56,6 +56,10 @@ ion-app.app-root core-courses-course-progress {
                 margins: 6px 0;
                 flex-grow: 1;
             }
+
+            &.core-course-more-than-title {
+                padding-bottom: 0;
+            }
         }
         .label {
             @include margin(0, 0, 0, null);
diff --git a/src/core/courses/components/course-progress/course-progress.ts b/src/core/courses/components/course-progress/course-progress.ts
index 96f9b60b5..6e4ac089d 100644
--- a/src/core/courses/components/course-progress/course-progress.ts
+++ b/src/core/courses/components/course-progress/course-progress.ts
@@ -13,14 +13,16 @@
 // limitations under the License.
 
 import { Component, Input, OnInit, OnDestroy, Optional } from '@angular/core';
-import { NavController } from 'ionic-angular';
+import { NavController, PopoverController } from 'ionic-angular';
 import { CoreEventsProvider } from '@providers/events';
 import { CoreSitesProvider } from '@providers/sites';
 import { CoreDomUtilsProvider } from '@providers/utils/dom';
+import { CoreUserProvider } from '@core/user/providers/user';
 import { CoreCoursesProvider } from '@core/courses/providers/courses';
 import { CoreCourseFormatDelegate } from '@core/course/providers/format-delegate';
 import { CoreCourseProvider } from '@core/course/providers/course';
 import { CoreCourseHelperProvider } from '@core/course/providers/helper';
+import { CoreCoursesCourseOptionsMenuComponent } from '../course-options-menu/course-options-menu';
 
 /**
  * This component is meant to display a course for a list of courses with progress.
@@ -42,7 +44,9 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
         prefetchCourseIcon: 'spinner',
         title: 'core.course.downloadcourse'
     };
+    showSpinner = false;
     downloadCourseEnabled: boolean;
+    courseOptionMenuEnabled: boolean;
 
     protected isDestroyed = false;
     protected courseStatusObserver;
@@ -51,7 +55,8 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
     constructor(@Optional() private navCtrl: NavController, private courseHelper: CoreCourseHelperProvider,
             private courseFormatDelegate: CoreCourseFormatDelegate, private domUtils: CoreDomUtilsProvider,
             private courseProvider: CoreCourseProvider, private eventsProvider: CoreEventsProvider,
-            private sitesProvider: CoreSitesProvider, private coursesProvider: CoreCoursesProvider) { }
+            private sitesProvider: CoreSitesProvider, private coursesProvider: CoreCoursesProvider,
+            private popoverCtrl: PopoverController, private userProvider: CoreUserProvider) { }
 
     /**
      * Component being initialized.
@@ -63,6 +68,8 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
             this.initPrefetchCourse();
         }
 
+        this.courseOptionMenuEnabled = typeof this.course.isfavourite != 'undefined';
+
         // Refresh the enabled flag if site is updated.
         this.siteUpdatedObserver = this.eventsProvider.on(CoreEventsProvider.SITE_UPDATED, () => {
             const wasEnabled = this.downloadCourseEnabled;
@@ -153,6 +160,58 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
         this.prefetchCourseData.title = statusData.title;
     }
 
+    /**
+     * Show the context menu.
+     *
+     * @param {Event} e Click Event.
+     */
+    showCourseOptionsMenu(e: Event): void {
+        e.preventDefault();
+        e.stopPropagation();
+
+        const popover = this.popoverCtrl.create(CoreCoursesCourseOptionsMenuComponent, {
+            course: this.course,
+            prefetch: this.prefetchCourseData
+        });
+        popover.onDidDismiss((action) => {
+            if (action) {
+                switch (action) {
+                    case 'download':
+                        this.prefetchCourse(e);
+                        break;
+                    case 'hide':
+                        this.setCourseHidden(true);
+                        break;
+                    case 'show':
+                        this.setCourseHidden(false);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        });
+        popover.present({
+            ev: e
+        });
+    }
+
+    /**
+     * Hide/Unhide the course from the course list.
+     *
+     * @param {boolean} hide True to hide and false to show.
+     */
+    protected setCourseHidden(hide: boolean): void {
+        this.showSpinner = true;
+
+        this.userProvider.updateUserPreference('block_myoverview_hidden_course_' + this.course.id, hide ? 1 : false).then(() => {
+            this.course.hidden = hide;
+            this.eventsProvider.trigger(
+                CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {course: this.course}, this.sitesProvider.getCurrentSiteId());
+        }).finally(() => {
+            this.showSpinner = false;
+        });
+    }
+
     /**
      * Component destroyed.
      */
diff --git a/src/core/courses/lang/en.json b/src/core/courses/lang/en.json
index f961a47ef..818098e23 100644
--- a/src/core/courses/lang/en.json
+++ b/src/core/courses/lang/en.json
@@ -14,6 +14,7 @@
     "errorselfenrol": "An error occurred while self enrolling.",
     "filtermycourses": "Filter my courses",
     "frontpage": "Front page",
+    "hidecourse": "Hide from view",
     "mycourses": "My courses",
     "nocourses": "No course information to show.",
     "nocoursesyet": "No courses in this category",
@@ -28,5 +29,6 @@
     "searchcoursesadvice": "You can use the search courses button to find courses to access as a  guest or enrol yourself in courses that allow it.",
     "selfenrolment": "Self enrolment",
     "sendpaymentbutton": "Send payment via PayPal",
+    "show": "Show this course",
     "totalcoursesearchresults": "Total courses: {{$a}}"
 }
\ No newline at end of file
diff --git a/src/core/courses/pages/course-preview/course-preview.ts b/src/core/courses/pages/course-preview/course-preview.ts
index ce2b0d7cd..51d2253e4 100644
--- a/src/core/courses/pages/course-preview/course-preview.ts
+++ b/src/core/courses/pages/course-preview/course-preview.ts
@@ -353,7 +353,7 @@ export class CoreCoursesCoursePreviewPage implements OnDestroy {
                 this.refreshData().finally(() => {
                     // My courses have been updated, trigger event.
                     this.eventsProvider.trigger(
-                        CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {}, this.sitesProvider.getCurrentSiteId());
+                        CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {course: this.course}, this.sitesProvider.getCurrentSiteId());
                 });
             });
         }).catch((error) => {

From ed9dd1bba027d75c77b5e77f3e6b51fda4e0c9a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= <crazyserver@gmail.com>
Date: Thu, 8 Nov 2018 12:29:15 +0100
Subject: [PATCH 2/3] MOBILE-2688 workshop: Fix bug on prefetch

---
 src/addon/mod/workshop/providers/prefetch-handler.ts | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/addon/mod/workshop/providers/prefetch-handler.ts b/src/addon/mod/workshop/providers/prefetch-handler.ts
index 5168d2a5e..651e1b735 100644
--- a/src/addon/mod/workshop/providers/prefetch-handler.ts
+++ b/src/addon/mod/workshop/providers/prefetch-handler.ts
@@ -224,9 +224,9 @@ export class AddonModWorkshopPrefetchHandler extends CoreCourseActivityPrefetchH
      * @param  {number}  workshopId Workshop ID.
      * @param  {any[]}   groups     Array of groups in the activity.
      * @param  {string}  siteId     Site ID. If not defined, current site.
-     * @return {Promise<any>}       All unique entries.
+     * @return {Promise<any[]>}       All unique entries.
      */
-    protected getAllGradesReport(workshopId: number, groups: any[], siteId: string): Promise<any> {
+    protected getAllGradesReport(workshopId: number, groups: any[], siteId: string): Promise<any[]> {
         const promises = [];
 
         groups.forEach((group) => {
@@ -245,7 +245,7 @@ export class AddonModWorkshopPrefetchHandler extends CoreCourseActivityPrefetchH
                 });
             });
 
-            return uniqueGrades;
+            return this.utils.objectToArray(uniqueGrades);
         });
     }
 

From 0c0c01b8ce9b3f613992ff399e1537abc896b45d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= <crazyserver@gmail.com>
Date: Thu, 8 Nov 2018 12:29:43 +0100
Subject: [PATCH 3/3] MOBILE-2688 courses: Invalidate course list when updated

---
 scripts/langindex.json                               |  2 ++
 .../recentlyaccessedcourses.ts                       | 12 ++++++++++--
 .../components/course-progress/course-progress.ts    |  4 +++-
 src/core/courses/pages/dashboard/dashboard.ts        |  2 +-
 4 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/scripts/langindex.json b/scripts/langindex.json
index 79aa4ffe2..f4b615cda 100644
--- a/scripts/langindex.json
+++ b/scripts/langindex.json
@@ -1188,6 +1188,7 @@
   "core.courses.errorselfenrol": "local_moodlemobileapp",
   "core.courses.filtermycourses": "local_moodlemobileapp",
   "core.courses.frontpage": "admin",
+  "core.courses.hidecourse": "block_myoverview",
   "core.courses.mycourses": "moodle",
   "core.courses.mymoodle": "admin",
   "core.courses.nocourses": "my",
@@ -1203,6 +1204,7 @@
   "core.courses.searchcoursesadvice": "local_moodlemobileapp",
   "core.courses.selfenrolment": "local_moodlemobileapp",
   "core.courses.sendpaymentbutton": "enrol_paypal",
+  "core.courses.show": "block_myoverview",
   "core.courses.totalcoursesearchresults": "local_moodlemobileapp",
   "core.currentdevice": "local_moodlemobileapp",
   "core.datastoredoffline": "local_moodlemobileapp",
diff --git a/src/addon/block/recentlyaccessedcourses/components/recentlyaccessedcourses/recentlyaccessedcourses.ts b/src/addon/block/recentlyaccessedcourses/components/recentlyaccessedcourses/recentlyaccessedcourses.ts
index 9f1b3d64d..d81c2fc07 100644
--- a/src/addon/block/recentlyaccessedcourses/components/recentlyaccessedcourses/recentlyaccessedcourses.ts
+++ b/src/addon/block/recentlyaccessedcourses/components/recentlyaccessedcourses/recentlyaccessedcourses.ts
@@ -15,6 +15,7 @@
 import { Component, OnInit, OnDestroy, Injector } from '@angular/core';
 import { CoreEventsProvider } from '@providers/events';
 import { CoreUtilsProvider } from '@providers/utils/utils';
+import { CoreSitesProvider } from '@providers/sites';
 import { CoreCoursesProvider } from '@core/courses/providers/courses';
 import { CoreCoursesHelperProvider } from '@core/courses/providers/helper';
 import { CoreCourseHelperProvider } from '@core/course/providers/helper';
@@ -40,13 +41,15 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
     protected prefetchIconsInitialized = false;
     protected isDestroyed;
     protected updateSiteObserver;
+    protected coursesObserver;
     protected courseIds = [];
     protected fetchContentDefaultError = 'Error getting recent courses data.';
 
     constructor(injector: Injector, private coursesProvider: CoreCoursesProvider,
             private courseCompletionProvider: AddonCourseCompletionProvider, private eventsProvider: CoreEventsProvider,
             private courseHelper: CoreCourseHelperProvider, private utils: CoreUtilsProvider,
-            private courseOptionsDelegate: CoreCourseOptionsDelegate, private coursesHelper: CoreCoursesHelperProvider) {
+            private courseOptionsDelegate: CoreCourseOptionsDelegate, private coursesHelper: CoreCoursesHelperProvider,
+            private sitesProvider: CoreSitesProvider) {
 
         super(injector, 'AddonBlockRecentlyAccessedCoursesComponent');
     }
@@ -67,7 +70,11 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
                 // Download all courses is enabled now, initialize it.
                 this.initPrefetchCoursesIcons();
             }
-        });
+        }, this.sitesProvider.getCurrentSiteId());
+
+        this.coursesObserver = this.eventsProvider.on(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, () => {
+            this.refreshContent();
+        }, this.sitesProvider.getCurrentSiteId());
 
         super.ngOnInit();
     }
@@ -147,6 +154,7 @@ export class AddonBlockRecentlyAccessedCoursesComponent extends CoreBlockBaseCom
      */
     ngOnDestroy(): void {
         this.isDestroyed = true;
+        this.coursesObserver && this.coursesObserver.off();
         this.updateSiteObserver && this.updateSiteObserver.off();
     }
 }
diff --git a/src/core/courses/components/course-progress/course-progress.ts b/src/core/courses/components/course-progress/course-progress.ts
index 6e4ac089d..09c9167c9 100644
--- a/src/core/courses/components/course-progress/course-progress.ts
+++ b/src/core/courses/components/course-progress/course-progress.ts
@@ -68,6 +68,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
             this.initPrefetchCourse();
         }
 
+        // This field is only available from 3.6 onwards.
         this.courseOptionMenuEnabled = typeof this.course.isfavourite != 'undefined';
 
         // Refresh the enabled flag if site is updated.
@@ -203,7 +204,8 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
     protected setCourseHidden(hide: boolean): void {
         this.showSpinner = true;
 
-        this.userProvider.updateUserPreference('block_myoverview_hidden_course_' + this.course.id, hide ? 1 : false).then(() => {
+        // We should use null to unset the preference.
+        this.userProvider.updateUserPreference('block_myoverview_hidden_course_' + this.course.id, hide ? 1 : null).then(() => {
             this.course.hidden = hide;
             this.eventsProvider.trigger(
                 CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {course: this.course}, this.sitesProvider.getCurrentSiteId());
diff --git a/src/core/courses/pages/dashboard/dashboard.ts b/src/core/courses/pages/dashboard/dashboard.ts
index 51a52a9e7..591b5fec5 100644
--- a/src/core/courses/pages/dashboard/dashboard.ts
+++ b/src/core/courses/pages/dashboard/dashboard.ts
@@ -69,7 +69,7 @@ export class CoreCoursesDashboardPage implements OnDestroy {
         this.updateSiteObserver = this.eventsProvider.on(CoreEventsProvider.SITE_UPDATED, () => {
             this.searchEnabled = !this.coursesProvider.isSearchCoursesDisabledInSite();
             this.loadSiteName();
-        });
+        }, this.sitesProvider.getCurrentSiteId());
 
         const promises = [];