Merge pull request #2829 from dpalou/MOBILE-3320

Mobile 3320
main
Pau Ferrer Ocaña 2021-06-15 08:49:57 +02:00 committed by GitHub
commit 345ff293c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 49 additions and 32 deletions

View File

@ -56,11 +56,11 @@
"duration_finish": day.haslastdayofevent "duration_finish": day.haslastdayofevent
}' }'
[class.addon-calendar-event-past-day]="isPastMonth || day.ispast" [class.addon-calendar-event-past-day]="isPastMonth || day.ispast"
role="button cell" role="cell"
tabindex="0" tabindex="0"
(ariaButtonClick)="dayClicked(day.mday)" (ariaButtonClick)="dayClicked(day.mday)"
> >
<p class="addon-calendar-day-number"> <p class="addon-calendar-day-number" role="button">
<span aria-hidden="true">{{ day.mday }}</span> <span aria-hidden="true">{{ day.mday }}</span>
<span class="sr-only">{{ day.periodName | translate }}</span> <span class="sr-only">{{ day.periodName | translate }}</span>
</p> </p>

View File

@ -802,14 +802,14 @@ export class AddonModDataHelperProvider {
offline: boolean, offline: boolean,
siteId?: string, siteId?: string,
): Promise<number | CoreFileUploaderStoreFilesResult> { ): Promise<number | CoreFileUploaderStoreFilesResult> {
if (!files.length) {
return 0;
}
if (offline) { if (offline) {
return this.storeFiles(dataId, entryId, fieldId, files, siteId); return this.storeFiles(dataId, entryId, fieldId, files, siteId);
} }
if (!files.length) {
return 0;
}
return CoreFileUploader.uploadOrReuploadFiles(files, AddonModDataProvider.COMPONENT, itemId, siteId); return CoreFileUploader.uploadOrReuploadFiles(files, AddonModDataProvider.COMPONENT, itemId, siteId);
} }

View File

@ -215,7 +215,6 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
// Reload the current page. // Reload the current page.
const scrollElement = await this.content?.getScrollElement(); const scrollElement = await this.content?.getScrollElement();
const scrollTop = scrollElement?.scrollTop || -1; const scrollTop = scrollElement?.scrollTop || -1;
const scrollLeft = scrollElement?.scrollLeft || -1;
this.loaded = false; this.loaded = false;
this.content?.scrollToTop(); // Scroll top so the spinner is seen. this.content?.scrollToTop(); // Scroll top so the spinner is seen.
@ -224,8 +223,11 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
await this.loadPage(this.attempt!.currentpage!); await this.loadPage(this.attempt!.currentpage!);
} finally { } finally {
this.loaded = true; this.loaded = true;
if (scrollTop != -1 && scrollLeft != -1) { if (scrollTop != -1) {
this.content?.scrollToPoint(scrollLeft, scrollTop); // Wait for content to be rendered.
setTimeout(() => {
this.content?.scrollToPoint(0, scrollTop);
}, 50);
} }
} }
} catch (error) { } catch (error) {

View File

@ -32,7 +32,12 @@ import {
} from '../../services/survey'; } from '../../services/survey';
import { AddonModSurveyHelper, AddonModSurveyQuestionFormatted } from '../../services/survey-helper'; import { AddonModSurveyHelper, AddonModSurveyQuestionFormatted } from '../../services/survey-helper';
import { AddonModSurveyOffline } from '../../services/survey-offline'; import { AddonModSurveyOffline } from '../../services/survey-offline';
import { AddonModSurveyAutoSyncData, AddonModSurveySync, AddonModSurveySyncResult } from '../../services/survey-sync'; import {
AddonModSurveyAutoSyncData,
AddonModSurveySync,
AddonModSurveySyncProvider,
AddonModSurveySyncResult,
} from '../../services/survey-sync';
/** /**
* Component that displays a survey. * Component that displays a survey.
@ -52,6 +57,7 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
answers: Record<string, string> = {}; answers: Record<string, string> = {};
protected currentUserId?: number; protected currentUserId?: number;
protected syncEventName = AddonModSurveySyncProvider.AUTO_SYNCED;
constructor( constructor(
protected content?: IonContent, protected content?: IonContent,

View File

@ -590,7 +590,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
if (modalData) { if (modalData) {
if (modalData.home) { if (modalData.home) {
// Go back to the initial page of the wiki. // Go back to the initial page of the wiki.
CoreNavigator.navigateToSitePath(modalData.home); CoreNavigator.navigateToSitePath(modalData.home, { animationDirection: 'back' });
} else if (modalData.page) { } else if (modalData.page) {
this.goToPage(modalData.page); this.goToPage(modalData.page);
} }

View File

@ -37,7 +37,7 @@
elementId="content_editor" [draftExtraParams]="editorExtraParams"></core-rich-text-editor> elementId="content_editor" [draftExtraParams]="editorExtraParams"></core-rich-text-editor>
</ion-item> </ion-item>
<core-attachments *ngIf="fileAvailable" [files]="submission?.attachmentfiles || []" [maxSize]="workshop.maxbytes" <core-attachments *ngIf="fileAvailable" [files]="attachments" [maxSize]="workshop.maxbytes"
[maxSubmissions]="workshop.nattachments" [component]="component" [componentId]="workshop.coursemodule" [maxSubmissions]="workshop.nattachments" [component]="component" [componentId]="workshop.coursemodule"
allowOffline="true" [acceptedTypes]="workshop.submissionfiletypes" [required]="fileRequired"> allowOffline="true" [acceptedTypes]="workshop.submissionfiletypes" [required]="fileRequired">
</core-attachments> </core-attachments>

View File

@ -20,7 +20,6 @@ import { CoreFileUploader, CoreFileUploaderStoreFilesResult } from '@features/fi
import { CanLeave } from '@guards/can-leave'; import { CanLeave } from '@guards/can-leave';
import { CoreFile } from '@services/file'; import { CoreFile } from '@services/file';
import { CoreFileEntry, CoreFileHelper } from '@services/file-helper'; import { CoreFileEntry, CoreFileHelper } from '@services/file-helper';
import { CoreFileSession } from '@services/file-session';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreSync } from '@services/sync'; import { CoreSync } from '@services/sync';
@ -67,6 +66,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
textRequired = false; textRequired = false;
fileAvailable = false; fileAvailable = false;
fileRequired = false; fileRequired = false;
attachments: CoreFileEntry[] = [];
protected workshopId!: number; protected workshopId!: number;
protected submissionId = 0; protected submissionId = 0;
@ -211,14 +211,9 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
this.editForm.controls['title'].setValue(this.submission.title); this.editForm.controls['title'].setValue(this.submission.title);
this.editForm.controls['content'].setValue(this.submission.content); this.editForm.controls['content'].setValue(this.submission.content);
this.attachments = this.submission.attachmentfiles || [];
} }
CoreFileSession.setFiles(
this.component,
this.getFilesComponentId(),
this.submission?.attachmentfiles || [],
);
this.loaded = true; this.loaded = true;
} catch (error) { } catch (error) {
this.loaded = false; this.loaded = false;
@ -254,7 +249,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
} }
if (this.fileAvailable) { if (this.fileAvailable) {
values.attachmentfiles = CoreFileSession.getFiles(this.component, this.getFilesComponentId()) || []; values.attachmentfiles = this.attachments;
} }
return values; return values;
@ -337,7 +332,9 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
// Upload attachments first if any. // Upload attachments first if any.
let allowOffline = !inputData.attachmentfiles.length; let allowOffline = !inputData.attachmentfiles.length;
try { try {
let attachmentsId: CoreFileUploaderStoreFilesResult | number | undefined; let attachmentsId: number | undefined;
let storeFilesResult: CoreFileUploaderStoreFilesResult | undefined;
try { try {
attachmentsId = await AddonModWorkshopHelper.uploadOrStoreSubmissionFiles( attachmentsId = await AddonModWorkshopHelper.uploadOrStoreSubmissionFiles(
this.workshopId, this.workshopId,
@ -349,7 +346,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
saveOffline = true; saveOffline = true;
allowOffline = true; allowOffline = true;
attachmentsId = await AddonModWorkshopHelper.uploadOrStoreSubmissionFiles( storeFilesResult = await AddonModWorkshopHelper.uploadOrStoreSubmissionFiles(
this.workshopId, this.workshopId,
inputData.attachmentfiles, inputData.attachmentfiles,
true, true,
@ -369,7 +366,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
this.courseId, this.courseId,
inputData.title, inputData.title,
inputData.content, inputData.content,
attachmentsId as CoreFileUploaderStoreFilesResult, storeFilesResult,
submissionId, submissionId,
AddonModWorkshopAction.UPDATE, AddonModWorkshopAction.UPDATE,
); );
@ -396,7 +393,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
this.courseId, this.courseId,
inputData.title, inputData.title,
inputData.content, inputData.content,
attachmentsId as CoreFileUploaderStoreFilesResult, storeFilesResult,
undefined, undefined,
AddonModWorkshopAction.ADD, AddonModWorkshopAction.ADD,
); );

View File

@ -17,7 +17,6 @@ import { CoreError } from '@classes/errors/error';
import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
import { CoreCourseCommonModWSOptions } from '@features/course/services/course'; import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
import { CoreCourseLogHelper } from '@features/course/services/log-helper'; import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreFileUploaderStoreFilesResult } from '@features/fileuploader/services/fileuploader';
import { CoreGradesMenuItem } from '@features/grades/services/grades-helper'; import { CoreGradesMenuItem } from '@features/grades/services/grades-helper';
import { CoreApp } from '@services/app'; import { CoreApp } from '@services/app';
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
@ -718,7 +717,7 @@ export class AddonModWorkshopProvider {
courseId: number, courseId: number,
title: string, title: string,
content: string, content: string,
attachmentsId?: number | CoreFileUploaderStoreFilesResult, attachmentsId?: number,
siteId?: string, siteId?: string,
allowOffline: boolean = false, allowOffline: boolean = false,
): Promise<number | false> { ): Promise<number | false> {
@ -731,7 +730,7 @@ export class AddonModWorkshopProvider {
courseId, courseId,
title, title,
content, content,
attachmentsId as CoreFileUploaderStoreFilesResult, undefined,
undefined, undefined,
AddonModWorkshopAction.ADD, AddonModWorkshopAction.ADD,
siteId, siteId,
@ -814,7 +813,7 @@ export class AddonModWorkshopProvider {
courseId: number, courseId: number,
title: string, title: string,
content: string, content: string,
attachmentsId?: CoreFileUploaderStoreFilesResult | number | undefined, attachmentsId?: number | undefined,
siteId?: string, siteId?: string,
allowOffline: boolean = false, allowOffline: boolean = false,
): Promise<number | false> { ): Promise<number | false> {
@ -827,7 +826,7 @@ export class AddonModWorkshopProvider {
courseId, courseId,
title, title,
content, content,
attachmentsId as CoreFileUploaderStoreFilesResult, undefined,
submissionId, submissionId,
AddonModWorkshopAction.UPDATE, AddonModWorkshopAction.UPDATE,
siteId, siteId,

View File

@ -188,7 +188,7 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
if (tagName == 'VIDEO' && targetAttr != 'poster') { if (tagName == 'VIDEO' && targetAttr != 'poster') {
const video = <HTMLVideoElement> this.element; const video = <HTMLVideoElement> this.element;
if (video.textTracks) { if (video.textTracks) {
// It's a video with subtitles. In iOS, subtitles position is wrong so it needs to be fixed. // It's a video with subtitles. Fix some issues with subtitles.
video.textTracks.onaddtrack = (event): void => { video.textTracks.onaddtrack = (event): void => {
const track = <TextTrack> event.track; const track = <TextTrack> event.track;
if (track) { if (track) {
@ -248,6 +248,11 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
true, true,
downloadUnknown, downloadUnknown,
); );
} else if (tagName === 'TRACK') {
// Download tracks right away. Using an online URL for tracks can give a CORS error in Android.
finalUrl = await CoreFilepool.downloadUrl(site.getId(), url, false, this.component, this.componentId);
finalUrl = CoreFile.convertFileSrc(finalUrl);
} else { } else {
finalUrl = await CoreFilepool.getUrlByUrl( finalUrl = await CoreFilepool.getUrlByUrl(
site.getId(), site.getId(),
@ -277,6 +282,13 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
this.loaded = false; this.loaded = false;
this.waitForLoad(); this.waitForLoad();
} }
if (targetAttr == 'poster') {
// Setting the poster immediately doesn't display it in some cases. Set it to empty and then set the right one.
this.element.setAttribute(targetAttr, '');
await CoreUtils.nextTick();
}
this.element.setAttribute(targetAttr, finalUrl); this.element.setAttribute(targetAttr, finalUrl);
this.element.setAttribute('data-original-' + targetAttr, url); this.element.setAttribute('data-original-' + targetAttr, url);
} }

View File

@ -44,8 +44,7 @@ export type CoreRedirectPayload = {
/** /**
* Navigation options. * Navigation options.
*/ */
export type CoreNavigationOptions = { export type CoreNavigationOptions = Pick<NavigationOptions, 'animated'|'animation'|'animationDirection'> & {
animated?: boolean;
params?: Params; params?: Params;
reset?: boolean; reset?: boolean;
preferCurrentTab?: boolean; // Default true. preferCurrentTab?: boolean; // Default true.
@ -132,6 +131,8 @@ export class CoreNavigatorService {
const url: string[] = [/^[./]/.test(path) ? path : `./${path}`]; const url: string[] = [/^[./]/.test(path) ? path : `./${path}`];
const navigationOptions: NavigationOptions = CoreObject.withoutEmpty({ const navigationOptions: NavigationOptions = CoreObject.withoutEmpty({
animated: options.animated, animated: options.animated,
animation: options.animation,
animationDirection: options.animationDirection,
queryParams: CoreObject.isEmpty(options.params ?? {}) ? null : CoreObject.withoutEmpty(options.params), queryParams: CoreObject.isEmpty(options.params ?? {}) ? null : CoreObject.withoutEmpty(options.params),
relativeTo: path.startsWith('/') ? null : this.getCurrentRoute(), relativeTo: path.startsWith('/') ? null : this.getCurrentRoute(),
}); });