From a128ae892922dc435c43e12b3ff7f79fd0a3d809 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 9 May 2023 09:00:54 +0200 Subject: [PATCH 1/5] MOBILE-4270 notes: Fix error displayed when restoring note --- src/addons/notes/pages/list/list.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/addons/notes/pages/list/list.ts b/src/addons/notes/pages/list/list.ts index c59455cc7..1369ec308 100644 --- a/src/addons/notes/pages/list/list.ts +++ b/src/addons/notes/pages/list/list.ts @@ -98,12 +98,12 @@ export class AddonNotesListPage implements OnInit, OnDestroy { * Fetch notes. * * @param sync When to resync notes. - * @param showErrors When to display errors or not. + * @param showSyncErrors When to display sync errors or not. * @returns Promise with the notes. */ - protected async fetchNotes(sync = false, showErrors = false): Promise { + protected async fetchNotes(sync = false, showSyncErrors = false): Promise { if (sync) { - await this.syncNotes(showErrors); + await this.syncNotes(showSyncErrors); } try { @@ -150,15 +150,15 @@ export class AddonNotesListPage implements OnInit, OnDestroy { /** * Refresh notes on PTR. * - * @param showErrors Whether to display errors or not. + * @param showSyncErrors Whether to display sync errors or not. * @param refresher Refresher instance. */ - refreshNotes(showErrors: boolean, refresher?: IonRefresher): void { + refreshNotes(showSyncErrors: boolean, refresher?: IonRefresher): void { this.refreshIcon = CoreConstants.ICON_LOADING; this.syncIcon = CoreConstants.ICON_LOADING; AddonNotes.invalidateNotes(this.courseId, this.userId).finally(() => { - this.fetchNotes(true, showErrors).finally(() => { + this.fetchNotes(true, showSyncErrors).finally(() => { if (refresher) { refresher?.complete(); } @@ -253,7 +253,7 @@ export class AddonNotesListPage implements OnInit, OnDestroy { e.stopPropagation(); await AddonNotesOffline.undoDeleteNote(note.id); - this.refreshNotes(true); + this.refreshNotes(false); } /** @@ -266,16 +266,16 @@ export class AddonNotesListPage implements OnInit, OnDestroy { /** * Tries to synchronize course notes. * - * @param showErrors Whether to display errors or not. + * @param showSyncErrors Whether to display sync errors or not. * @returns Promise resolved when done. */ - protected async syncNotes(showErrors: boolean): Promise { + protected async syncNotes(showSyncErrors: boolean): Promise { try { const result = await AddonNotesSync.syncNotes(this.courseId); this.showSyncWarnings(result.warnings); } catch (error) { - if (showErrors) { + if (showSyncErrors) { CoreDomUtils.showErrorModalDefault(error, 'core.errorsync', true); } } From 1f3d72cfbb797652d0807b899f49ee8aad9f6343 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 9 May 2023 16:24:31 +0200 Subject: [PATCH 2/5] MOBILE-4270 messages: Decrease chances of offline messages duplicated This is because Android seems to duplicate the request if the type of connection changes while the request is done. E.g. when leaving flight mode the device could connect to mobile data first and then to WiFi. --- src/addons/messages/messages.module.ts | 2 +- src/core/initializers/watch-network.ts | 5 ++++- src/core/services/filepool.ts | 2 +- src/core/services/network.ts | 19 +++++++++++++++++++ src/core/services/utils/iframe.ts | 2 +- 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/addons/messages/messages.module.ts b/src/addons/messages/messages.module.ts index c6579af46..9f7748ff0 100644 --- a/src/addons/messages/messages.module.ts +++ b/src/addons/messages/messages.module.ts @@ -87,7 +87,7 @@ const preferencesRoutes: Routes = [ CoreUserDelegate.registerHandler(AddonMessagesSendMessageUserHandler.instance); // Sync some discussions when device goes online. - CoreNetwork.onConnect().subscribe(() => { + CoreNetwork.onConnectShouldBeStable().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { AddonMessagesSync.syncAllDiscussions(undefined, true); diff --git a/src/core/initializers/watch-network.ts b/src/core/initializers/watch-network.ts index 9d8aabf5f..74c6a0261 100644 --- a/src/core/initializers/watch-network.ts +++ b/src/core/initializers/watch-network.ts @@ -16,9 +16,12 @@ import { CoreCronDelegate } from '@services/cron'; import { NgZone } from '@singletons'; import { CoreNetwork } from '@services/network'; +/** + * Initializer function. + */ export default function(): void { // When the app is re-connected, start network handlers that were stopped. - CoreNetwork.onConnect().subscribe(() => { + CoreNetwork.onConnectShouldBeStable().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => CoreCronDelegate.startNetworkHandlers()); }); diff --git a/src/core/services/filepool.ts b/src/core/services/filepool.ts index 1751636f0..3c633823a 100644 --- a/src/core/services/filepool.ts +++ b/src/core/services/filepool.ts @@ -150,7 +150,7 @@ export class CoreFilepoolProvider { this.checkQueueProcessing(); // Start queue when device goes online. - CoreNetwork.onConnect().subscribe(() => { + CoreNetwork.onConnectShouldBeStable().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => this.checkQueueProcessing()); }); diff --git a/src/core/services/network.ts b/src/core/services/network.ts index aeb49a4ae..b50a87601 100644 --- a/src/core/services/network.ts +++ b/src/core/services/network.ts @@ -38,9 +38,11 @@ export class CoreNetworkService extends Network { type!: string; protected connectObservable = new Subject<'connected'>(); + protected connectStableObservable = new Subject<'connected'>(); protected disconnectObservable = new Subject<'disconnected'>(); protected forceConnectionMode?: CoreNetworkConnection; protected online = false; + protected connectStableTimeout?: number; get connectionType(): CoreNetworkConnection { if (this.forceConnectionMode !== undefined) { @@ -146,6 +148,7 @@ export class CoreNetworkService extends Network { /** * Returns an observable to notify when the app is connected. * It will also be fired when connection type changes. + * If you're going to perform network requests once the device is connected, please use onConnectShouldBeStable instead. * * @returns Observable. */ @@ -153,6 +156,18 @@ export class CoreNetworkService extends Network { return this.connectObservable; } + /** + * Returns an observable to notify when the app is connected and it should already be a stable a connection. + * E.g. when leaving flight mode the device could connect to mobile network first and then to WiFi. + * If you're going to perform network requests once the device is connected, it's recommended to use this function instead of + * onConnect because some OS (e.g. Android) duplicate a request if the type of connection changes while the request is done. + * + * @returns Observable. + */ + onConnectShouldBeStable(): Observable<'connected'> { + return this.connectStableObservable; + } + /** * Returns an observable to notify when the app is disconnected. * @@ -166,10 +181,14 @@ export class CoreNetworkService extends Network { * Fires the correct observable depending on the connection status. */ protected fireObservable(): void { + clearTimeout(this.connectStableTimeout); this.checkOnline(); if (this.online) { this.connectObservable.next('connected'); + this.connectStableTimeout = window.setTimeout(() => { + this.connectStableObservable.next('connected'); + }, 5000); } else { this.disconnectObservable.next('disconnected'); } diff --git a/src/core/services/utils/iframe.ts b/src/core/services/utils/iframe.ts index 3314fc8dc..a35d72194 100644 --- a/src/core/services/utils/iframe.ts +++ b/src/core/services/utils/iframe.ts @@ -76,7 +76,7 @@ export class CoreIframeUtilsProvider { this.addOfflineWarning(element, src, isSubframe); // If the network changes, check it again. - const subscription = CoreNetwork.onConnect().subscribe(() => { + const subscription = CoreNetwork.onConnectShouldBeStable().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { if (!this.checkOnlineFrameInOffline(element, isSubframe)) { From 5b3244b619227a282ca9c0e9c6d8046560ed0e7c Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 9 May 2023 16:31:37 +0200 Subject: [PATCH 3/5] MOBILE-4270 core: Add more logging in app component --- src/app/app.component.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 2462f1841..badb8dc75 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -196,10 +196,15 @@ export class AppComponent implements OnInit, AfterViewInit { */ ngAfterViewInit(): void { if (!this.outlet) { + this.logger.debug('Aftew view init: no outlet found'); + return; } + this.logger.debug('Aftew view init'); + CoreSubscriptions.once(this.outlet.activateEvents, async () => { + this.logger.debug('Activate event triggered'); await CorePlatform.ready(); this.logger.debug('Hide splash screen'); @@ -213,6 +218,8 @@ export class AppComponent implements OnInit, AfterViewInit { protected async onPlatformReady(): Promise { await CorePlatform.ready(); + this.logger.debug('Platform is ready'); + // Refresh online status when changes. CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. From 006358b209926a90397b1afdb9e850635316b58f Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 10 May 2023 09:01:34 +0200 Subject: [PATCH 4/5] MOBILE-4270 h5pp: Users with 0 attempts shouldn't be clickable --- .../mod/h5pactivity/pages/users-attempts/users-attempts.html | 4 ++-- .../mod/h5pactivity/pages/users-attempts/users-attempts.ts | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.html b/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.html index 375cb84cc..2610c501e 100644 --- a/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.html +++ b/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.html @@ -31,9 +31,9 @@ - + (click)="openUser(user)" [class.hide-detail]="!user.attempts.length" [button]="user.attempts.length > 0"> diff --git a/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.ts b/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.ts index b2bb4b57b..5a211d616 100644 --- a/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.ts +++ b/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.ts @@ -208,6 +208,10 @@ export class AddonModH5PActivityUsersAttemptsPage implements OnInit { * @param user User to open. */ openUser(user: AddonModH5PActivityUserAttemptsFormatted): void { + if (!user.attempts.length) { + return; + } + CoreNavigator.navigate(`../userattempts/${user.userid}`); } From 96bdb4bd304076afcde157e23d9b6f85a7cfd636 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 10 May 2023 09:17:43 +0200 Subject: [PATCH 5/5] MOBILE-4270 h5p: Display ellipsis in attempts tables headers --- .../mod/h5pactivity/pages/user-attempts/user-attempts.html | 2 +- .../mod/h5pactivity/pages/user-attempts/user-attempts.scss | 5 +++++ .../h5pactivity/pages/users-attempts/users-attempts.scss | 6 ++++++ .../mod/h5pactivity/pages/users-attempts/users-attempts.ts | 1 + 4 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.scss diff --git a/src/addons/mod/h5pactivity/pages/user-attempts/user-attempts.html b/src/addons/mod/h5pactivity/pages/user-attempts/user-attempts.html index 0f628b053..b174ad52c 100644 --- a/src/addons/mod/h5pactivity/pages/user-attempts/user-attempts.html +++ b/src/addons/mod/h5pactivity/pages/user-attempts/user-attempts.html @@ -65,7 +65,7 @@ - + # diff --git a/src/addons/mod/h5pactivity/pages/user-attempts/user-attempts.scss b/src/addons/mod/h5pactivity/pages/user-attempts/user-attempts.scss index 82ba0a46c..eee2a95b4 100644 --- a/src/addons/mod/h5pactivity/pages/user-attempts/user-attempts.scss +++ b/src/addons/mod/h5pactivity/pages/user-attempts/user-attempts.scss @@ -1,6 +1,11 @@ :host { .addon-mod_h5pactivity-table-header { font-weight: bold; + + ion-col { + overflow: hidden; + text-overflow: ellipsis; + } } .addon-mod_h5pactivity-table-row .addon-mod_h5pactivity-table-success-col { diff --git a/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.scss b/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.scss new file mode 100644 index 000000000..4f70d0bdd --- /dev/null +++ b/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.scss @@ -0,0 +1,6 @@ +:host { + .addon-mod_h5pactivity-table-header ion-col { + overflow: hidden; + text-overflow: ellipsis; + } +} diff --git a/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.ts b/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.ts index 5a211d616..cf977abbf 100644 --- a/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.ts +++ b/src/addons/mod/h5pactivity/pages/users-attempts/users-attempts.ts @@ -32,6 +32,7 @@ import { @Component({ selector: 'page-addon-mod-h5pactivity-users-attempts', templateUrl: 'users-attempts.html', + styleUrls: ['users-attempts.scss'], }) export class AddonModH5PActivityUsersAttemptsPage implements OnInit {