forked from CIT/Vmeda.Online
		
	
						commit
						7d819264d7
					
				@ -546,12 +546,12 @@ export class AddonCalendarHelperProvider {
 | 
			
		||||
        const site = await CoreSites.getSite(siteId);
 | 
			
		||||
        const fetchTimestarts: number[] = [];
 | 
			
		||||
        const invalidateTimestarts: number[] = [];
 | 
			
		||||
        const promises: Promise<unknown>[] = [];
 | 
			
		||||
        let promises: Promise<unknown>[] = [];
 | 
			
		||||
 | 
			
		||||
        // Always fetch upcoming events.
 | 
			
		||||
        promises.push(AddonCalendar.getUpcomingEvents(undefined, undefined, true, site.id));
 | 
			
		||||
 | 
			
		||||
        promises.concat(events.map(async (eventData) => {
 | 
			
		||||
        promises = promises.concat(events.map(async (eventData) => {
 | 
			
		||||
 | 
			
		||||
            if (eventData.repeated <= 1) {
 | 
			
		||||
                // Not repeated.
 | 
			
		||||
 | 
			
		||||
@ -31,6 +31,7 @@ import { CoreWSExternalWarning } from '@services/ws';
 | 
			
		||||
import { makeSingleton } from '@singletons';
 | 
			
		||||
import { CoreError } from '@classes/errors/error';
 | 
			
		||||
import { AddonMessagesSyncEvents, AddonMessagesSyncProvider } from './messages-sync';
 | 
			
		||||
import { CoreWSError } from '@classes/errors/wserror';
 | 
			
		||||
 | 
			
		||||
const ROOT_CACHE_KEY = 'mmaMessages:';
 | 
			
		||||
 | 
			
		||||
@ -191,7 +192,14 @@ export class AddonMessagesProvider {
 | 
			
		||||
                requesteduserid: userId,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            await site.write('core_message_create_contact_request', params);
 | 
			
		||||
            const result = await site.write<AddonMessagesCreateContactRequestWSResponse>(
 | 
			
		||||
                'core_message_create_contact_request',
 | 
			
		||||
                params,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (result.warnings?.length) {
 | 
			
		||||
                throw new CoreWSError(result.warnings[0]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await this.invalidateAllMemberInfo(userId, site).finally(() => {
 | 
			
		||||
@ -3483,6 +3491,19 @@ type AddonMessagesConfirmContactRequestWSParams = {
 | 
			
		||||
 */
 | 
			
		||||
type AddonMessagesCreateContactRequestWSParams = AddonMessagesConfirmContactRequestWSParams;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Data returned by core_message_create_contact_request WS.
 | 
			
		||||
 */
 | 
			
		||||
export type AddonMessagesCreateContactRequestWSResponse = {
 | 
			
		||||
    request?: {
 | 
			
		||||
        id: number; // Message id.
 | 
			
		||||
        userid: number; // User from id.
 | 
			
		||||
        requesteduserid: number; // User to id.
 | 
			
		||||
        timecreated: number; // Time created.
 | 
			
		||||
    }; // Request record.
 | 
			
		||||
    warnings?: CoreWSExternalWarning[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Params of core_message_decline_contact_request WS.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@ -48,13 +48,13 @@ export class AddonModForumPrefetchHandlerService extends CoreCourseActivityPrefe
 | 
			
		||||
        try {
 | 
			
		||||
            const forum = await AddonModForum.getForum(courseId, module.id);
 | 
			
		||||
 | 
			
		||||
            const files = this.getIntroFilesFromInstance(module, forum);
 | 
			
		||||
            let files = this.getIntroFilesFromInstance(module, forum);
 | 
			
		||||
 | 
			
		||||
            // Get posts.
 | 
			
		||||
            const posts = await this.getPostsForPrefetch(forum, { cmId: module.id });
 | 
			
		||||
 | 
			
		||||
            // Add posts attachments and embedded files.
 | 
			
		||||
            files.concat(this.getPostsFiles(posts));
 | 
			
		||||
            files = files.concat(this.getPostsFiles(posts));
 | 
			
		||||
 | 
			
		||||
            return files;
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
 | 
			
		||||
@ -573,7 +573,6 @@ class AddonModGlossaryEntriesManager extends CorePageItemsListManager<EntryItem>
 | 
			
		||||
     */
 | 
			
		||||
    setOnlineEntries(onlineEntries: AddonModGlossaryEntry[], hasMoreItems: boolean = false): void {
 | 
			
		||||
        this.setItems((<EntryItem[]> this.offlineEntries).concat(onlineEntries), hasMoreItems);
 | 
			
		||||
        this.onlineEntries.concat(onlineEntries);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -583,7 +582,6 @@ class AddonModGlossaryEntriesManager extends CorePageItemsListManager<EntryItem>
 | 
			
		||||
     */
 | 
			
		||||
    setOfflineEntries(offlineEntries: AddonModGlossaryOfflineEntry[]): void {
 | 
			
		||||
        this.setItems((<EntryItem[]> offlineEntries).concat(this.onlineEntries), this.hasMoreItems);
 | 
			
		||||
        this.offlineEntries = offlineEntries;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -19,11 +19,10 @@
 | 
			
		||||
            </ion-select>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
        <ion-item>
 | 
			
		||||
            <ion-label>
 | 
			
		||||
            <ion-label></ion-label>
 | 
			
		||||
            <ion-textarea placeholder="{{ 'addon.notes.note' | translate }}" rows="5" [(ngModel)]="text" name="text"
 | 
			
		||||
                required="required">
 | 
			
		||||
            </ion-textarea>
 | 
			
		||||
            </ion-label>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
        <div class="ion-padding">
 | 
			
		||||
            <ion-button expand="block" type="submit" [disabled]="processing || text.length < 2">
 | 
			
		||||
 | 
			
		||||
@ -62,12 +62,10 @@ export class AddonNotesSyncProvider extends CoreSyncBaseProvider<AddonNotesSyncR
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        // Get all the courses to be synced.
 | 
			
		||||
        const courseIds: number[] = [];
 | 
			
		||||
        let courseIds: number[] = [];
 | 
			
		||||
        notesArray.forEach((notes: (AddonNotesDeletedDBRecord | AddonNotesDBRecord)[]) => {
 | 
			
		||||
            const courseIds = notes.map((note) => note.courseid);
 | 
			
		||||
 | 
			
		||||
            courseIds.concat(courseIds);
 | 
			
		||||
        }, []);
 | 
			
		||||
            courseIds = courseIds.concat(notes.map((note) => note.courseid));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        CoreUtils.uniqueArray(courseIds);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -64,6 +64,8 @@ const preferencesRoutes: Routes = [
 | 
			
		||||
                CoreCronDelegate.register(AddonNotificationsCronHandler.instance);
 | 
			
		||||
                CorePushNotificationsDelegate.registerClickHandler(AddonNotificationsPushClickHandler.instance);
 | 
			
		||||
                CoreSettingsDelegate.registerHandler(AddonNotificationsSettingsHandler.instance);
 | 
			
		||||
 | 
			
		||||
                AddonNotificationsMainMenuHandler.initialize();
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
@ -132,16 +132,21 @@ export class AppComponent implements OnInit, AfterViewInit {
 | 
			
		||||
 | 
			
		||||
        // Check InAppBrowser closed.
 | 
			
		||||
        CoreEvents.on(CoreEvents.IAB_EXIT, () => {
 | 
			
		||||
            CoreLoginHelper.setWaitingForBrowser(false);
 | 
			
		||||
            this.lastInAppUrl = '';
 | 
			
		||||
 | 
			
		||||
            if (CoreLoginHelper.isWaitingForBrowser()) {
 | 
			
		||||
                CoreLoginHelper.setWaitingForBrowser(false);
 | 
			
		||||
                CoreLoginHelper.checkLogout();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        Platform.resume.subscribe(() => {
 | 
			
		||||
            // Wait a second before setting it to false since in iOS there could be some frozen WS calls.
 | 
			
		||||
            setTimeout(() => {
 | 
			
		||||
                if (CoreLoginHelper.isWaitingForBrowser()) {
 | 
			
		||||
                    CoreLoginHelper.setWaitingForBrowser(false);
 | 
			
		||||
                    CoreLoginHelper.checkLogout();
 | 
			
		||||
                }
 | 
			
		||||
            }, 1000);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -247,7 +247,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
 | 
			
		||||
 | 
			
		||||
        await this.calculateMaxSlides();
 | 
			
		||||
 | 
			
		||||
        this.updateSlides();
 | 
			
		||||
        await this.updateSlides();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -378,10 +378,15 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.maxSlides = 3;
 | 
			
		||||
        const width = this.slidesSwiper.width;
 | 
			
		||||
        let width = this.slidesSwiper.width;
 | 
			
		||||
        if (!width) {
 | 
			
		||||
            this.slidesSwiper.updateSize();
 | 
			
		||||
            width = this.slidesSwiper.width;
 | 
			
		||||
 | 
			
		||||
            if (!width) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const zoomLevel = await CoreSettingsHelper.getZoom();
 | 
			
		||||
 | 
			
		||||
@ -619,7 +624,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
 | 
			
		||||
    protected windowResized(): void {
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
            this.calculateSlides();
 | 
			
		||||
        });
 | 
			
		||||
        }, 200);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,6 @@
 | 
			
		||||
                    <ng-container *ngFor="let tab of tabs">
 | 
			
		||||
                        <ion-slide
 | 
			
		||||
                            role="presentation"
 | 
			
		||||
                            [hidden]="!hideUntil"
 | 
			
		||||
                            [id]="tab.id! + '-tab'"
 | 
			
		||||
                            class="tab-slide"
 | 
			
		||||
                            tabindex="-1"
 | 
			
		||||
 | 
			
		||||
@ -23,6 +23,7 @@ import {
 | 
			
		||||
    Optional,
 | 
			
		||||
    ViewContainerRef,
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import { DomSanitizer } from '@angular/platform-browser';
 | 
			
		||||
import { IonContent } from '@ionic/angular';
 | 
			
		||||
 | 
			
		||||
import { CoreEventLoadingChangedData, CoreEventObserver, CoreEvents } from '@singletons/events';
 | 
			
		||||
@ -90,6 +91,7 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
			
		||||
        element: ElementRef,
 | 
			
		||||
        @Optional() protected content: IonContent,
 | 
			
		||||
        protected viewContainerRef: ViewContainerRef,
 | 
			
		||||
        protected sanitizer: DomSanitizer,
 | 
			
		||||
    ) {
 | 
			
		||||
 | 
			
		||||
        this.element = element.nativeElement;
 | 
			
		||||
@ -504,7 +506,7 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
			
		||||
        // Important: We need to look for links first because in 'img' we add new links without core-link.
 | 
			
		||||
        anchors.forEach((anchor) => {
 | 
			
		||||
            // Angular 2 doesn't let adding directives dynamically. Create the CoreLinkDirective manually.
 | 
			
		||||
            const linkDir = new CoreLinkDirective(new ElementRef(anchor), this.content);
 | 
			
		||||
            const linkDir = new CoreLinkDirective(new ElementRef(anchor), this.content, this.sanitizer);
 | 
			
		||||
            linkDir.capture = this.captureLinks ?? true;
 | 
			
		||||
            linkDir.inApp = this.openLinksInApp;
 | 
			
		||||
            linkDir.ngOnInit();
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,8 @@
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Directive, Input, OnInit, ElementRef, Optional } from '@angular/core';
 | 
			
		||||
import { Directive, Input, OnInit, ElementRef, Optional, SecurityContext } from '@angular/core';
 | 
			
		||||
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
 | 
			
		||||
import { IonContent } from '@ionic/angular';
 | 
			
		||||
 | 
			
		||||
import { CoreFileHelper } from '@services/file-helper';
 | 
			
		||||
@ -33,7 +34,7 @@ import { CoreCustomURLSchemes } from '@services/urlschemes';
 | 
			
		||||
})
 | 
			
		||||
export class CoreLinkDirective implements OnInit {
 | 
			
		||||
 | 
			
		||||
    @Input() href?: string; // Link URL.
 | 
			
		||||
    @Input() href?: string | SafeUrl; // Link URL.
 | 
			
		||||
    @Input() capture?: boolean | string; // If the link needs to be captured by the app.
 | 
			
		||||
    @Input() inApp?: boolean | string; // True to open in embedded browser, false to open in system browser.
 | 
			
		||||
    /* Whether the link should be opened with auto-login. Accepts the following values:
 | 
			
		||||
@ -47,6 +48,7 @@ export class CoreLinkDirective implements OnInit {
 | 
			
		||||
    constructor(
 | 
			
		||||
        element: ElementRef,
 | 
			
		||||
        @Optional() protected content: IonContent,
 | 
			
		||||
        protected sanitizer: DomSanitizer,
 | 
			
		||||
    ) {
 | 
			
		||||
        this.element = element.nativeElement;
 | 
			
		||||
    }
 | 
			
		||||
@ -91,7 +93,13 @@ export class CoreLinkDirective implements OnInit {
 | 
			
		||||
            return; // Link already treated, stop.
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let href = this.href || this.element.getAttribute('href') || this.element.getAttribute('xlink:href');
 | 
			
		||||
        let href: string | null = null;
 | 
			
		||||
        if (this.href) {
 | 
			
		||||
            // Convert the URL back to string if needed.
 | 
			
		||||
            href = typeof this.href === 'string' ? this.href : this.sanitizer.sanitize(SecurityContext.URL, this.href);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        href = href || this.element.getAttribute('href') || this.element.getAttribute('xlink:href');
 | 
			
		||||
 | 
			
		||||
        if (!href || CoreUrlUtils.getUrlScheme(href) == 'javascript') {
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,7 @@ export function buildTabMainRoutes(injector: Injector, mainRoute: Route): Routes
 | 
			
		||||
 | 
			
		||||
    mainRoute.path = mainRoute.path || '';
 | 
			
		||||
    mainRoute.children = mainRoute.children || [];
 | 
			
		||||
    mainRoute.children.concat(routes.children);
 | 
			
		||||
    mainRoute.children = mainRoute.children.concat(routes.children);
 | 
			
		||||
 | 
			
		||||
    return [
 | 
			
		||||
        mainRoute,
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content>
 | 
			
		||||
    <core-shared-files-list [siteId]="siteId" [mimetypes]="mimetypes" [isModal]="true" [manage]="manage" [pick]="pick"
 | 
			
		||||
        [path]="path" [showSitePicker]="showSitePicker" (onPathChanged)="calculateTitle($event)" (onFilePicked)="filePicked($event)">
 | 
			
		||||
        [path]="path" [showSitePicker]="!hideSitePicker" (onPathChanged)="calculateTitle($event)"
 | 
			
		||||
        (onFilePicked)="filePicked($event)">
 | 
			
		||||
    </core-shared-files-list>
 | 
			
		||||
</ion-content>
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,7 @@ export class CoreSharedFilesListModalComponent implements OnInit {
 | 
			
		||||
    @Input() manage?: boolean;
 | 
			
		||||
    @Input() pick?: boolean; // To pick a file you MUST use a modal.
 | 
			
		||||
    @Input() path?: string;
 | 
			
		||||
    @Input() showSitePicker?: boolean;
 | 
			
		||||
    @Input() hideSitePicker?: boolean;
 | 
			
		||||
 | 
			
		||||
    title?: string;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -40,7 +40,7 @@ export class CoreTagListComponent {
 | 
			
		||||
            fromContextId: tag.taginstancecontextid,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        CoreNavigator.navigateToSitePath('/tag/index', { params, preferCurrentTab: false });
 | 
			
		||||
        CoreNavigator.navigateToSitePath('/tag/index', { params });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -38,21 +38,21 @@
 | 
			
		||||
                        </a></p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="user.address">
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="formattedAddress">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <h2>{{ 'core.user.address' | translate}}</h2>
 | 
			
		||||
                        <p><a class="core-anchor" [href]="encodedAddress" core-link auto-login="no">
 | 
			
		||||
                            {{ user.address }}
 | 
			
		||||
                            {{ formattedAddress }}
 | 
			
		||||
                        </a></p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="user.city && !user.address">
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="user.city && !formattedAddress">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <h2>{{ 'core.user.city' | translate}}</h2>
 | 
			
		||||
                        <p>{{ user.city }}</p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="user.country && !user.address">
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="user.country && !formattedAddress">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <h2>{{ 'core.user.country' | translate}}</h2>
 | 
			
		||||
                        <p>{{ user.country }}</p>
 | 
			
		||||
 | 
			
		||||
@ -75,7 +75,7 @@ export class CoreUserAboutPage implements OnInit {
 | 
			
		||||
 | 
			
		||||
            if (user.address) {
 | 
			
		||||
                this.formattedAddress = CoreUserHelper.formatAddress(user.address, user.city, user.country);
 | 
			
		||||
                this.encodedAddress = CoreTextUtils.buildAddressURL(user.address);
 | 
			
		||||
                this.encodedAddress = CoreTextUtils.buildAddressURL(this.formattedAddress);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.hasContact = !!(user.email || user.phone1 || user.phone2 || user.city || user.country || user.address);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user