diff --git a/config.xml b/config.xml index 1ad6dba00..587cd8bb2 100644 --- a/config.xml +++ b/config.xml @@ -1,42 +1,29 @@ - + Moodle Moodle official app Moodle Mobile team - - - - - - - + - - + + @@ -51,21 +38,17 @@ - - - - + - @@ -73,11 +56,6 @@ - @@ -89,15 +67,13 @@ - - - + @@ -109,23 +85,22 @@ We need your location so you can attach it as part of your submissions. - + We need camera access to take pictures so you can attach them as part of your submissions. - + We need microphone access to record sounds so you can attach them as part of your submissions. - + We need photo library access to get pictures from there so you can attach them as part of your submissions. - - + + - + 3.8.2 - - + YES @@ -156,12 +131,12 @@ Alternate LSItemContentTypes - public.calendar-event - public.database - public.executable - public.data - public.content - public.item + public.calendar-event + public.database + public.executable + public.data + public.content + public.item @@ -171,7 +146,7 @@ Alternate LSItemContentTypes - public.video + public.video @@ -181,7 +156,7 @@ Alternate LSItemContentTypes - public.image + public.image @@ -191,7 +166,7 @@ Alternate LSItemContentTypes - com.apple.webarchive + com.apple.webarchive @@ -201,9 +176,9 @@ Alternate LSItemContentTypes - com.apple.keynote.key - com.apple.iwork.keynote.key - com.apple.iwork.keynote.kth + com.apple.keynote.key + com.apple.iwork.keynote.key + com.apple.iwork.keynote.kth @@ -213,9 +188,9 @@ Alternate LSItemContentTypes - com.apple.numbers.numbers - com.apple.iwork.numbers.numbers - com.apple.iwork.numbers.template + com.apple.numbers.numbers + com.apple.iwork.numbers.numbers + com.apple.iwork.numbers.template @@ -225,9 +200,9 @@ Alternate LSItemContentTypes - com.apple.page.pages - com.apple.iwork.pages.pages - com.apple.iwork.pages.template + com.apple.page.pages + com.apple.iwork.pages.pages + com.apple.iwork.pages.template @@ -237,7 +212,7 @@ Alternate LSItemContentTypes - org.oasis.opendocument.spreadsheet + org.oasis.opendocument.spreadsheet @@ -247,7 +222,7 @@ Alternate LSItemContentTypes - org.oasis.opendocument.presentation + org.oasis.opendocument.presentation @@ -257,7 +232,7 @@ Alternate LSItemContentTypes - org.oasis.opendocument.text + org.oasis.opendocument.text @@ -267,7 +242,7 @@ Alternate LSItemContentTypes - public.folder + public.folder @@ -277,13 +252,13 @@ Alternate LSItemContentTypes - public.audio - public.mp3 - public.mpeg-4-audio - com.apple.protected-​mpeg-4-audio - public.aifc-audio - com.apple.coreaudio-​format - public.aiff-audio + public.audio + public.mp3 + public.mpeg-4-audio + com.apple.protected-​mpeg-4-audio + public.aifc-audio + com.apple.coreaudio-​format + public.aiff-audio @@ -293,12 +268,12 @@ Alternate LSItemContentTypes - public.movie - public.3gpp2 - public.3gpp - public.mpeg - com.apple.quicktime-movie - public.mpeg-4 + public.movie + public.3gpp2 + public.3gpp + public.mpeg + com.apple.quicktime-movie + public.mpeg-4 @@ -308,7 +283,7 @@ Alternate LSItemContentTypes - com.compuserve.gif + com.compuserve.gif @@ -318,7 +293,7 @@ Alternate LSItemContentTypes - public.png + public.png @@ -328,7 +303,7 @@ Alternate LSItemContentTypes - public.tiff + public.tiff @@ -338,7 +313,7 @@ Alternate LSItemContentTypes - public.jpeg + public.jpeg @@ -348,7 +323,7 @@ Alternate LSItemContentTypes - public.xml + public.xml @@ -358,8 +333,8 @@ Alternate LSItemContentTypes - public.html - public.xhtml + public.html + public.xhtml @@ -369,9 +344,9 @@ Alternate LSItemContentTypes - public.rtf - com.apple.rtfd - com.apple.flat-rtfd + public.rtf + com.apple.rtfd + com.apple.flat-rtfd @@ -381,29 +356,29 @@ Alternate LSItemContentTypes - public.text - public.plain-text - public.utf8-plain-text - public.utf16-external-plain-​text - public.utf16-plain-text - com.apple.traditional-mac-​plain-text - public.source-code - public.c-source - public.objective-c-source - public.c-plus-plus-source - public.objective-c-plus-​plus-source - public.c-header - public.c-plus-plus-header - com.sun.java-source - public.script - public.shell-script + public.text + public.plain-text + public.utf8-plain-text + public.utf16-external-plain-​text + public.utf16-plain-text + com.apple.traditional-mac-​plain-text + public.source-code + public.c-source + public.objective-c-source + public.c-plus-plus-source + public.objective-c-plus-​plus-source + public.c-header + public.c-plus-plus-header + com.sun.java-source + public.script + public.shell-script CFBundleTypeExtensions - zip - zipx + zip + zipx CFBundleTypeName Zip archive @@ -411,17 +386,17 @@ Alternate LSItemContentTypes - public.zip-archive - public.archive - com.pkware.zip-archive - com.pkware.zipx-archive + public.zip-archive + public.archive + com.pkware.zip-archive + com.pkware.zipx-archive CFBundleTypeExtensions - rar - RAR + rar + RAR CFBundleTypeName Rar archive @@ -429,15 +404,15 @@ Alternate LSItemContentTypes - com.rarlab.rar-archive - public.archive + com.rarlab.rar-archive + public.archive CFBundleTypeExtensions - 7z - 7Z + 7z + 7Z CFBundleTypeName 7z archive @@ -445,8 +420,8 @@ Alternate LSItemContentTypes - org.7-zip.7-zip-archive - public.archive + org.7-zip.7-zip-archive + public.archive @@ -456,7 +431,7 @@ Alternate LSItemContentTypes - com.microsoft.waveform-​audio + com.microsoft.waveform-​audio @@ -466,8 +441,8 @@ Alternate LSItemContentTypes - com.microsoft.ico - com.apple.icns + com.microsoft.ico + com.apple.icns @@ -477,7 +452,7 @@ Alternate LSItemContentTypes - com.microsoft.bmp + com.microsoft.bmp @@ -487,8 +462,8 @@ Alternate LSItemContentTypes - com.microsoft.powerpoint.​ppt - org.openxmlformats.presentationml.presentation + com.microsoft.powerpoint.​ppt + org.openxmlformats.presentationml.presentation @@ -498,8 +473,8 @@ Alternate LSItemContentTypes - org.openxmlformats.spreadsheetml.sheet - com.microsoft.excel.xls + org.openxmlformats.spreadsheetml.sheet + com.microsoft.excel.xls @@ -509,9 +484,9 @@ Alternate LSItemContentTypes - com.microsoft.word.doc - com.microsoft.word.wordml - org.openxmlformats.wordprocessingml.document + com.microsoft.word.doc + com.microsoft.word.wordml + org.openxmlformats.wordprocessingml.document @@ -521,7 +496,7 @@ Alternate LSItemContentTypes - com.adobe.pdf + com.adobe.pdf diff --git a/src/addon/mod/lti/providers/lti.ts b/src/addon/mod/lti/providers/lti.ts index 0c544b4b6..4ea3c1460 100644 --- a/src/addon/mod/lti/providers/lti.ts +++ b/src/addon/mod/lti/providers/lti.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Injectable } from '@angular/core'; +import { Injectable, NgZone } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from '@providers/app'; import { CoreFileProvider } from '@providers/file'; @@ -41,7 +41,8 @@ export class AddonModLtiProvider { private utils: CoreUtilsProvider, private translate: TranslateService, private appProvider: CoreAppProvider, - private logHelper: CoreCourseLogHelperProvider) {} + private logHelper: CoreCourseLogHelperProvider, + protected zone: NgZone) {} /** * Delete launcher. @@ -59,38 +60,61 @@ export class AddonModLtiProvider { * @param params Launch params. * @return Promise resolved with the file URL. */ - generateLauncher(url: string, params: AddonModLtiParam[]): Promise { + async generateLauncher(url: string, params: AddonModLtiParam[]): Promise { if (!this.fileProvider.isAvailable()) { - return Promise.resolve(url); + return url; } - // Generate a form with the params. - let text = '
\n'; - params.forEach((p) => { - if (p.name == 'ext_submit') { - text += ' \n'; - }); - text += '
\n'; - - // Add an in-line script to automatically submit the form. - text += ' \n'; - return this.fileProvider.writeFile(this.LAUNCHER_FILE_NAME, text).then((entry) => { - if (this.appProvider.isDesktop()) { - return entry.toInternalURL(); + const entry = await this.fileProvider.writeFile(this.LAUNCHER_FILE_NAME, text); + + if (this.appProvider.isDesktop()) { + return entry.toInternalURL(); + } else { + return entry.toURL(); + } + } + + /** + * Get the Javascript code to launch the LTI tool. + * + * @param url Launch URL. + * @param params Launch params. + * @return Javascript code. + */ + getLaunchJSCode(url: string, params: AddonModLtiParam[]): string { + // Create the form. + let jsCode = 'var form = document.createElement("form");\n' + + 'form.method = "post";\n' + + 'form.setAttribute("encType", "application/x-www-form-urlencoded");\n' + + `form.setAttribute("action", "${url}");\n`; + + // Create the inputs based on the params. + params.forEach((p) => { + jsCode += 'var input = document.createElement("input");\n'; + + if (p.name == 'ext_submit') { + jsCode += 'input.type = "submit";\n'; } else { - return entry.toURL(); + jsCode += 'input.type = "hidden";\n' + + 'input.name = "' + this.textUtils.escapeHTML(p.name) + '";\n'; } + + jsCode += 'input.value = "' + this.textUtils.escapeHTML(p.value) + '";\n' + + 'form.appendChild(input);\n'; }); + + // Add the form to the document and submit it. + jsCode += 'document.body.appendChild(form);\n' + + 'form.submit();\n'; + + return jsCode; } /** @@ -200,20 +224,47 @@ export class AddonModLtiProvider { * @param params Launch params. * @return Promise resolved when the WS call is successful. */ - launch(url: string, params: AddonModLtiParam[]): Promise { + async launch(url: string, params: AddonModLtiParam[]): Promise { if (!this.urlUtils.isHttpURL(url)) { - return Promise.reject(this.translate.instant('addon.mod_lti.errorinvalidlaunchurl')); + throw this.translate.instant('addon.mod_lti.errorinvalidlaunchurl'); } - // Generate launcher and open it. - return this.generateLauncher(url, params).then((url) => { - if (this.appProvider.isMobile()) { - this.utils.openInApp(url); - } else { - // In desktop open in browser, we found some cases where inapp caused JS issues. - this.utils.openInBrowser(url); - } - }); + if (this.appProvider.isMobile()) { + // Open it in InAppBrowser. Use JS code because IAB has a bug in iOS when opening local files. + const jsCode = this.getLaunchJSCode(url, params); + + const iabInstance = this.utils.openInApp('about:blank'); + + // Execute the JS code when the page is loaded. + let codeExecuted = false; + const executeCode = (): void => { + if (codeExecuted) { + return; + } + + codeExecuted = true; + loadStopSubscription && loadStopSubscription.unsubscribe(); + + // Execute the callback in the Angular zone, so change detection doesn't stop working. + this.zone.run(() => { + iabInstance.executeScript({code: jsCode}); + }); + }; + + const loadStopSubscription = iabInstance.on('loadstop').subscribe((event) => { + executeCode(); + }); + + // If loadstop hasn't triggered after 1 second, execute the code anyway. + setTimeout(() => { + executeCode(); + }, 1000); + } else { + // Generate launched and open it in system browser, we found some cases where inapp caused JS issues. + const launcherUrl = await this.generateLauncher(url, params); + + this.utils.openInBrowser(launcherUrl); + } } /** diff --git a/src/providers/utils/utils.ts b/src/providers/utils/utils.ts index 49d562d18..ac9fb4622 100644 --- a/src/providers/utils/utils.ts +++ b/src/providers/utils/utils.ts @@ -921,6 +921,7 @@ export class CoreUtilsProvider { } options = options || {}; + options.usewkwebview = 'yes'; // Force WKWebView in iOS. if (!options.enableViewPortScale) { options.enableViewPortScale = 'yes'; // Enable zoom on iOS.