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/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.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.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 b2bb4b57b..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 { @@ -208,6 +209,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}`); } 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); } } 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. 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)) {