From f20e34db5c5f3f064c40b6af58d7acab81f7b68e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= <crazyserver@gmail.com>
Date: Tue, 14 May 2019 12:48:29 +0200
Subject: [PATCH 1/2] MOBILE-2851 user: Fix user not enrolled message

---
 scripts/langindex.json                    |  5 ++++
 src/addon/notes/providers/user-handler.ts |  2 +-
 src/assets/lang/en.json                   |  1 +
 src/core/user/pages/profile/profile.html  |  5 ++--
 src/core/user/pages/profile/profile.ts    |  2 ++
 src/core/user/providers/user-delegate.ts  | 36 +++++++++++------------
 src/core/user/providers/user-handler.ts   |  2 +-
 src/lang/en.json                          |  1 +
 8 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/scripts/langindex.json b/scripts/langindex.json
index f3702f753..1afd0fd4a 100644
--- a/scripts/langindex.json
+++ b/scripts/langindex.json
@@ -1266,9 +1266,11 @@
   "core.course.activitynotyetviewablesiteupgradeneeded": "local_moodlemobileapp",
   "core.course.allsections": "local_moodlemobileapp",
   "core.course.askadmintosupport": "local_moodlemobileapp",
+  "core.course.availablespace": "local_moodlemobileapp",
   "core.course.confirmdeletemodulefiles": "local_moodlemobileapp",
   "core.course.confirmdownload": "local_moodlemobileapp",
   "core.course.confirmdownloadunknownsize": "local_moodlemobileapp",
+  "core.course.confirmlimiteddownload": "local_moodlemobileapp",
   "core.course.confirmpartialdownloadsize": "local_moodlemobileapp",
   "core.course.contents": "local_moodlemobileapp",
   "core.course.couldnotloadsectioncontent": "local_moodlemobileapp",
@@ -1280,6 +1282,8 @@
   "core.course.errorgetmodule": "local_moodlemobileapp",
   "core.course.hiddenfromstudents": "moodle",
   "core.course.hiddenoncoursepage": "moodle",
+  "core.course.insufficientavailablequota": "local_moodlemobileapp",
+  "core.course.insufficientavailablespace": "local_moodlemobileapp",
   "core.course.manualcompletionnotsynced": "local_moodlemobileapp",
   "core.course.nocontentavailable": "local_moodlemobileapp",
   "core.course.overriddennotice": "grades",
@@ -1586,6 +1590,7 @@
   "core.nopermissions": "error",
   "core.noresults": "moodle",
   "core.notapplicable": "local_moodlemobileapp",
+  "core.notenrolledprofile": "moodle",
   "core.notice": "moodle",
   "core.notingroup": "moodle",
   "core.notsent": "local_moodlemobileapp",
diff --git a/src/addon/notes/providers/user-handler.ts b/src/addon/notes/providers/user-handler.ts
index a348ffb13..c7a37d061 100644
--- a/src/addon/notes/providers/user-handler.ts
+++ b/src/addon/notes/providers/user-handler.ts
@@ -72,7 +72,7 @@ export class AddonNotesUserHandler implements CoreUserProfileHandler {
     isEnabledForUser(user: any, courseId: number, navOptions?: any, admOptions?: any): boolean | Promise<boolean> {
         // Active course required.
         if (!courseId || user.id == this.sitesProvider.getCurrentSiteUserId()) {
-            return Promise.resolve(false);
+            return false;
         }
 
         if (typeof this.noteEnabledCache[courseId] != 'undefined') {
diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json
index 40e85aa93..7cbba2a50 100644
--- a/src/assets/lang/en.json
+++ b/src/assets/lang/en.json
@@ -1590,6 +1590,7 @@
     "core.nopermissions": "Sorry, but you do not currently have permissions to do that ({{$a}}).",
     "core.noresults": "No results",
     "core.notapplicable": "n/a",
+    "core.notenrolledprofile": "This profile is not available because this user is not enrolled in this course.",
     "core.notice": "Notice",
     "core.notingroup": "Sorry, but you need to be part of a group to see this page.",
     "core.notsent": "Not sent",
diff --git a/src/core/user/pages/profile/profile.html b/src/core/user/pages/profile/profile.html
index 57d96674e..fae5a9edd 100644
--- a/src/core/user/pages/profile/profile.html
+++ b/src/core/user/pages/profile/profile.html
@@ -8,7 +8,7 @@
         <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
     </ion-refresher>
     <core-loading [hideUntil]="userLoaded">
-        <ion-list *ngIf="user && !isDeleted">
+        <ion-list *ngIf="user && !isDeleted && isEnrolled">
             <ion-item text-center>
                 <ion-avatar core-user-avatar class="item-avatar-center" [user]="user" [userId]="user.id" [linkProfile]="false" [checkOnline]="true">
                     <ion-icon name="create" class="core-icon-foreground" *ngIf="canChangeProfilePicture" (click)="changeProfilePicture()"></ion-icon>
@@ -58,8 +58,9 @@
                 </button>
             </ion-item>
         </ion-list>
-        <core-empty-box *ngIf="!user && !isDeleted" icon="person" [message]=" 'core.user.detailsnotavailable' | translate"></core-empty-box>
+        <core-empty-box *ngIf="!user && !isDeleted && isEnrolled" icon="person" [message]=" 'core.user.detailsnotavailable' | translate"></core-empty-box>
 
         <core-empty-box *ngIf="isDeleted" icon="person" [message]="'core.userdeleted' | translate"></core-empty-box>
+        <core-empty-box *ngIf="!isEnrolled" icon="person" [message]="'core.notenrolledprofile' | translate"></core-empty-box>
     </core-loading>
 </ion-content>
\ No newline at end of file
diff --git a/src/core/user/pages/profile/profile.ts b/src/core/user/pages/profile/profile.ts
index 957de53e7..46fb41d6a 100644
--- a/src/core/user/pages/profile/profile.ts
+++ b/src/core/user/pages/profile/profile.ts
@@ -46,6 +46,7 @@ export class CoreUserProfilePage {
     user: any;
     title: string;
     isDeleted = false;
+    isEnrolled = true;
     canChangeProfilePicture = false;
     actionHandlers: CoreUserProfileHandlerData[] = [];
     newPageHandlers: CoreUserProfileHandlerData[] = [];
@@ -85,6 +86,7 @@ export class CoreUserProfilePage {
         this.fetchUser().then(() => {
             return this.userProvider.logView(this.userId, this.courseId).catch((error) => {
                 this.isDeleted = error.errorcode === 'userdeleted';
+                this.isEnrolled = error.errorcode !== 'notenrolledprofile';
             });
         }).finally(() => {
             this.userLoaded = true;
diff --git a/src/core/user/providers/user-delegate.ts b/src/core/user/providers/user-delegate.ts
index 7bab647d1..92796f273 100644
--- a/src/core/user/providers/user-delegate.ts
+++ b/src/core/user/providers/user-delegate.ts
@@ -16,6 +16,7 @@ import { Injectable } from '@angular/core';
 import { NavController } from 'ionic-angular';
 import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
 import { CoreCoursesProvider } from '@core/courses/providers/courses';
+import { CoreUtilsProvider } from '@providers/utils/utils';
 import { CoreLoggerProvider } from '@providers/logger';
 import { CoreSitesProvider } from '@providers/sites';
 import { CoreEventsProvider } from '@providers/events';
@@ -173,7 +174,8 @@ export class CoreUserDelegate extends CoreDelegate {
         }} = {};
 
     constructor(protected loggerProvider: CoreLoggerProvider, protected sitesProvider: CoreSitesProvider,
-            private coursesProvider: CoreCoursesProvider, protected eventsProvider: CoreEventsProvider) {
+            private coursesProvider: CoreCoursesProvider, protected eventsProvider: CoreEventsProvider,
+            protected utils: CoreUtilsProvider) {
         super('CoreUserDelegate', loggerProvider, sitesProvider, eventsProvider);
 
         eventsProvider.on(CoreUserDelegate.UPDATE_HANDLER_EVENT, (data) => {
@@ -266,25 +268,23 @@ export class CoreUserDelegate extends CoreDelegate {
             for (const name in this.enabledHandlers) {
                 // Checks if the handler is enabled for the user.
                 const handler = <CoreUserProfileHandler> this.handlers[name],
-                    isEnabledForUser = handler.isEnabledForUser(user, courseId, navOptions, admOptions),
-                    promise = Promise.resolve(isEnabledForUser).then((enabled) => {
-                        if (enabled) {
-                            userData.handlers.push({
-                                name: name,
-                                data: handler.getDisplayData(user, courseId),
-                                priority: handler.priority,
-                                type: handler.type || CoreUserDelegate.TYPE_NEW_PAGE
-                            });
-                        } else {
-                            return Promise.reject(null);
-                        }
-                    }).catch(() => {
-                        // Nothing to do here, it is not enabled for this user.
-                    });
-                promises.push(promise);
+                    isEnabledForUser = handler.isEnabledForUser(user, courseId, navOptions, admOptions);
+
+                promises.push(Promise.resolve(isEnabledForUser).then((enabled) => {
+                    if (enabled) {
+                        userData.handlers.push({
+                            name: name,
+                            data: handler.getDisplayData(user, courseId),
+                            priority: handler.priority,
+                            type: handler.type || CoreUserDelegate.TYPE_NEW_PAGE
+                        });
+                    }
+                }).catch(() => {
+                    // Nothing to do here, it is not enabled for this user.
+                }));
             }
 
-            return Promise.all(promises).then(() => {
+            return this.utils.allPromises(promises).then(() => {
                 // Sort them by priority.
                 userData.handlers.sort((a, b) => {
                     return b.priority - a.priority;
diff --git a/src/core/user/providers/user-handler.ts b/src/core/user/providers/user-handler.ts
index 15956dd8e..699f1fac2 100644
--- a/src/core/user/providers/user-handler.ts
+++ b/src/core/user/providers/user-handler.ts
@@ -48,7 +48,7 @@ export class CoreUserProfileMailHandler implements CoreUserProfileHandler {
      */
     isEnabledForUser(user: any, courseId: number, navOptions?: any, admOptions?: any): boolean | Promise<boolean> {
         // Not current user required.
-        return user.id != this.sitesProvider.getCurrentSite().getUserId() && user.email;
+        return user.id != this.sitesProvider.getCurrentSite().getUserId() && !!user.email;
     }
 
     /**
diff --git a/src/lang/en.json b/src/lang/en.json
index d1e2a0c96..0fb6bb5bd 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -172,6 +172,7 @@
     "nopermissions": "Sorry, but you do not currently have permissions to do that ({{$a}}).",
     "noresults": "No results",
     "notapplicable": "n/a",
+    "notenrolledprofile": "This profile is not available because this user is not enrolled in this course.",
     "notice": "Notice",
     "notingroup": "Sorry, but you need to be part of a group to see this page.",
     "notsent": "Not sent",

From e413c956987ee29515716ae5870de158940ae0eb Mon Sep 17 00:00:00 2001
From: Dani Palou <dani@moodle.com>
Date: Tue, 14 May 2019 13:42:33 +0200
Subject: [PATCH 2/2] MOBILE-2851 core: Fix promise never finished when retry
 request

---
 src/classes/site.ts | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/classes/site.ts b/src/classes/site.ts
index ec988b24b..5331b38a1 100644
--- a/src/classes/site.ts
+++ b/src/classes/site.ts
@@ -794,6 +794,17 @@ export class CoreSite {
             request.deferred.reject = reject;
         });
 
+        return this.enqueueRequest(request);
+    }
+
+    /**
+     * Adds a request to the queue.
+     *
+     * @param {RequestQueueItem} request The request to enqueue.
+     * @returns {Promise<any>} Promise resolved with the response when the WS is called.
+     */
+    protected enqueueRequest(request: RequestQueueItem): Promise<any> {
+
         this.requestQueue.push(request);
 
         if (this.requestQueue.length >= CoreSite.REQUEST_QUEUE_LIMIT) {
@@ -875,7 +886,7 @@ export class CoreSite {
 
                 if (!response) {
                     // Request not executed, enqueue again.
-                    this.callOrEnqueueRequest(request.method, request.data, request.preSets, request.wsPreSets);
+                    this.enqueueRequest(request);
                 } else if (response.error) {
                     request.deferred.reject(this.textUtils.parseJSON(response.exception));
                 } else {