forked from CIT/Vmeda.Online
		
	
						commit
						2002ad6b5d
					
				@ -1,5 +1,5 @@
 | 
				
			|||||||
<?xml version='1.0' encoding='utf-8'?>
 | 
					<?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>
 | 
					    <name>Moodle</name>
 | 
				
			||||||
    <description>Moodle official app</description>
 | 
					    <description>Moodle official app</description>
 | 
				
			||||||
    <author email="mobile@moodle.com" href="http://moodle.com">Moodle Mobile team</author>
 | 
					    <author email="mobile@moodle.com" href="http://moodle.com">Moodle Mobile team</author>
 | 
				
			||||||
@ -122,7 +122,7 @@
 | 
				
			|||||||
    </plugin>
 | 
					    </plugin>
 | 
				
			||||||
    <plugin name="ionic-plugin-keyboard" spec="^2.2.1" />
 | 
					    <plugin name="ionic-plugin-keyboard" spec="^2.2.1" />
 | 
				
			||||||
    <plugin name="cordova-plugin-zip" spec="^3.1.0" />
 | 
					    <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="cordova-plugin-file-opener2" spec="^2.0.19" />
 | 
				
			||||||
    <plugin name="com-darryncampbell-cordova-plugin-intent" spec="^1.1.0" />
 | 
					    <plugin name="com-darryncampbell-cordova-plugin-intent" spec="^1.1.0" />
 | 
				
			||||||
    <plugin name="cordova-sqlite-evcore-extbuild-free" spec="^0.9.7" />
 | 
					    <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 {
 | 
					    .core-has-fixed-timer form {
 | 
				
			||||||
        padding-top: 56px;
 | 
					        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.
 | 
					                    // Attempt not found or it's finished in online. Discard it.
 | 
				
			||||||
                    warnings.push(this.translate.instant('addon.mod_quiz.warningattemptfinished'));
 | 
					                    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.
 | 
					                // Get the data stored in offline.
 | 
				
			||||||
 | 
				
			|||||||
@ -151,4 +151,22 @@ export class AddonQtypeMultichoiceHandler implements CoreQuestionHandler {
 | 
				
			|||||||
    isSameResponseSingle(prevAnswers: any, newAnswers: any): boolean {
 | 
					    isSameResponseSingle(prevAnswers: any, newAnswers: any): boolean {
 | 
				
			||||||
        return this.utils.sameAtKeyMissingIsBlank(prevAnswers, newAnswers, 'answer');
 | 
					        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.
 | 
					  // Fix modals displayed over action sheet.
 | 
				
			||||||
  .disable-scroll ion-modal .ion-page {
 | 
					  &.disable-scroll ion-modal .ion-page {
 | 
				
			||||||
    pointer-events: initial;
 | 
					    pointer-events: initial;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
            </button>
 | 
					            </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <button *ngIf="editMode" ion-button icon-only clear [attr.aria-label]="'core.save' | translate" color="success" type="submit">
 | 
					            <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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <button ion-button clear icon-only (click)="deleteFile($event)" [attr.aria-label]="'core.delete' | translate" color="danger">
 | 
					            <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-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>
 | 
					        <ng-content></ng-content>
 | 
				
			||||||
    </ion-menu>
 | 
					    </ion-menu>
 | 
				
			||||||
    <ion-nav [root]="detailPage" #detailNav main class="core-avoid-header"></ion-nav>
 | 
					    <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
 | 
					// Code based on https://github.com/martinpritchardelevate/ionic-split-pane-demo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, ViewChild, Input, ElementRef, OnInit, Optional, OnDestroy } from '@angular/core';
 | 
					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 { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader';
 | 
				
			||||||
import { Subscription } from 'rxjs';
 | 
					import { Subscription } from 'rxjs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -45,7 +46,9 @@ import { Subscription } from 'rxjs';
 | 
				
			|||||||
export class CoreSplitViewComponent implements OnInit, OnDestroy {
 | 
					export class CoreSplitViewComponent implements OnInit, OnDestroy {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ViewChild('detailNav') detailNav: Nav;
 | 
					    @ViewChild('detailNav') detailNav: Nav;
 | 
				
			||||||
 | 
					    @ViewChild('menu') menu: Menu;
 | 
				
			||||||
    @Input() when?: string | boolean = 'md';
 | 
					    @Input() when?: string | boolean = 'md';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected isEnabled = false;
 | 
					    protected isEnabled = false;
 | 
				
			||||||
    protected masterPageName = '';
 | 
					    protected masterPageName = '';
 | 
				
			||||||
    protected masterPageIndex = 0;
 | 
					    protected masterPageIndex = 0;
 | 
				
			||||||
@ -56,16 +59,27 @@ export class CoreSplitViewComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
    protected originalMasterCanLeave: Function;
 | 
					    protected originalMasterCanLeave: Function;
 | 
				
			||||||
    protected ignoreSplitChanged = false;
 | 
					    protected ignoreSplitChanged = false;
 | 
				
			||||||
    protected audioCaptureSubscription: Subscription;
 | 
					    protected audioCaptureSubscription: Subscription;
 | 
				
			||||||
 | 
					    protected languageChangedSubscription: Subscription;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Empty placeholder for the 'detail' page.
 | 
					    // Empty placeholder for the 'detail' page.
 | 
				
			||||||
    detailPage: any = null;
 | 
					    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.element = element.nativeElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.audioCaptureSubscription = fileUploaderProvider.onAudioCapture.subscribe((starting) => {
 | 
					        this.audioCaptureSubscription = fileUploaderProvider.onAudioCapture.subscribe((starting) => {
 | 
				
			||||||
            this.ignoreSplitChanged = 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 {
 | 
					    ngOnDestroy(): void {
 | 
				
			||||||
        this.detailsDidEnterSubscription && this.detailsDidEnterSubscription.unsubscribe();
 | 
					        this.detailsDidEnterSubscription && this.detailsDidEnterSubscription.unsubscribe();
 | 
				
			||||||
        this.audioCaptureSubscription.unsubscribe();
 | 
					        this.audioCaptureSubscription.unsubscribe();
 | 
				
			||||||
 | 
					        this.languageChangedSubscription.unsubscribe();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,8 +2,8 @@
 | 
				
			|||||||
    "app_id" : "com.moodle.moodlemobile",
 | 
					    "app_id" : "com.moodle.moodlemobile",
 | 
				
			||||||
    "appname": "Moodle Mobile",
 | 
					    "appname": "Moodle Mobile",
 | 
				
			||||||
    "desktopappname": "Moodle Desktop",
 | 
					    "desktopappname": "Moodle Desktop",
 | 
				
			||||||
    "versioncode" : 3510,
 | 
					    "versioncode" : 3520,
 | 
				
			||||||
    "versionname" : "3.5.1",
 | 
					    "versionname" : "3.5.2",
 | 
				
			||||||
    "cache_expiration_time" : 300000,
 | 
					    "cache_expiration_time" : 300000,
 | 
				
			||||||
    "default_lang" : "en",
 | 
					    "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" : "正體中文"},
 | 
					    "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) {
 | 
					                    if (selected) {
 | 
				
			||||||
                        selected.setAttribute('selected', 'selected');
 | 
					                        selected.setAttribute('selected', 'selected');
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else if (element.type == 'radio' || element.type == 'checkbox') {
 | 
					                } else if (element.type == 'radio') {
 | 
				
			||||||
                    // Check if this radio or checkbox is selected.
 | 
					                    // Check if this radio is selected.
 | 
				
			||||||
                    if (element.value == question.localAnswers[name]) {
 | 
					                    if (element.value == question.localAnswers[name]) {
 | 
				
			||||||
                        element.setAttribute('checked', 'checked');
 | 
					                        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 {
 | 
					                } else {
 | 
				
			||||||
                    // Put the answer in the value.
 | 
					                    // Put the answer in the value.
 | 
				
			||||||
 | 
				
			|||||||
@ -497,6 +497,8 @@ export class CoreLocalNotificationsProvider {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Show an in app notification popover.
 | 
					     * 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.
 | 
					     * @param {CoreILocalNotification} notification Notification.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -594,11 +596,6 @@ export class CoreLocalNotificationsProvider {
 | 
				
			|||||||
     * @return {Promise<any>} Promise resolved when stored, rejected otherwise.
 | 
					     * @return {Promise<any>} Promise resolved when stored, rejected otherwise.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    trigger(notification: CoreILocalNotification): Promise<any> {
 | 
					    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 = {
 | 
					        const entry = {
 | 
				
			||||||
            id: notification.id,
 | 
					            id: notification.id,
 | 
				
			||||||
            at: parseInt(notification.at, 10)
 | 
					            at: parseInt(notification.at, 10)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user