diff --git a/scripts/langindex.json b/scripts/langindex.json index 092fbfb2c..11f362ee4 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1970,7 +1970,6 @@ "core.login.recaptchaexpired": "local_moodlemobileapp", "core.login.recaptchaincorrect": "local_moodlemobileapp", "core.login.reconnect": "local_moodlemobileapp", - "core.login.reconnectdescription": "local_moodlemobileapp", "core.login.reconnectssodescription": "local_moodlemobileapp", "core.login.removeaccount": "local_moodlemobileapp", "core.login.resendemail": "moodle", diff --git a/src/core/classes/site.ts b/src/core/classes/site.ts index f88defc5d..99f9bb496 100644 --- a/src/core/classes/site.ts +++ b/src/core/classes/site.ts @@ -45,6 +45,7 @@ import { CoreSites } from '@services/sites'; import { asyncInstance, AsyncInstance } from '../utils/async-instance'; import { CoreDatabaseTable } from './database/database-table'; import { CoreDatabaseCachingStrategy } from './database/database-table-proxy'; +import { CoreSilentError } from './errors/silenterror'; /** * QR Code type enumeration. @@ -520,7 +521,8 @@ export class CoreSite { // Site is logged out, it cannot call WebServices. CoreEvents.trigger(CoreEvents.SESSION_EXPIRED, {}, this.id); - throw new CoreError(Translate.instant('core.lostconnection')); + // Use a silent error, the SESSION_EXPIRED event will display a message if needed. + throw new CoreSilentError(Translate.instant('core.lostconnection')); } const initialToken = this.token || ''; @@ -610,6 +612,8 @@ export class CoreSite { return response; } catch (error) { + let useSilentError = false; + if (CoreUtils.isExpiredTokenError(error)) { if (initialToken !== this.token && !retrying) { // Token has changed, retry with the new token. @@ -627,6 +631,7 @@ export class CoreSite { CoreEvents.trigger(CoreEvents.SESSION_EXPIRED, {}, this.id); // Change error message. Try to get data from cache, the event will handle the error. error.message = Translate.instant('core.lostconnection'); + useSilentError = true; // Use a silent error, the SESSION_EXPIRED event will display a message if needed. } else if (error.errorcode === 'userdeleted' || error.errorcode === 'wsaccessuserdeleted') { // User deleted, trigger event. CoreEvents.trigger(CoreEvents.USER_DELETED, { params: data }, this.id); @@ -707,7 +712,11 @@ export class CoreSite { try { return await this.getFromCache(method, data, preSets, true); - } catch (e) { + } catch { + if (useSilentError) { + throw new CoreSilentError(error.message); + } + throw new CoreWSError(error); } } diff --git a/src/core/features/login/lang.json b/src/core/features/login/lang.json index f3716516e..6eb0b227f 100644 --- a/src/core/features/login/lang.json +++ b/src/core/features/login/lang.json @@ -96,7 +96,6 @@ "recaptchaexpired": "Verification expired. Answer the security question again.", "recaptchaincorrect": "The security question answer is incorrect.", "reconnect": "Reconnect", - "reconnectdescription": "Your authentication token is invalid or has expired. You have to reconnect to the site.", "reconnectssodescription": "Your authentication token is invalid or has expired. You have to reconnect to the site. You need to log in to the site in a browser window.", "removeaccount": "Remove account", "resendemail": "Resend email", diff --git a/src/core/features/login/pages/reconnect/reconnect.html b/src/core/features/login/pages/reconnect/reconnect.html index 3a37bd1f0..61bf8066f 100644 --- a/src/core/features/login/pages/reconnect/reconnect.html +++ b/src/core/features/login/pages/reconnect/reconnect.html @@ -30,7 +30,7 @@ -

{{ 'core.login.reconnectdescription' | translate }}

+

{{ 'core.lostconnection' | translate }}

diff --git a/src/core/services/filepool.ts b/src/core/services/filepool.ts index f41ee3cd4..b3db06a44 100644 --- a/src/core/services/filepool.ts +++ b/src/core/services/filepool.ts @@ -2603,12 +2603,12 @@ export class CoreFilepoolProvider { // Success, we add links and remove from queue. CoreUtils.ignoreErrors(this.addFileLinks(siteId, fileId, links)); - this.treatQueueDeferred(siteId, fileId, true); - this.notifyFileDownloaded(siteId, fileId, links); - // Wait for the item to be removed from queue before resolving the promise. // If the item could not be removed from queue we still resolve the promise. await CoreUtils.ignoreErrors(this.removeFromQueue(siteId, fileId)); + + this.treatQueueDeferred(siteId, fileId, true); + this.notifyFileDownloaded(siteId, fileId, links); } catch (errorObject) { // Whoops, we have an error... let dropFromQueue = false; diff --git a/src/core/services/utils/utils.ts b/src/core/services/utils/utils.ts index e211d3350..08150ed3f 100644 --- a/src/core/services/utils/utils.ts +++ b/src/core/services/utils/utils.ts @@ -49,6 +49,7 @@ export class CoreUtilsProvider { protected iabInstance?: InAppBrowserObject; protected uniqueIds: {[name: string]: number} = {}; protected qrScanData?: {deferred: PromiseDefer; observable: Subscription}; + protected initialColorSchemeContent = 'light dark'; constructor() { this.logger = CoreLogger.getInstance('CoreUtilsProvider'); @@ -1651,6 +1652,13 @@ export class CoreUtilsProvider { document.body.classList.add('core-scanning-qr'); + // Set color-scheme to 'normal', otherwise the camera isn't seen in Android. + const colorSchemeMeta = document.querySelector('meta[name="color-scheme"]'); + if (colorSchemeMeta) { + this.initialColorSchemeContent = colorSchemeMeta.getAttribute('content') || this.initialColorSchemeContent; + colorSchemeMeta.setAttribute('content', 'normal'); + } + return this.qrScanData.deferred.promise; } catch (e) { this.stopScanQR(e, true); @@ -1679,6 +1687,10 @@ export class CoreUtilsProvider { // Hide camera preview. document.body.classList.remove('core-scanning-qr'); + + // Set color-scheme to the initial value. + document.querySelector('meta[name="color-scheme"]')?.setAttribute('content', this.initialColorSchemeContent); + QRScanner.hide(); QRScanner.destroy();