commit
2002ad6b5d
|
@ -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" />
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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')];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" : "正體中文"},
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue