Merge pull request #1504 from dpalou/MOBILE-2567

Mobile 2567
main
Juan Leyva 2018-09-07 14:27:28 +02:00 committed by GitHub
commit 2002ad6b5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 61 additions and 17 deletions

View File

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.moodle.moodlemobile" version="3.5.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<widget id="com.moodle.moodlemobile" version="3.5.2" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>Moodle</name>
<description>Moodle official app</description>
<author email="mobile@moodle.com" href="http://moodle.com">Moodle Mobile team</author>
@ -122,7 +122,7 @@
</plugin>
<plugin name="ionic-plugin-keyboard" spec="^2.2.1" />
<plugin name="cordova-plugin-zip" spec="^3.1.0" />
<plugin name="cordova-plugin-local-notifications-mm" spec="^1.0.11" />
<plugin name="cordova-plugin-local-notifications-mm" spec="^1.0.13" />
<plugin name="cordova-plugin-file-opener2" spec="^2.0.19" />
<plugin name="com-darryncampbell-cordova-plugin-intent" spec="^1.1.0" />
<plugin name="cordova-sqlite-evcore-extbuild-free" spec="^0.9.7" />

View File

@ -7,4 +7,8 @@ ion-app.app-root page-addon-mod-quiz-player {
.core-has-fixed-timer form {
padding-top: 56px;
}
.toolbar-ios .bar-buttons-ios .bar-button {
@include padding-horizontal($content-padding);
}
}

View File

@ -285,7 +285,8 @@ export class AddonModQuizSyncProvider extends CoreSyncBaseProvider {
// Attempt not found or it's finished in online. Discard it.
warnings.push(this.translate.instant('addon.mod_quiz.warningattemptfinished'));
return this.finishSync(siteId, quiz, courseId, warnings, lastAttemptId, offlineAttempt, onlineAttempt, true);
return this.finishSync(siteId, quiz, courseId, warnings, offlineAttempt.id, offlineAttempt, onlineAttempt,
true);
}
// Get the data stored in offline.

View File

@ -151,4 +151,22 @@ export class AddonQtypeMultichoiceHandler implements CoreQuestionHandler {
isSameResponseSingle(prevAnswers: any, newAnswers: any): boolean {
return this.utils.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer');
}
/**
* Prepare and add to answers the data to send to server based in the input. Return promise if async.
*
* @param {any} question Question.
* @param {any} answers The answers retrieved from the form. Prepared answers must be stored in this object.
* @param {boolean} [offline] Whether the data should be saved in offline.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {void|Promise<any>} Return a promise resolved when done if async, void if sync.
*/
prepareAnswers(question: any, answers: any, offline: boolean, siteId?: string): void | Promise<any> {
if (question && !question.multi && typeof answers[question.optionsName] != 'undefined' && !answers[question.optionsName]) {
/* It's a single choice and the user hasn't answered. Delete the answer and its sequencecheck because
sending an empty string (default value) will mark the first option as selected. */
delete answers[question.optionsName];
delete answers[question.optionsName.replace('answer', ':sequencecheck')];
}
}
}

View File

@ -930,7 +930,7 @@ ion-app.app-root {
}
// Fix modals displayed over action sheet.
.disable-scroll ion-modal .ion-page {
&.disable-scroll ion-modal .ion-page {
pointer-events: initial;
}
}

View File

@ -17,7 +17,7 @@
</button>
<button *ngIf="editMode" ion-button icon-only clear [attr.aria-label]="'core.save' | translate" color="success" type="submit">
<ion-icon name="checkmark"></ion-icon>
<ion-icon name="checkmark" ios="md-checkmark"></ion-icon>
</button>
<button ion-button clear icon-only (click)="deleteFile($event)" [attr.aria-label]="'core.delete' | translate" color="danger">

View File

@ -1,5 +1,5 @@
<ion-split-pane (ionChange)="onSplitPaneChanged($event._visible);" [when]="when">
<ion-menu [content]="detailNav" type="push" class="core-avoid-header">
<ion-menu [content]="detailNav" type="push" class="core-avoid-header" [side]="side" #menu>
<ng-content></ng-content>
</ion-menu>
<ion-nav [root]="detailPage" #detailNav main class="core-avoid-header"></ion-nav>

View File

@ -15,7 +15,8 @@
// Code based on https://github.com/martinpritchardelevate/ionic-split-pane-demo
import { Component, ViewChild, Input, ElementRef, OnInit, Optional, OnDestroy } from '@angular/core';
import { NavController, Nav, ViewController } from 'ionic-angular';
import { NavController, Nav, ViewController, Platform, Menu } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core';
import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader';
import { Subscription } from 'rxjs';
@ -45,7 +46,9 @@ import { Subscription } from 'rxjs';
export class CoreSplitViewComponent implements OnInit, OnDestroy {
@ViewChild('detailNav') detailNav: Nav;
@ViewChild('menu') menu: Menu;
@Input() when?: string | boolean = 'md';
protected isEnabled = false;
protected masterPageName = '';
protected masterPageIndex = 0;
@ -56,16 +59,27 @@ export class CoreSplitViewComponent implements OnInit, OnDestroy {
protected originalMasterCanLeave: Function;
protected ignoreSplitChanged = false;
protected audioCaptureSubscription: Subscription;
protected languageChangedSubscription: Subscription;
// Empty placeholder for the 'detail' page.
detailPage: any = null;
side: string;
constructor(@Optional() private masterNav: NavController, element: ElementRef, fileUploaderProvider: CoreFileUploaderProvider) {
constructor(@Optional() private masterNav: NavController, element: ElementRef, fileUploaderProvider: CoreFileUploaderProvider,
platform: Platform, translate: TranslateService) {
this.element = element.nativeElement;
this.audioCaptureSubscription = fileUploaderProvider.onAudioCapture.subscribe((starting) => {
this.ignoreSplitChanged = starting;
});
// Change the side when the language changes.
this.languageChangedSubscription = translate.onLangChange.subscribe((event: any) => {
setTimeout(() => {
this.side = platform.isRTL ? 'right' : 'left';
this.menu.setElementAttribute('side', this.side);
});
});
}
/**
@ -244,5 +258,6 @@ export class CoreSplitViewComponent implements OnInit, OnDestroy {
ngOnDestroy(): void {
this.detailsDidEnterSubscription && this.detailsDidEnterSubscription.unsubscribe();
this.audioCaptureSubscription.unsubscribe();
this.languageChangedSubscription.unsubscribe();
}
}

View File

@ -2,8 +2,8 @@
"app_id" : "com.moodle.moodlemobile",
"appname": "Moodle Mobile",
"desktopappname": "Moodle Desktop",
"versioncode" : 3510,
"versionname" : "3.5.1",
"versioncode" : 3520,
"versionname" : "3.5.2",
"cache_expiration_time" : 300000,
"default_lang" : "en",
"languages": {"ar": "عربي", "bg": "Български", "ca": "Català", "cs": "Čeština", "da": "Dansk", "de": "Deutsch", "de-du": "Deutsch - Du", "el": "Ελληνικά", "en": "English", "es": "Español", "es-mx": "Español - México", "eu": "Euskara", "fa": "فارسی", "fi": "Suomi", "fr" : "Français", "he" : "עברית", "hu": "magyar", "it": "Italiano", "ja": "日本語", "ko" : "한국어", "lt" : "Lietuvių", "mr": "मराठी", "nl": "Nederlands", "pl": "Polski", "pt-br": "Português - Brasil", "pt": "Português - Portugal", "ro": "Română", "ru": "Русский", "sr-cr": "Српски", "sr-lt": "Srpski", "sv": "Svenska", "tr" : "Türkçe", "uk" : "Українська", "zh-cn" : "简体中文", "zh-tw" : "正體中文"},

View File

@ -465,10 +465,19 @@ export class CoreQuestionHelperProvider {
if (selected) {
selected.setAttribute('selected', 'selected');
}
} else if (element.type == 'radio' || element.type == 'checkbox') {
// Check if this radio or checkbox is selected.
} else if (element.type == 'radio') {
// Check if this radio is selected.
if (element.value == question.localAnswers[name]) {
element.setAttribute('checked', 'checked');
} else {
element.removeAttribute('checked');
}
} else if (element.type == 'checkbox') {
// Check if this checkbox is checked.
if (this.utils.isTrueOrOne(question.localAnswers[name])) {
element.setAttribute('checked', 'checked');
} else {
element.removeAttribute('checked');
}
} else {
// Put the answer in the value.

View File

@ -497,6 +497,8 @@ export class CoreLocalNotificationsProvider {
/**
* Show an in app notification popover.
* This function was used because local notifications weren't displayed when the app was in foreground in iOS10+,
* but the issue was fixed in the plugin and this function is no longer used.
*
* @param {CoreILocalNotification} notification Notification.
*/
@ -594,11 +596,6 @@ export class CoreLocalNotificationsProvider {
* @return {Promise<any>} Promise resolved when stored, rejected otherwise.
*/
trigger(notification: CoreILocalNotification): Promise<any> {
if (this.platform.is('ios') && this.platform.version().num >= 10) {
// In iOS10 show in app notification.
this.showNotificationPopover(notification);
}
const entry = {
id: notification.id,
at: parseInt(notification.at, 10)