diff --git a/config.xml b/config.xml index b565229241f..6f949ffa981 100644 --- a/config.xml +++ b/config.xml @@ -1,5 +1,5 @@ - + Moodle Moodle official app Moodle Mobile team diff --git a/desktop/assets/windows/AppXManifest.xml b/desktop/assets/windows/AppXManifest.xml index f7726e61b00..583b9fdc126 100644 --- a/desktop/assets/windows/AppXManifest.xml +++ b/desktop/assets/windows/AppXManifest.xml @@ -6,7 +6,7 @@ + Version="3.8.2.0" /> Moodle Desktop Moodle Pty Ltd. diff --git a/package.json b/package.json index ee8d9a7fc47..bd1de5e567c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "moodlemobile", - "version": "3.8.1", + "version": "3.8.2", "description": "The official app for Moodle.", "author": { "name": "Moodle Pty Ltd.", @@ -225,7 +225,7 @@ "category": "public.app-category.education", "icon": "resources/desktop/icon.icns", "target": "mas", - "bundleVersion": "3.8.1", + "bundleVersion": "3.8.2", "extendInfo": { "ElectronTeamID": "2NU57U5PAW" } diff --git a/src/assets/exttomime.json b/src/assets/exttomime.json index bab0004455e..2728d8b3d36 100644 --- a/src/assets/exttomime.json +++ b/src/assets/exttomime.json @@ -6,17 +6,17 @@ "3ds": {"type":"image/x-3ds"}, "3g2": {"type":"video/3gpp2"}, "3gp": {"type":"video/quicktime","icon":"quicktime","string":"video","groups":["video"]}, -"7z": {"type":"application/x-7z-compressed","icon":"archive"}, +"7z": {"type":"application/x-7z-compressed","icon":"archive","string":"archive","groups":["archive"]}, "a": {"type":"application/octet-stream"}, "aab": {"type":"application/x-authorware-bin"}, -"aac": {"type":"audio/aac","icon":"audio","string":"audio","groups":["audio"]}, +"aac": {"type":"audio/aac","icon":"audio","string":"audio","groups":["audio","html_audio","web_audio"]}, "aam": {"type":"application/x-authorware-map"}, "aas": {"type":"application/x-authorware-seg"}, "abc": {"type":"text/vnd.abc"}, "abw": {"type":"application/x-abiword"}, "ac": {"type":"application/pkix-attr-cert"}, "acc": {"type":"application/vnd.americandynamics.acc"}, -"accdb": {"type":"application/msaccess","icon":"database"}, +"accdb": {"type":"application/msaccess","icon":"base"}, "ace": {"type":"application/x-ace-compressed","icon":"archive"}, "acgi": {"type":"text/html"}, "acu": {"type":"application/vnd.acucobol"}, @@ -77,6 +77,7 @@ "bcpio": {"type":"application/x-bcpio"}, "bdf": {"type":"application/x-font-bdf"}, "bdm": {"type":"application/vnd.syncml.dm+wbxml"}, +"bdoc": {"type":"application/x-digidoc","icon":"document","groups":["archive"]}, "bed": {"type":"application/vnd.realvnc.bed"}, "bh2": {"type":"application/vnd.fujitsu.oasysprs"}, "bin": {"type":"application/octet-stream"}, @@ -126,6 +127,7 @@ "cdmid": {"type":"application/cdmi-domain"}, "cdmio": {"type":"application/cdmi-object"}, "cdmiq": {"type":"application/cdmi-queue"}, +"cdoc": {"type":"application/x-digidoc","icon":"document","groups":["archive"]}, "cdx": {"type":"chemical/x-cdx"}, "cdxml": {"type":"application/vnd.chemdraw+xml"}, "cdy": {"type":"application/vnd.cinderella"}, @@ -188,6 +190,7 @@ "dcurl": {"type":"text/vnd.curl.dcurl"}, "dd2": {"type":"application/vnd.oma.dd2+xml"}, "ddd": {"type":"application/vnd.fujixerox.ddd"}, +"ddoc": {"type":"application/x-digidoc","icon":"document","groups":["archive"]}, "deb": {"type":"application/x-debian-package"}, "deepv": {"type":"application/x-deepv"}, "def": {"type":"text/plain"}, @@ -274,7 +277,7 @@ "fbs": {"type":"image/vnd.fastbidsheet"}, "fcdt": {"type":"application/vnd.adobe.formscentral.fcdt"}, "fcs": {"type":"application/vnd.isac.fcs"}, -"fdf": {"type":"application/pdf","icon":"pdf"}, +"fdf": {"type":"application/vnd.fdf","icon":"pdf"}, "fdk": {"type":"application/octet-stream"}, "fe_launch": {"type":"application/vnd.denovo.fcselayout-link"}, "fg5": {"type":"application/vnd.fujitsu.oasysgp"}, @@ -286,7 +289,7 @@ "fhc": {"type":"image/x-freehand"}, "fif": {"type":"application/fractals"}, "fig": {"type":"application/x-xfig"}, -"flac": {"type":"audio/x-flac","icon":"audio","string":"audio","groups":["audio","web_audio"]}, +"flac": {"type":"audio/flac","icon":"audio","string":"audio","groups":["audio","html_audio","web_audio"]}, "fli": {"type":"video/x-fli"}, "flo": {"type":"application/vnd.micrografx.flo"}, "flv": {"type":"video/x-flv","icon":"flash","string":"video","groups":["video","web_video"]}, @@ -295,6 +298,7 @@ "fly": {"type":"text/vnd.fly"}, "fm": {"type":"application/vnd.framemaker"}, "fmf": {"type":"video/x-atomic3d-feature"}, +"fmp4": {"type":"video/mp4","icon":"mpeg","string":"video","groups":["html_video","video","web_video"]}, "fnc": {"type":"application/vnd.frogans.fnc"}, "for": {"type":"text/x-fortran"}, "fpx": {"type":"image/vnd.fpx"}, @@ -314,12 +318,15 @@ "g3": {"type":"image/g3fax"}, "g3w": {"type":"application/vnd.geospace"}, "gac": {"type":"application/vnd.groove-account"}, +"gallery": {"type":"application/x-smarttech-notebook","icon":"archive"}, +"gallerycollection": {"type":"application/x-smarttech-notebook","icon":"archive"}, +"galleryitem": {"type":"application/x-smarttech-notebook","icon":"archive"}, "gam": {"type":"application/x-tads"}, "gbr": {"type":"application/rpki-ghostbusters"}, "gca": {"type":"application/x-gca-compressed"}, "gdl": {"type":"model/vnd.gdl"}, "gdoc": {"type":"application/vnd.google-apps.document","icon":"document","groups":["document"]}, -"gdraw": {"type":"application/vnd.google-apps.drawing","icon":"draw"}, +"gdraw": {"type":"application/vnd.google-apps.drawing","icon":"image","groups":["image"]}, "geo": {"type":"application/vnd.dynageo"}, "gex": {"type":"application/vnd.geometry-explorer"}, "ggb": {"type":"application/vnd.geogebra.file","icon":"archive"}, @@ -359,7 +366,7 @@ "h261": {"type":"video/h261"}, "h263": {"type":"video/h263"}, "h264": {"type":"video/h264"}, -"h5p": {"type":"application/zip","icon":"archive","string":"archive","groups":["archive"]}, +"h5p": {"type":"application/zip","icon":"h5p","string":"archive"}, "hal": {"type":"application/vnd.hal+xml"}, "hbci": {"type":"application/vnd.hbci"}, "hdf": {"type":"application/x-hdf"}, @@ -434,7 +441,7 @@ "ivy": {"type":"application/x-livescreen"}, "jad": {"type":"text/vnd.sun.j2me.app-descriptor"}, "jam": {"type":"application/vnd.jam"}, -"jar": {"type":"application/java-archive"}, +"jar": {"type":"application/java-archive","icon":"archive"}, "jav": {"type":"text/plain"}, "java": {"type":"text/plain","icon":"sourcecode"}, "jcb": {"type":"text/xml","icon":"markup"}, @@ -447,7 +454,7 @@ "jlt": {"type":"application/vnd.hp-jlyt"}, "jmt": {"type":"text/xml","icon":"markup"}, "jmx": {"type":"text/xml","icon":"markup"}, -"jnlp": {"type":"application/x-java-jnlp-file"}, +"jnlp": {"type":"application/x-java-jnlp-file","icon":"markup"}, "joda": {"type":"application/vnd.joost.joda-archive"}, "jpe": {"type":"image/jpeg","icon":"jpeg","string":"image","groups":["image","web_image"]}, "jpeg": {"type":"image/jpeg","icon":"jpeg","string":"image","groups":["image","web_image"]}, @@ -458,7 +465,7 @@ "jps": {"type":"image/x-jps"}, "jqz": {"type":"text/xml","icon":"markup"}, "js": {"type":"application/x-javascript","icon":"text","groups":["web_file"]}, -"json": {"type":"application/json"}, +"json": {"type":"application/json","icon":"text"}, "jsonml": {"type":"application/jsonml+json"}, "jut": {"type":"image/jutvision"}, "kar": {"type":"audio/midi"}, @@ -521,10 +528,10 @@ "m2v": {"type":"video/mpeg"}, "m3a": {"type":"audio/mpeg"}, "m3u": {"type":"audio/x-mpegurl","icon":"mp3","string":"audio","groups":["audio"]}, -"m3u8": {"type":"application/vnd.apple.mpegurl"}, -"m4a": {"type":"audio/mp4","icon":"audio","string":"audio","groups":["audio","web_audio"]}, +"m3u8": {"type":"application/x-mpegURL","icon":"mpeg","groups":["media_source"]}, +"m4a": {"type":"audio/mp4","icon":"mp3","string":"audio","groups":["audio","html_audio","web_audio"]}, "m4u": {"type":"video/vnd.mpegurl"}, -"m4v": {"type":"video/mp4","icon":"mpeg","string":"video","groups":["video","web_video"]}, +"m4v": {"type":"video/mp4","icon":"mpeg","string":"video","groups":["html_video","video","web_video"]}, "ma": {"type":"application/mathematica","string":"math"}, "mads": {"type":"application/mads+xml"}, "mag": {"type":"application/vnd.ecowin.chart"}, @@ -544,7 +551,7 @@ "mcf": {"type":"image/vasa"}, "mcp": {"type":"application/netmc"}, "mcurl": {"type":"text/vnd.curl.mcurl"}, -"mdb": {"type":"application/x-msaccess","icon":"database"}, +"mdb": {"type":"application/x-msaccess","icon":"base"}, "mdi": {"type":"image/vnd.ms-modi"}, "me": {"type":"text/troff"}, "mesh": {"type":"model/mesh"}, @@ -555,8 +562,8 @@ "mft": {"type":"application/rpki-manifest"}, "mgp": {"type":"application/vnd.osgeo.mapguide.package"}, "mgz": {"type":"application/vnd.proteus.magazine"}, -"mht": {"type":"message/rfc822"}, -"mhtml": {"type":"message/rfc822"}, +"mht": {"type":"message/rfc822","icon":"archive"}, +"mhtml": {"type":"message/rfc822","icon":"archive"}, "mid": {"type":"audio/midi"}, "midi": {"type":"audio/midi"}, "mie": {"type":"application/x-mie"}, @@ -582,18 +589,19 @@ "mod": {"type":"audio/mod"}, "mods": {"type":"application/mods+xml"}, "moov": {"type":"video/quicktime"}, -"mov": {"type":"video/quicktime","icon":"quicktime","string":"video","groups":["video","web_video"]}, +"mov": {"type":"video/quicktime","icon":"quicktime","string":"video","groups":["video","web_video","html_video"]}, "movie": {"type":"video/x-sgi-movie","icon":"quicktime","string":"video","groups":["video"]}, "mp2": {"type":"audio/mpeg"}, "mp21": {"type":"application/mp21"}, "mp2a": {"type":"audio/mpeg"}, -"mp3": {"type":"audio/mp3","icon":"mp3","string":"audio","groups":["audio","web_audio"]}, -"mp4": {"type":"video/mp4","icon":"mpeg","string":"video","groups":["video","web_video"]}, -"mp4a": {"type":"audio/mp4","icon":"audio","string":"audio","groups":["audio","web_audio"]}, +"mp3": {"type":"audio/mp3","icon":"mp3","string":"audio","groups":["audio","html_audio","web_audio"]}, +"mp4": {"type":"video/mp4","icon":"mpeg","string":"video","groups":["html_video","video","web_video"]}, +"mp4a": {"type":"audio/mp4","icon":"audio","string":"audio","groups":["audio","html_audio","web_audio"]}, "mp4s": {"type":"application/mp4"}, "mp4v": {"type":"video/mp4","icon":"mpeg","string":"video","groups":["video","web_video"]}, "mpa": {"type":"audio/mpeg"}, "mpc": {"type":"application/vnd.mophun.certificate"}, +"mpd": {"type":"application/dash+xml","icon":"mpeg","groups":["media_source"]}, "mpe": {"type":"video/mpeg","icon":"mpeg","string":"video","groups":["video","web_video"]}, "mpeg": {"type":"video/mpeg","icon":"mpeg","string":"video","groups":["video","web_video"]}, "mpg": {"type":"video/mpeg","icon":"mpeg","string":"video","groups":["video","web_video"]}, @@ -603,6 +611,7 @@ "mpm": {"type":"application/vnd.blueice.multipass"}, "mpn": {"type":"application/vnd.mophun.application"}, "mpp": {"type":"application/vnd.ms-project"}, +"mpr": {"type":"application/vnd.moodle.profiling","icon":"moodle"}, "mpt": {"type":"application/vnd.ms-project"}, "mpv": {"type":"application/x-project"}, "mpx": {"type":"application/x-project"}, @@ -624,7 +633,9 @@ "musicxml": {"type":"application/vnd.recordare.musicxml+xml"}, "mv": {"type":"video/x-sgi-movie"}, "mvb": {"type":"application/x-msmediaview"}, +"mw": {"type":"application/maple","icon":"math"}, "mwf": {"type":"application/vnd.mfer"}, +"mws": {"type":"application/maple","icon":"math"}, "mxf": {"type":"application/mxf"}, "mxl": {"type":"application/vnd.recordare.musicxml"}, "mxml": {"type":"application/xv+xml"}, @@ -637,6 +648,7 @@ "nap": {"type":"image/naplps"}, "naplps": {"type":"image/naplps"}, "nb": {"type":"application/mathematica","string":"math"}, +"nbk": {"type":"application/x-smarttech-notebook","icon":"archive"}, "nbp": {"type":"application/vnd.wolfram.player"}, "nc": {"type":"application/x-netcdf"}, "ncm": {"type":"application/vnd.nokia.configuration-message"}, @@ -652,6 +664,7 @@ "nnd": {"type":"application/vnd.noblenet-directory"}, "nns": {"type":"application/vnd.noblenet-sealer"}, "nnw": {"type":"application/vnd.noblenet-web"}, +"notebook": {"type":"application/x-smarttech-notebook","icon":"archive"}, "npx": {"type":"image/vnd.net-fpx"}, "nsc": {"type":"application/x-conference"}, "nsf": {"type":"application/vnd.lotus-notes"}, @@ -672,12 +685,12 @@ "odg": {"type":"application/vnd.oasis.opendocument.graphics","icon":"draw"}, "odi": {"type":"application/vnd.oasis.opendocument.image","icon":"draw"}, "odm": {"type":"application/vnd.oasis.opendocument.text-master","icon":"writer"}, -"odp": {"type":"application/vnd.oasis.opendocument.presentation","icon":"impress"}, +"odp": {"type":"application/vnd.oasis.opendocument.presentation","icon":"impress","groups":["presentation"]}, "ods": {"type":"application/vnd.oasis.opendocument.spreadsheet","icon":"calc","groups":["spreadsheet"]}, "odt": {"type":"application/vnd.oasis.opendocument.text","icon":"writer","groups":["document"]}, -"oga": {"type":"audio/ogg","icon":"audio","string":"audio","groups":["audio","web_audio"]}, -"ogg": {"type":"audio/ogg","icon":"audio","string":"audio","groups":["audio","web_audio"]}, -"ogv": {"type":"video/ogg","icon":"video","string":"video","groups":["video","web_video"]}, +"oga": {"type":"audio/ogg","icon":"audio","string":"audio","groups":["audio","html_audio","web_audio"]}, +"ogg": {"type":"audio/ogg","icon":"audio","string":"audio","groups":["audio","html_audio","web_audio"]}, +"ogv": {"type":"video/ogg","icon":"video","string":"video","groups":["html_video","video","web_video"]}, "ogx": {"type":"application/ogg"}, "omc": {"type":"application/x-omc"}, "omcd": {"type":"application/x-omcdatamaker"}, @@ -698,7 +711,7 @@ "otg": {"type":"application/vnd.oasis.opendocument.graphics-template","icon":"draw"}, "oth": {"type":"application/vnd.oasis.opendocument.text-web","icon":"oth","groups":["document"]}, "oti": {"type":"application/vnd.oasis.opendocument.image-template"}, -"otp": {"type":"application/vnd.oasis.opendocument.presentation-template","icon":"impress"}, +"otp": {"type":"application/vnd.oasis.opendocument.presentation-template","icon":"impress","groups":["presentation"]}, "ots": {"type":"application/vnd.oasis.opendocument.spreadsheet-template","icon":"calc","groups":["spreadsheet"]}, "ott": {"type":"application/vnd.oasis.opendocument.text-template","icon":"writer","groups":["document"]}, "oxps": {"type":"application/oxps"}, @@ -726,7 +739,7 @@ "pcurl": {"type":"application/vnd.curl.pcurl"}, "pcx": {"type":"image/x-pcx"}, "pdb": {"type":"application/vnd.palm"}, -"pdf": {"type":"application/pdf","icon":"pdf"}, +"pdf": {"type":"application/pdf","icon":"pdf","groups":["document"]}, "pem": {"type":"application/x-pem-file"}, "pfa": {"type":"application/x-font-type1"}, "pfb": {"type":"application/x-font-type1"}, @@ -760,20 +773,20 @@ "png": {"type":"image/png","icon":"png","string":"image","groups":["image","web_image"]}, "pnm": {"type":"image/x-portable-anymap"}, "portpkg": {"type":"application/vnd.macports.portpkg"}, -"pot": {"type":"application/vnd.ms-powerpoint","icon":"powerpoint"}, -"potm": {"type":"application/vnd.ms-powerpoint.template.macroenabled.12","icon":"powerpoint"}, -"potx": {"type":"application/vnd.openxmlformats-officedocument.presentationml.template","icon":"powerpoint"}, +"pot": {"type":"application/vnd.ms-powerpoint","icon":"powerpoint","groups":["presentation"]}, +"potm": {"type":"application/vnd.ms-powerpoint.template.macroenabled.12","icon":"powerpoint","groups":["presentation"]}, +"potx": {"type":"application/vnd.openxmlformats-officedocument.presentationml.template","icon":"powerpoint","groups":["presentation"]}, "pov": {"type":"model/x-pov"}, -"ppa": {"type":"application/vnd.ms-powerpoint","icon":"powerpoint"}, -"ppam": {"type":"application/vnd.ms-powerpoint.addin.macroenabled.12","icon":"powerpoint"}, +"ppa": {"type":"application/vnd.ms-powerpoint","icon":"powerpoint","groups":["presentation"]}, +"ppam": {"type":"application/vnd.ms-powerpoint.addin.macroenabled.12","icon":"powerpoint","groups":["presentation"]}, "ppd": {"type":"application/vnd.cups-ppd"}, "ppm": {"type":"image/x-portable-pixmap"}, "pps": {"type":"application/vnd.ms-powerpoint","icon":"powerpoint","groups":["presentation"]}, -"ppsm": {"type":"application/vnd.ms-powerpoint.slideshow.macroenabled.12","icon":"powerpoint"}, -"ppsx": {"type":"application/vnd.openxmlformats-officedocument.presentationml.slideshow","icon":"powerpoint"}, +"ppsm": {"type":"application/vnd.ms-powerpoint.slideshow.macroenabled.12","icon":"powerpoint","groups":["presentation"]}, +"ppsx": {"type":"application/vnd.openxmlformats-officedocument.presentationml.slideshow","icon":"powerpoint","groups":["presentation"]}, "ppt": {"type":"application/vnd.ms-powerpoint","icon":"powerpoint","groups":["presentation"]}, -"pptm": {"type":"application/vnd.ms-powerpoint.presentation.macroenabled.12","icon":"powerpoint"}, -"pptx": {"type":"application/vnd.openxmlformats-officedocument.presentationml.presentation","icon":"powerpoint"}, +"pptm": {"type":"application/vnd.ms-powerpoint.presentation.macroenabled.12","icon":"powerpoint","groups":["presentation"]}, +"pptx": {"type":"application/vnd.openxmlformats-officedocument.presentationml.presentation","icon":"powerpoint","groups":["presentation"]}, "ppz": {"type":"application/mspowerpoint"}, "pqa": {"type":"application/vnd.palm"}, "prc": {"type":"application/x-mobipocket-ebook"}, @@ -786,11 +799,11 @@ "psf": {"type":"application/x-font-linux-psf"}, "pskcxml": {"type":"application/pskc+xml"}, "ptid": {"type":"application/vnd.pvi.ptid1"}, -"pub": {"type":"application/x-mspublisher","icon":"publisher"}, +"pub": {"type":"application/x-mspublisher","icon":"publisher","groups":["presentation"]}, "pvb": {"type":"application/vnd.3gpp.pic-bw-var"}, "pvu": {"type":"paleovu/x-pv"}, "pwn": {"type":"application/vnd.3m.post-it-notes"}, -"pwz": {"type":"application/vnd.ms-powerpoint","icon":"powerpoint"}, +"pwz": {"type":"application/vnd.ms-powerpoint","icon":"powerpoint","groups":["presentation"]}, "py": {"type":"text/x-script.phyton"}, "pya": {"type":"audio/vnd.ms-playready.media.pya"}, "pyc": {"type":"application/x-bytecode.python"}, @@ -815,7 +828,7 @@ "qxt": {"type":"application/vnd.quark.quarkxpress"}, "ra": {"type":"audio/x-realaudio-plugin","icon":"audio","string":"audio","groups":["audio","web_audio"]}, "ram": {"type":"audio/x-pn-realaudio-plugin","icon":"audio","string":"audio","groups":["audio"]}, -"rar": {"type":"application/x-rar-compressed"}, +"rar": {"type":"application/x-rar-compressed","icon":"archive","string":"archive","groups":["archive"]}, "ras": {"type":"image/x-cmu-raster"}, "rast": {"type":"image/cmu-raster"}, "rb": {"type":"text/plain"}, @@ -872,7 +885,7 @@ "scm": {"type":"application/vnd.lotus-screencam"}, "scq": {"type":"application/scvp-cv-request"}, "scs": {"type":"application/scvp-cv-response"}, -"scss": {"type":"text/x-scss"}, +"scss": {"type":"text/x-scss","icon":"text","groups":["web_file"]}, "scurl": {"type":"text/vnd.curl.scurl"}, "sda": {"type":"application/vnd.stardivision.draw","icon":"draw"}, "sdc": {"type":"application/vnd.stardivision.calc","icon":"calc"}, @@ -917,7 +930,7 @@ "skp": {"type":"application/vnd.koan"}, "skt": {"type":"application/vnd.koan"}, "sl": {"type":"application/x-seelogo"}, -"sldm": {"type":"application/vnd.ms-powerpoint.slide.macroenabled.12","icon":"powerpoint"}, +"sldm": {"type":"application/vnd.ms-powerpoint.slide.macroenabled.12","icon":"powerpoint","groups":["presentation"]}, "sldx": {"type":"application/vnd.openxmlformats-officedocument.presentationml.slide"}, "slt": {"type":"application/vnd.epson.salt"}, "sm": {"type":"application/vnd.stepmania.stepchart"}, @@ -957,7 +970,7 @@ "std": {"type":"application/vnd.sun.xml.draw.template","icon":"draw"}, "step": {"type":"application/step"}, "stf": {"type":"application/vnd.wt.stf"}, -"sti": {"type":"application/vnd.sun.xml.impress.template","icon":"impress"}, +"sti": {"type":"application/vnd.sun.xml.impress.template","icon":"impress","groups":["presentation"]}, "stk": {"type":"application/hyperstudio"}, "stl": {"type":"application/vnd.ms-pki.stl"}, "stp": {"type":"application/step"}, @@ -982,7 +995,7 @@ "sxc": {"type":"application/vnd.sun.xml.calc","icon":"calc"}, "sxd": {"type":"application/vnd.sun.xml.draw","icon":"draw"}, "sxg": {"type":"application/vnd.sun.xml.writer.global","icon":"writer"}, -"sxi": {"type":"application/vnd.sun.xml.impress","icon":"impress"}, +"sxi": {"type":"application/vnd.sun.xml.impress","icon":"impress","groups":["presentation"]}, "sxm": {"type":"application/vnd.sun.xml.math","icon":"math"}, "sxw": {"type":"application/vnd.sun.xml.writer","icon":"writer"}, "t": {"type":"text/troff"}, @@ -1016,6 +1029,7 @@ "tr": {"type":"text/troff"}, "tra": {"type":"application/vnd.trueapp"}, "trm": {"type":"application/x-msterminal"}, +"ts": {"type":"video/MP2T","icon":"mpeg","string":"video","groups":["video","web_video"]}, "tsd": {"type":"application/timestamped-data"}, "tsi": {"type":"audio/tsp-audio"}, "tsp": {"type":"application/dsptype"}, @@ -1028,7 +1042,7 @@ "twds": {"type":"application/vnd.simtech-mindmapper"}, "txd": {"type":"application/vnd.genomatix.tuxedo"}, "txf": {"type":"application/vnd.mobius.txf"}, -"txt": {"type":"text/plain","icon":"text"}, +"txt": {"type":"text/plain","icon":"text","defaulticon":true}, "udeb": {"type":"application/x-debian-package"}, "ufd": {"type":"application/vnd.ufdl"}, "ufdl": {"type":"application/vnd.ufdl"}, @@ -1104,7 +1118,7 @@ "vss": {"type":"application/vnd.visio"}, "vst": {"type":"application/vnd.visio"}, "vsw": {"type":"application/vnd.visio"}, -"vtt": {"type":"text/vtt"}, +"vtt": {"type":"text/vtt","icon":"text","groups":["html_track"]}, "vtu": {"type":"model/vnd.vtu"}, "vxml": {"type":"application/voicexml+xml"}, "w3d": {"type":"application/x-director"}, @@ -1112,7 +1126,7 @@ "w61": {"type":"application/wordperfect6.1"}, "w6w": {"type":"application/msword"}, "wad": {"type":"application/x-doom"}, -"wav": {"type":"audio/wav","icon":"wav","string":"audio","groups":["audio","web_audio"]}, +"wav": {"type":"audio/wav","icon":"wav","string":"audio","groups":["audio","html_audio","web_audio"]}, "wax": {"type":"audio/x-ms-wax"}, "wb1": {"type":"application/x-qpro"}, "wbmp": {"type":"image/vnd.wap.wbmp"}, @@ -1122,8 +1136,8 @@ "wdb": {"type":"application/vnd.ms-works"}, "wdp": {"type":"image/vnd.ms-photo"}, "web": {"type":"application/vnd.xara"}, -"weba": {"type":"audio/webm","icon":"audio","string":"audio","groups":["audio","web_audio"]}, -"webm": {"type":"video/webm","icon":"video","string":"video","groups":["video","web_video"]}, +"weba": {"type":"audio/webm","icon":"audio","string":"audio","groups":["audio","html_audio","web_audio"]}, +"webm": {"type":"video/webm","icon":"video","string":"video","groups":["html_video","video","web_video"]}, "webp": {"type":"image/webp"}, "wg": {"type":"application/vnd.pmi.widget"}, "wgt": {"type":"application/widget"}, @@ -1131,7 +1145,7 @@ "wk1": {"type":"application/x-123"}, "wks": {"type":"application/vnd.ms-works"}, "wm": {"type":"video/x-ms-wm"}, -"wma": {"type":"audio/x-ms-wma"}, +"wma": {"type":"audio/x-ms-wma","icon":"audio","string":"audio","groups":["audio"]}, "wmd": {"type":"application/x-ms-wmd"}, "wmf": {"type":"application/x-msmetafile"}, "wml": {"type":"text/vnd.wap.wml"}, @@ -1173,17 +1187,18 @@ "xar": {"type":"application/vnd.xara"}, "xbap": {"type":"application/x-ms-xbap"}, "xbd": {"type":"application/vnd.fujixerox.docuworks.binder"}, +"xbk": {"type":"application/x-smarttech-notebook","icon":"archive"}, "xbm": {"type":"image/x-xbitmap"}, "xdf": {"type":"application/xcap-diff+xml"}, "xdm": {"type":"application/vnd.syncml.dm+xml"}, -"xdp": {"type":"application/pdf","icon":"pdf"}, +"xdp": {"type":"application/vnd.adobe.xdp+xml","icon":"pdf"}, "xdr": {"type":"video/x-amt-demorun"}, "xdssc": {"type":"application/dssc+xml"}, "xdw": {"type":"application/vnd.fujixerox.docuworks"}, "xenc": {"type":"application/xenc+xml"}, "xer": {"type":"application/patch-ops-error+xml"}, -"xfd": {"type":"application/pdf","icon":"pdf"}, -"xfdf": {"type":"application/pdf","icon":"pdf"}, +"xfd": {"type":"application/vnd.xfdl","icon":"pdf"}, +"xfdf": {"type":"application/vnd.adobe.xfdf","icon":"pdf"}, "xfdl": {"type":"application/vnd.xfdl"}, "xgz": {"type":"xgl/drawing"}, "xht": {"type":"application/xhtml+xml"}, @@ -1203,7 +1218,7 @@ "xls": {"type":"application/vnd.ms-excel","icon":"spreadsheet","groups":["spreadsheet"]}, "xlsb": {"type":"application/vnd.ms-excel.sheet.binary.macroenabled.12","icon":"spreadsheet"}, "xlsm": {"type":"application/vnd.ms-excel.sheet.macroenabled.12","icon":"spreadsheet","groups":["spreadsheet"]}, -"xlsx": {"type":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","icon":"spreadsheet"}, +"xlsx": {"type":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","icon":"spreadsheet","groups":["spreadsheet"]}, "xlt": {"type":"application/vnd.ms-excel","icon":"spreadsheet"}, "xltm": {"type":"application/vnd.ms-excel.template.macroenabled.12","icon":"spreadsheet"}, "xltx": {"type":"application/vnd.openxmlformats-officedocument.spreadsheetml.template","icon":"spreadsheet"}, diff --git a/src/assets/img/files/h5p-64.png b/src/assets/img/files/h5p-64.png new file mode 100644 index 00000000000..cdd1c9b1bc6 Binary files /dev/null and b/src/assets/img/files/h5p-64.png differ diff --git a/src/assets/img/login/faq_url.png b/src/assets/img/login/faq_url.png new file mode 100644 index 00000000000..13d92cd502b Binary files /dev/null and b/src/assets/img/login/faq_url.png differ diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 51b1c753dab..e33e9f8abd8 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1331,7 +1331,7 @@ "core.block.blocks": "Blocks", "core.browser": "Browser", "core.cancel": "Cancel", - "core.cannotconnect": "Cannot connect: Verify that you have correctly typed the URL and that your site uses Moodle {{$a}} or later.", + "core.cannotconnect": "Cannot connect: Verify that you have correctly typed your site address.", "core.cannotdownloadfiles": "File downloading is disabled. Please contact your site administrator.", "core.captureaudio": "Record audio", "core.capturedimage": "Taken picture.", @@ -1707,7 +1707,17 @@ "core.login.emailnotmatch": "Emails do not match", "core.login.erroraccesscontrolalloworigin": "The cross-origin call you're trying to perform has been rejected. Please check https://docs.moodle.org/dev/Moodle_Mobile_development_using_Chrome_or_Chromium", "core.login.errordeletesite": "An error occurred while deleting this site. Please try again.", + "core.login.errorexampleurl": "The URL https://campus.example.edu is only an example URL, it's not a real site. Please use the URL of your school or organization's site.", "core.login.errorupdatesite": "An error occurred while updating the site's token.", + "core.login.faqcannotconnectanswer": "Please, contact your site administrator.", + "core.login.faqcannotconnectquestion": "I typed my site address correctly but I still can't connect.", + "core.login.faqsetupsiteanswer": "Visit {{$link}} to check out the different options you have to create your own Moodle site.", + "core.login.faqsetupsitelinktitle": "Get started.", + "core.login.faqsetupsitequestion": "I want to set up my own Moodle site.", + "core.login.faqtestappanswer": "To test the app in a Moodle Demo Site, type \"teacher\" or \"student\" in the \"Your site address\" field and click the \"Connect!\" button.", + "core.login.faqtestappquestion": "I just want to test the app, what can I do?", + "core.login.faqwhatisurlanswer": "

Every organisation or school has their own custom address for their Moodle site.

To find the address of the Moodle site you want to connect to, do the following:

  1. Open a web browser and go to your school's or organisation's Moodle site login page
  2. At the top of the page, on the address bar, you will see the URL of your Moodle site. E.g. \"campus.example.edu\".{{$image}}
  3. Copy the address (do not copy the /login and what comes after), paste it into the Moodle App and click \"Connect!\"
  4. Now you can log into your site, using your username and password
  5. ", + "core.login.faqwhatisurlquestion": "What is the URL of my Moodle site? How can I find my school’s site?", "core.login.findyoursite": "Find your site", "core.login.firsttime": "Is this your first time here?", "core.login.forcepasswordchangenotice": "You must change your password to proceed.", @@ -1736,7 +1746,6 @@ "core.login.mobileservicesnotenabled": "Mobile access is not enabled on your site. Please contact your site administrator if you think it should be enabled.", "core.login.mustconfirm": "You need to confirm your account", "core.login.newaccount": "New account", - "core.login.newsitedescription": "Please enter the URL of your Moodle site. Note that it might not be configured to work with this app.", "core.login.notloggedin": "You need to be logged in.", "core.login.password": "Password", "core.login.passwordforgotten": "Forgotten password", @@ -1762,7 +1771,7 @@ "core.login.selectacountry": "Select a country", "core.login.selectsite": "Please select your site:", "core.login.signupplugindisabled": "{{$a}} is not enabled.", - "core.login.siteaddress": "Site address", + "core.login.siteaddress": "Your site address", "core.login.sitehasredirect": "Your site contains at least one HTTP redirect. The app cannot follow redirects, this could be the issue that's preventing the app from connecting to your site.", "core.login.siteinmaintenance": "Your site is in maintenance mode", "core.login.sitepolicynotagreederror": "Site policy not agreed.", @@ -1816,6 +1825,7 @@ "core.more": "more", "core.mygroups": "My groups", "core.name": "Name", + "core.needhelp": "Need help?", "core.networkerroriframemsg": "This content is not available offline. Please connect to the internet and try again.", "core.networkerrormsg": "There was a problem connecting to the site. Please check your connection and try again.", "core.never": "Never", @@ -2090,6 +2100,7 @@ "core.warningofflinedatadeleted": "Offline data from {{component}} '{{name}}' has been deleted. {{error}}", "core.whatisyourage": "What is your age?", "core.wheredoyoulive": "In which country do you live?", + "core.whoissiteadmin": "\"Site Administrators\" are the people who manage the Moodle at your school/university/company or learning organisation. If you don't know how to contact them, please contact your teachers/trainers.", "core.whoops": "Oops!", "core.whyisthishappening": "Why is this happening?", "core.whyisthisrequired": "Why is this required?", diff --git a/src/assets/mimetoext.json b/src/assets/mimetoext.json index 842fcf09d07..438731f8b69 100644 --- a/src/assets/mimetoext.json +++ b/src/assets/mimetoext.json @@ -20,6 +20,7 @@ "application/clariscad": ["ccad"], "application/commonground": ["dp"], "application/cu-seeme": ["cu"], +"application/dash+xml": ["mpd"], "application/davmount+xml": ["davmount"], "application/docbook+xml": ["dbk"], "application/drafting": ["drw"], @@ -71,6 +72,7 @@ "application/mac-compactpro": ["cpt"], "application/macbinary": ["bin"], "application/mads+xml": ["mads"], +"application/maple": ["mw","mws"], "application/marc": ["mrc"], "application/marcxml+xml": ["mrcx"], "application/mathematica": ["ma","mb","nb"], @@ -355,6 +357,7 @@ "application/vnd.mobius.plc": ["plc"], "application/vnd.mobius.txf": ["txf"], "application/vnd.moodle.backup": ["mbz"], +"application/vnd.moodle.profiling": ["mpr"], "application/vnd.mophun.application": ["mpn"], "application/vnd.mophun.certificate": ["mpc"], "application/vnd.mozilla.xul+xml": ["xul"], @@ -520,7 +523,7 @@ "application/vnd.wqd": ["wqd"], "application/vnd.wt.stf": ["stf"], "application/vnd.xara": ["xar","web"], -"application/vnd.xfdl": ["xfdl"], +"application/vnd.xfdl": ["xfdl","xfd"], "application/vnd.yamaha.hv-dic": ["hvd"], "application/vnd.yamaha.hv-script": ["hvs"], "application/vnd.yamaha.hv-voice": ["hvp"], @@ -579,6 +582,7 @@ "application/x-debian-package": ["deb","udeb"], "application/x-deepv": ["deepv"], "application/x-dgc-compressed": ["dgc"], +"application/x-digidoc": ["bdoc","cdoc","ddoc"], "application/x-director": ["cct","cst","cxt","dcr","dir","dxr","fgd","swa","w3d"], "application/x-doom": ["wad"], "application/x-dtbncx+xml": ["ncx"], @@ -709,6 +713,7 @@ "application/x-shockwave-flash": ["swf","swfl"], "application/x-silverlight-app": ["xap"], "application/x-sit": ["sit"], +"application/x-smarttech-notebook": ["gallery","gallerycollection","galleryitem","nbk","notebook","xbk"], "application/x-sprite": ["spr","sprite"], "application/x-sql": ["sql"], "application/x-stuffit": ["sit"], @@ -762,13 +767,14 @@ "application/xv+xml": ["mxml","xhvml","xvm","xvml"], "application/yang": ["yang"], "application/yin+xml": ["yin"], -"application/zip": ["zip"], +"application/zip": ["zip","h5p"], "audio/aac": ["aac"], "audio/adpcm": ["adp"], "audio/aiff": ["aif","aifc","aiff"], "audio/amr": ["amr"], "audio/au": ["au"], "audio/basic": ["au","snd"], +"audio/flac": ["flac"], "audio/it": ["it"], "audio/make": ["funk","my","pfunk"], "audio/make.my.funk": ["pfunk"], @@ -816,7 +822,7 @@ "audio/x-mod": ["mod"], "audio/x-mpeg": ["mp2"], "audio/x-mpeg-3": ["mp3"], -"audio/x-mpegurl": ["m3u"], +"audio/x-mpegurl": ["m3u","m3u8"], "audio/x-mpequrl": ["m3u"], "audio/x-ms-wax": ["wax"], "audio/x-ms-wma": ["wma"], @@ -1026,8 +1032,9 @@ "video/jpeg": ["jpgv"], "video/jpm": ["jpgm","jpm"], "video/mj2": ["mj2","mjp2"], -"video/mp4": ["mp4","f4v","m4v","mp4v","mpg4"], +"video/mp4": ["mp4","f4v","m4v","mp4v","mpg4","fmp4"], "video/mpeg": ["mpeg","m1v","m2v","mp2","mp3","mpa","mpe","mpg"], +"video/MP2T": ["ts"], "video/msvideo": ["avi"], "video/ogg": ["ogv"], "video/quicktime": ["mov","3gp","moov","qt"], diff --git a/src/config.json b/src/config.json index 99c9ee8f7ae..b90656877c7 100644 --- a/src/config.json +++ b/src/config.json @@ -2,8 +2,8 @@ "app_id": "com.moodle.moodlemobile", "appname": "Moodle Mobile", "desktopappname": "Moodle Desktop", - "versioncode": 3810, - "versionname": "3.8.1-dev", + "versioncode": 3820, + "versionname": "3.8.2", "cache_update_frequency_usually": 420000, "cache_update_frequency_often": 1200000, "cache_update_frequency_sometimes": 3600000, diff --git a/src/core/compile/providers/compile.ts b/src/core/compile/providers/compile.ts index 8ad107f6a64..51cbc8afd8e 100644 --- a/src/core/compile/providers/compile.ts +++ b/src/core/compile/providers/compile.ts @@ -39,6 +39,8 @@ import { CORE_SITEHOME_PROVIDERS } from '@core/sitehome/sitehome.module'; import { CORE_USER_PROVIDERS } from '@core/user/user.module'; import { CORE_PUSHNOTIFICATIONS_PROVIDERS } from '@core/pushnotifications/pushnotifications.module'; import { IONIC_NATIVE_PROVIDERS } from '@core/emulator/emulator.module'; +import { CORE_EDITOR_PROVIDERS } from '@core/editor/editor.module'; +import { CORE_SEARCH_PROVIDERS } from '@core/search/search.module'; // Import only this provider to prevent circular dependencies. import { CoreSitePluginsProvider } from '@core/siteplugins/providers/siteplugins'; @@ -75,6 +77,8 @@ import { CoreSiteHomeComponentsModule } from '@core/sitehome/components/componen import { CoreUserComponentsModule } from '@core/user/components/components.module'; import { CoreQuestionComponentsModule } from '@core/question/components/components.module'; import { CoreBlockComponentsModule } from '@core/block/components/components.module'; +import { CoreEditorComponentsModule } from '@core/editor/components/components.module'; +import { CoreSearchComponentsModule } from '@core/search/components/components.module'; // Import some components listed in entryComponents so they can be injected dynamically. import { CoreCourseUnsupportedModuleComponent } from '@core/course/components/unsupported-module/unsupported-module'; @@ -144,7 +148,7 @@ export class CoreCompileProvider { IonicModule, TranslateModule.forChild(), CoreComponentsModule, CoreDirectivesModule, CorePipesModule, CoreCourseComponentsModule, CoreCoursesComponentsModule, CoreSiteHomeComponentsModule, CoreUserComponentsModule, CoreCourseDirectivesModule, CoreSitePluginsDirectivesModule, CoreQuestionComponentsModule, AddonModAssignComponentsModule, - AddonModWorkshopComponentsModule, CoreBlockComponentsModule + AddonModWorkshopComponentsModule, CoreBlockComponentsModule, CoreEditorComponentsModule, CoreSearchComponentsModule ]; constructor(protected injector: Injector, logger: CoreLoggerProvider, compilerFactory: JitCompilerFactory) { @@ -237,7 +241,8 @@ export class CoreCompileProvider { .concat(ADDON_MOD_SURVEY_PROVIDERS).concat(ADDON_MOD_URL_PROVIDERS).concat(ADDON_MOD_WIKI_PROVIDERS) .concat(ADDON_MOD_WORKSHOP_PROVIDERS).concat(ADDON_NOTES_PROVIDERS).concat(ADDON_NOTIFICATIONS_PROVIDERS) .concat(CORE_PUSHNOTIFICATIONS_PROVIDERS).concat(ADDON_REMOTETHEMES_PROVIDERS).concat(CORE_BLOCK_PROVIDERS) - .concat(CORE_FILTER_PROVIDERS).concat(CORE_H5P_PROVIDERS); + .concat(CORE_FILTER_PROVIDERS).concat(CORE_H5P_PROVIDERS).concat(CORE_EDITOR_PROVIDERS) + .concat(CORE_SEARCH_PROVIDERS); // We cannot inject anything to this constructor. Use the Injector to inject all the providers into the instance. for (const i in providers) { diff --git a/src/core/editor/editor.module.ts b/src/core/editor/editor.module.ts index e55c88a493c..b34cb47e16a 100644 --- a/src/core/editor/editor.module.ts +++ b/src/core/editor/editor.module.ts @@ -17,7 +17,7 @@ import { CoreEditorComponentsModule } from './components/components.module'; import { CoreEditorOfflineProvider } from './providers/editor-offline'; // List of providers (without handlers). -export const CORE_GRADES_PROVIDERS: any[] = [ +export const CORE_EDITOR_PROVIDERS: any[] = [ CoreEditorOfflineProvider, ]; diff --git a/src/core/emulator/providers/capture-helper.ts b/src/core/emulator/providers/capture-helper.ts index e20fb64d856..ad09550aa96 100644 --- a/src/core/emulator/providers/capture-helper.ts +++ b/src/core/emulator/providers/capture-helper.ts @@ -99,7 +99,7 @@ export class CoreEmulatorCaptureHelperProvider { params.maxTime = options.duration * 1000; } - modal = this.modalCtrl.create('CoreEmulatorCaptureMediaPage', params); + modal = this.modalCtrl.create('CoreEmulatorCaptureMediaPage', params, { cssClass: 'core-modal-fullscreen' }); modal.present(); modal.onDidDismiss((data: any, role: string) => { if (role == 'success') { diff --git a/src/core/fileuploader/providers/fileuploader.ts b/src/core/fileuploader/providers/fileuploader.ts index a061b8e2925..d5c2fcda385 100644 --- a/src/core/fileuploader/providers/fileuploader.ts +++ b/src/core/fileuploader/providers/fileuploader.ts @@ -298,12 +298,18 @@ export class CoreFileUploaderProvider { * @return Undefined if file is valid, error message if file is invalid. */ isInvalidMimetype(mimetypes?: string[], path?: string, mimetype?: string): string { - let extension; + let extension: string; if (mimetypes) { // Verify that the mimetype of the file is supported. if (mimetype) { extension = this.mimeUtils.getExtension(mimetype); + + if (mimetypes.indexOf(mimetype) == -1) { + // Get the "main" mimetype of the extension. + // It's possible that the list of accepted mimetypes only includes the "main" mimetypes. + mimetype = this.mimeUtils.getMimeType(extension); + } } else { extension = this.mimeUtils.getFileExtension(path); mimetype = this.mimeUtils.getMimeType(extension); diff --git a/src/core/login/lang/en.json b/src/core/login/lang/en.json index 054a5116818..3624b10636c 100644 --- a/src/core/login/lang/en.json +++ b/src/core/login/lang/en.json @@ -24,7 +24,17 @@ "emailnotmatch": "Emails do not match", "erroraccesscontrolalloworigin": "The cross-origin call you're trying to perform has been rejected. Please check https://docs.moodle.org/dev/Moodle_Mobile_development_using_Chrome_or_Chromium", "errordeletesite": "An error occurred while deleting this site. Please try again.", + "errorexampleurl": "The URL https://campus.example.edu is only an example URL, it's not a real site. Please use the URL of your school or organization's site.", "errorupdatesite": "An error occurred while updating the site's token.", + "faqcannotconnectanswer": "Please, contact your site administrator.", + "faqcannotconnectquestion": "I typed my site address correctly but I still can't connect.", + "faqsetupsiteanswer": "Visit {{$link}} to check out the different options you have to create your own Moodle site.", + "faqsetupsitelinktitle": "Get started.", + "faqsetupsitequestion": "I want to set up my own Moodle site.", + "faqtestappanswer": "To test the app in a Moodle Demo Site, type \"teacher\" or \"student\" in the \"Your site address\" field and click the \"Connect!\" button.", + "faqtestappquestion": "I just want to test the app, what can I do?", + "faqwhatisurlanswer": "

    Every organisation or school has their own custom address for their Moodle site.

    To find the address of the Moodle site you want to connect to, do the following:

    1. Open a web browser and go to your school's or organisation's Moodle site login page
    2. At the top of the page, on the address bar, you will see the URL of your Moodle site. E.g. \"campus.example.edu\".{{$image}}
    3. Copy the address (do not copy the /login and what comes after), paste it into the Moodle App and click \"Connect!\"
    4. Now you can log into your site, using your username and password
    5. ", + "faqwhatisurlquestion": "What is the URL of my Moodle site? How can I find my school’s site?", "findyoursite": "Find your site", "firsttime": "Is this your first time here?", "forcepasswordchangenotice": "You must change your password to proceed.", @@ -53,7 +63,6 @@ "mobileservicesnotenabled": "Mobile access is not enabled on your site. Please contact your site administrator if you think it should be enabled.", "mustconfirm": "You need to confirm your account", "newaccount": "New account", - "newsitedescription": "Please enter the URL of your Moodle site. Note that it might not be configured to work with this app.", "notloggedin": "You need to be logged in.", "password": "Password", "passwordforgotten": "Forgotten password", @@ -79,7 +88,7 @@ "selectacountry": "Select a country", "selectsite": "Please select your site:", "signupplugindisabled": "{{$a}} is not enabled.", - "siteaddress": "Site address", + "siteaddress": "Your site address", "sitehasredirect": "Your site contains at least one HTTP redirect. The app cannot follow redirects, this could be the issue that's preventing the app from connecting to your site.", "siteinmaintenance": "Your site is in maintenance mode", "sitepolicynotagreederror": "Site policy not agreed.", diff --git a/src/core/login/pages/init/init.ts b/src/core/login/pages/init/init.ts index b7ea6435279..baa1218bd17 100644 --- a/src/core/login/pages/init/init.ts +++ b/src/core/login/pages/init/init.ts @@ -91,16 +91,7 @@ export class CoreLoginInitPage { }); } - return this.sitesProvider.getCurrentSite().getPublicConfig().catch(() => { - return {}; - }).then((config) => { - return this.sitesProvider.checkRequiredMinimumVersion(config).then(() => { - // User is logged in, go to site initial page. - return this.loginHelper.goToSiteInitialPage(); - }).catch(() => { - return this.loadPage(); - }); - }); + return this.loginHelper.goToSiteInitialPage(); } return this.navCtrl.setRoot('CoreLoginSitesPage'); diff --git a/src/core/login/pages/site-help/site-help.html b/src/core/login/pages/site-help/site-help.html index ae21bace1dd..2aa5a82473f 100644 --- a/src/core/login/pages/site-help/site-help.html +++ b/src/core/login/pages/site-help/site-help.html @@ -10,5 +10,31 @@ - + + +

      {{ 'core.login.faqwhatisurlquestion' | translate }}

      +
      + +
      +
      +
      + +

      {{ 'core.login.faqcannotconnectquestion' | translate }}

      +
      + +

      {{ 'core.login.faqcannotconnectanswer' | translate }} {{ 'core.whoissiteadmin' | translate }}

      +
      + +

      {{ 'core.login.faqsetupsitequestion' | translate }}

      +
      + +

      +
      + +

      {{ 'core.login.faqtestappquestion' | translate }}

      +
      + +

      {{ 'core.login.faqtestappanswer' | translate }}

      +
      +
      diff --git a/src/core/login/pages/site-help/site-help.scss b/src/core/login/pages/site-help/site-help.scss new file mode 100644 index 00000000000..01699c80f03 --- /dev/null +++ b/src/core/login/pages/site-help/site-help.scss @@ -0,0 +1,5 @@ +page-core-login-site-help { + .content { + background-color: $white; + } +} \ No newline at end of file diff --git a/src/core/login/pages/site-help/site-help.ts b/src/core/login/pages/site-help/site-help.ts index 90d948b75fa..eb489e3c262 100644 --- a/src/core/login/pages/site-help/site-help.ts +++ b/src/core/login/pages/site-help/site-help.ts @@ -14,6 +14,7 @@ import { Component } from '@angular/core'; import { IonicPage, ViewController } from 'ionic-angular'; +import { TranslateService } from '@ngx-translate/core'; /** * Component that displays some help regarding the CoreLoginSitePage. @@ -24,7 +25,17 @@ import { IonicPage, ViewController } from 'ionic-angular'; templateUrl: 'site-help.html', }) export class CoreLoginSiteHelpPage { - constructor(private viewCtrl: ViewController) { } + + urlImageHtml: string; + setupLinkHtml: string; + + constructor(protected viewCtrl: ViewController, + protected translate: TranslateService) { + + this.urlImageHtml = ''; + this.setupLinkHtml = 'https://moodle.com/getstarted/'; + } /** * Close help modal. diff --git a/src/core/login/pages/site/site.html b/src/core/login/pages/site/site.html index 8da75c237ec..6d13b7507b0 100644 --- a/src/core/login/pages/site/site.html +++ b/src/core/login/pages/site/site.html @@ -6,9 +6,6 @@ - @@ -20,9 +17,9 @@
      -

      {{ 'core.login.newsitedescription' | translate }}

      - +

      {{ 'core.login.siteaddress' | translate }}

      +
      @@ -50,5 +47,36 @@

      {{site.name}}

      {{ 'core.login.selectsite' | translate }}

      {{site.name}} + + +
      + + + {{ 'core.whoops' | translate }} + + +

      + +

      {{ 'core.login.problemconnectingerror' | translate }}

      +

      {{ error.url }}

      +

      {{ 'core.login.problemconnectingerrorcontinue' | translate }}

      +
      +
      + + {{ 'core.login.stillcantconnect' | translate }} + + +

      {{ 'core.login.contactyouradministrator' | translate }}

      +

      {{ 'core.whoissiteadmin' | translate }}

      +
      +
      +
      + + + + + diff --git a/src/core/login/pages/site/site.scss b/src/core/login/pages/site/site.scss index 53fafed9133..0a740cead7f 100644 --- a/src/core/login/pages/site/site.scss +++ b/src/core/login/pages/site/site.scss @@ -10,4 +10,24 @@ ion-app.app-root page-core-login-site { background-color: $searchbar-ios-toolbar-input-background; } } + + .core-site-error { + background: $red-light; + margin-left: 0; + margin-right: 0; + width: 100%; + user-select: text; + + p, ion-card-header { + color: $red-dark; + user-select: text; + } + ion-card-header { + font-weight: bold; + } + } + + .core-login-need-help { + text-decoration: underline; + } } \ No newline at end of file diff --git a/src/core/login/pages/site/site.ts b/src/core/login/pages/site/site.ts index 9e44cbd4f0f..ebf6cfcaf1b 100644 --- a/src/core/login/pages/site/site.ts +++ b/src/core/login/pages/site/site.ts @@ -18,10 +18,32 @@ import { CoreAppProvider } from '@providers/app'; import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider, CoreSiteCheckResponse } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { CoreUrlUtilsProvider } from '@providers/utils/url'; import { CoreConfigConstants } from '../../../../configconstants'; import { CoreLoginHelperProvider } from '../../providers/helper'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { CoreUrl } from '@classes/utils/url'; +import { TranslateService } from '@ngx-translate/core'; + +/** + * Data about an error when connecting to a site. + */ +type CoreLoginSiteError = { + /** + * The error message that ocurred. + */ + message: string; + + /** + * URL the user entered. + */ + url?: string; + + /** + * URL the user entered with protocol added if needed. + */ + fullUrl?: string; +}; /** * Page to enter or select the site URL to connect to. @@ -41,6 +63,7 @@ export class CoreLoginSitePage { fixedDisplay = 'buttons'; showKeyboard = false; filter = ''; + error: CoreLoginSiteError; constructor(navParams: NavParams, protected navCtrl: NavController, @@ -50,7 +73,9 @@ export class CoreLoginSitePage { protected loginHelper: CoreLoginHelperProvider, protected modalCtrl: ModalController, protected domUtils: CoreDomUtilsProvider, - protected eventsProvider: CoreEventsProvider) { + protected eventsProvider: CoreEventsProvider, + protected translate: TranslateService, + protected urlUtils: CoreUrlUtilsProvider) { this.showKeyboard = !!navParams.get('showKeyboard'); @@ -99,6 +124,14 @@ export class CoreLoginSitePage { url = url.trim(); + if (url.match(/^(https?:\/\/)?campus\.example\.edu/)) { + this.showLoginIssue(null, this.translate.instant('core.login.errorexampleurl')); + + return; + } + + this.hideLoginIssue(); + const modal = this.domUtils.showModalLoading(), siteData = this.sitesProvider.getDemoSiteData(url); @@ -164,6 +197,13 @@ export class CoreLoginSitePage { modal.present(); } + /** + * Hide the login error. + */ + protected hideLoginIssue(): void { + this.error = null; + } + /** * Show an error that aims people to solve the issue. * @@ -171,12 +211,14 @@ export class CoreLoginSitePage { * @param error Error to display. */ protected showLoginIssue(url: string, error: any): void { - const modal = this.modalCtrl.create('CoreLoginSiteErrorPage', { - siteUrl: url, - issue: this.domUtils.getErrorMessage(error) - }); + this.error = { + url: url, + message: this.domUtils.getErrorMessage(error), + }; - modal.present(); + if (url) { + this.error.fullUrl = this.urlUtils.isAbsoluteURL(url) ? url : 'https://' + url; + } } /** diff --git a/src/core/search/search.module.ts b/src/core/search/search.module.ts index 4026fb89897..2ea1e8d63ff 100644 --- a/src/core/search/search.module.ts +++ b/src/core/search/search.module.ts @@ -16,6 +16,11 @@ import { NgModule } from '@angular/core'; import { CoreSearchComponentsModule } from './components/components.module'; import { CoreSearchHistoryProvider } from './providers/search-history'; +// List of providers (without handlers). +export const CORE_SEARCH_PROVIDERS: any[] = [ + CoreSearchHistoryProvider, +]; + @NgModule({ declarations: [ ], diff --git a/src/directives/format-text.ts b/src/directives/format-text.ts index dc178bedca5..7057b269f1f 100644 --- a/src/directives/format-text.ts +++ b/src/directives/format-text.ts @@ -221,7 +221,7 @@ export class CoreFormatTextDirective implements OnChanges { anchor.addEventListener('click', (e: Event) => { e.preventDefault(); e.stopPropagation(); - this.domUtils.viewImage(imgSrc, img.getAttribute('alt'), this.component, this.componentId); + this.domUtils.viewImage(imgSrc, img.getAttribute('alt'), this.component, this.componentId, true); }); img.parentNode.appendChild(anchor); diff --git a/src/lang/en.json b/src/lang/en.json index 876b80259e2..3b9ccff0fbb 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -12,7 +12,7 @@ "back": "Back", "browser": "Browser", "cancel": "Cancel", - "cannotconnect": "Cannot connect: Verify that you have correctly typed the URL and that your site uses Moodle {{$a}} or later.", + "cannotconnect": "Cannot connect: Verify that you have correctly typed your site address.", "cannotdownloadfiles": "File downloading is disabled. Please contact your site administrator.", "captureaudio": "Record audio", "capturedimage": "Taken picture.", @@ -167,6 +167,7 @@ "more": "more", "mygroups": "My groups", "name": "Name", + "needhelp": "Need help?", "networkerroriframemsg": "This content is not available offline. Please connect to the internet and try again.", "networkerrormsg": "There was a problem connecting to the site. Please check your connection and try again.", "never": "Never", @@ -293,6 +294,7 @@ "warningofflinedatadeleted": "Offline data from {{component}} '{{name}}' has been deleted. {{error}}", "whatisyourage": "What is your age?", "wheredoyoulive": "In which country do you live?", + "whoissiteadmin": "\"Site Administrators\" are the people who manage the Moodle at your school/university/company or learning organisation. If you don't know how to contact them, please contact your teachers/trainers.", "whoops": "Oops!", "whyisthishappening": "Why is this happening?", "whyisthisrequired": "Why is this required?", diff --git a/src/providers/handlers/site-info-cron-handler.ts b/src/providers/handlers/site-info-cron-handler.ts index c8e39cd58cd..32f23b92951 100644 --- a/src/providers/handlers/site-info-cron-handler.ts +++ b/src/providers/handlers/site-info-cron-handler.ts @@ -48,7 +48,7 @@ export class CoreSiteInfoCronHandler implements CoreCronHandler { * @return Interval time (in milliseconds). */ getInterval(): number { - return 3600000; // 1 hour. + return 10800000; // 3 hours. } /** diff --git a/src/providers/utils/dom.ts b/src/providers/utils/dom.ts index 35055cbb1ec..c692faf657e 100644 --- a/src/providers/utils/dom.ts +++ b/src/providers/utils/dom.ts @@ -1561,25 +1561,26 @@ export class CoreDomUtilsProvider { } /** - * View an image in a new page or modal. + * View an image in a modal. * * @param image URL of the image. * @param title Title of the page or modal. * @param component Component to link the image to if needed. * @param componentId An ID to use in conjunction with the component. + * @param fullScreen Whether the modal should be full screen. */ - viewImage(image: string, title?: string, component?: string, componentId?: string | number): void { + viewImage(image: string, title?: string, component?: string, componentId?: string | number, fullScreen?: boolean): void { if (image) { const params: any = { - title: title, - image: image, - component: component, - componentId: componentId - }, - modal = this.modalCtrl.create('CoreViewerImagePage', params); + title: title, + image: image, + component: component, + componentId: componentId, + }; + const options = fullScreen ? { cssClass: 'core-modal-fullscreen' } : {}; + const modal = this.modalCtrl.create('CoreViewerImagePage', params, options); modal.present(); } - } /** diff --git a/src/providers/ws.ts b/src/providers/ws.ts index c13af220f94..8440316ae14 100644 --- a/src/providers/ws.ts +++ b/src/providers/ws.ts @@ -171,6 +171,7 @@ export class CoreWSProvider { /** * Call a Moodle WS using the AJAX API. Please use it if the WS layer is not an option. + * It uses a cache to prevent duplicate requests. * * @param method The WebService method to be called. * @param data Arguments to pass to the method. @@ -181,79 +182,19 @@ export class CoreWSProvider { * - available: 0 if unknown, 1 if available, -1 if not available. */ callAjax(method: string, data: any, preSets: CoreWSAjaxPreSets): Promise { - let promise; - - if (typeof preSets.siteUrl == 'undefined') { - return rejectWithError(this.createFakeWSError('core.unexpectederror', true)); - } else if (!this.appProvider.isOnline()) { - return rejectWithError(this.createFakeWSError('core.networkerrormsg', true)); - } - - if (typeof preSets.responseExpected == 'undefined') { - preSets.responseExpected = true; - } - - const script = preSets.noLogin ? 'service-nologin.php' : 'service.php', - ajaxData = JSON.stringify([{ - index: 0, - methodname: method, - args: this.convertValuesToString(data) - }]); + const cacheParams = { + methodname: method, + args: data, + }; - // The info= parameter has no function. It is just to help with debugging. - // We call it info to match the parameter name use by Moodle's AMD ajax module. - let siteUrl = preSets.siteUrl + '/lib/ajax/' + script + '?info=' + method; + let promise = this.getPromiseHttp('ajax', preSets.siteUrl, cacheParams); - if (preSets.noLogin && preSets.useGet) { - // Send params using GET. - siteUrl += '&args=' + encodeURIComponent(ajaxData); - promise = this.http.get(siteUrl).timeout(this.getRequestTimeout()).toPromise(); - } else { - promise = this.http.post(siteUrl, ajaxData).timeout(this.getRequestTimeout()).toPromise(); + if (!promise) { + promise = this.performAjax(method, data, preSets); + promise = this.setPromiseHttp(promise, 'ajax', preSets.siteUrl, cacheParams); } - return promise.then((data: any) => { - // Some moodle web services return null. - // If the responseExpected value is set then so long as no data is returned, we create a blank object. - if (!data && !preSets.responseExpected) { - data = [{}]; - } - - // Check if error. Ajax layer should always return an object (if error) or an array (if success). - if (!data || typeof data != 'object') { - return rejectWithError(this.createFakeWSError('core.serverconnection', true)); - } else if (data.error) { - return rejectWithError(data); - } - - // Get the first response since only one request was done. - data = data[0]; - - if (data.error) { - return rejectWithError(data.exception); - } - - return data.data; - }, (data) => { - const available = data.status == 404 ? -1 : 0; - - return rejectWithError(this.createFakeWSError('core.serverconnection', true), available); - }); - - // Convenience function to return an error. - function rejectWithError(exception: any, available?: number): Promise { - if (typeof available == 'undefined') { - if (exception.errorcode) { - available = exception.errorcode == 'invalidrecord' ? -1 : 1; - } else { - available = 0; - } - } - - exception.available = available; - - return Promise.reject(exception); - } + return promise; } /** @@ -496,6 +437,94 @@ export class CoreWSProvider { return method + '#' + Md5.hashAsciiStr(url); } + /** + * Call a Moodle WS using the AJAX API. + * + * @param method The WebService method to be called. + * @param data Arguments to pass to the method. + * @param preSets Extra settings and information. Only some + * @return Promise resolved with the response data in success and rejected with an object containing: + * - error: Error message. + * - errorcode: Error code returned by the site (if any). + * - available: 0 if unknown, 1 if available, -1 if not available. + */ + protected performAjax(method: string, data: any, preSets: CoreWSAjaxPreSets): Promise { + + let promise; + + if (typeof preSets.siteUrl == 'undefined') { + return rejectWithError(this.createFakeWSError('core.unexpectederror', true)); + } else if (!this.appProvider.isOnline()) { + return rejectWithError(this.createFakeWSError('core.networkerrormsg', true)); + } + + if (typeof preSets.responseExpected == 'undefined') { + preSets.responseExpected = true; + } + + const script = preSets.noLogin ? 'service-nologin.php' : 'service.php', + ajaxData = JSON.stringify([{ + index: 0, + methodname: method, + args: this.convertValuesToString(data) + }]); + + // The info= parameter has no function. It is just to help with debugging. + // We call it info to match the parameter name use by Moodle's AMD ajax module. + let siteUrl = preSets.siteUrl + '/lib/ajax/' + script + '?info=' + method; + + if (preSets.noLogin && preSets.useGet) { + // Send params using GET. + siteUrl += '&args=' + encodeURIComponent(ajaxData); + promise = this.http.get(siteUrl).timeout(this.getRequestTimeout()).toPromise(); + } else { + promise = this.http.post(siteUrl, ajaxData).timeout(this.getRequestTimeout()).toPromise(); + } + + return promise.then((data: any) => { + // Some moodle web services return null. + // If the responseExpected value is set then so long as no data is returned, we create a blank object. + if (!data && !preSets.responseExpected) { + data = [{}]; + } + + // Check if error. Ajax layer should always return an object (if error) or an array (if success). + if (!data || typeof data != 'object') { + return rejectWithError(this.createFakeWSError('core.serverconnection', true)); + } else if (data.error) { + return rejectWithError(data); + } + + // Get the first response since only one request was done. + data = data[0]; + + if (data.error) { + return rejectWithError(data.exception); + } + + return data.data; + }, (data) => { + const available = data.status == 404 ? -1 : 0; + + return rejectWithError(this.createFakeWSError('core.serverconnection', true), available); + }); + + // Convenience function to return an error. + function rejectWithError(exception: any, available?: number): Promise { + if (typeof available == 'undefined') { + if (exception.errorcode) { + available = exception.errorcode == 'invalidrecord' ? -1 : 1; + } else { + available = 0; + } + } + + exception.available = available; + + return Promise.reject(exception); + } + } + /** * Perform a HEAD request and save the promise while waiting to be resolved. *