commit
221b1f51cb
|
@ -64,7 +64,7 @@
|
|||
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|screenLayout|smallestScreenSize" android:debuggable="true" />
|
||||
</edit-config>
|
||||
<edit-config file="AndroidManifest.xml" mode="merge" target="/manifest/application">
|
||||
<application android:usesCleartextTraffic="true" />
|
||||
<application android:largeHeap="true" android:usesCleartextTraffic="true" />
|
||||
</edit-config>
|
||||
<config-file parent="/manifest/application" target="AndroidManifest.xml">
|
||||
<meta-data android:name="firebase_analytics_collection_deactivated" android:value="true" />
|
||||
|
|
|
@ -107,6 +107,11 @@
|
|||
"resolved": "https://registry.npmjs.org/@ionic-native/camera/-/camera-4.20.0.tgz",
|
||||
"integrity": "sha512-WnfQq8RV+7ezOqpCyNx9Xgpy7Y8TZehGLSxZXnCqCbFZ72CpC70Q5AV/eTIRGiKkotx2U6nUopYF+gTj1cunFA=="
|
||||
},
|
||||
"@ionic-native/chooser": {
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic-native/chooser/-/chooser-4.20.0.tgz",
|
||||
"integrity": "sha512-3Qn6TqWBzs2EQV0zp0uoTRDVPPdC/EgkdzIQVnryTZg1p1NZ3L8hKuIOHms/WqFwOGMeA87dMImxSgHjw9JXJQ=="
|
||||
},
|
||||
"@ionic-native/clipboard": {
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic-native/clipboard/-/clipboard-4.20.0.tgz",
|
||||
|
@ -2655,6 +2660,11 @@
|
|||
"resolved": "https://registry.npmjs.org/cordova-plugin-camera/-/cordova-plugin-camera-4.1.0.tgz",
|
||||
"integrity": "sha512-fCLhWjWYn49q3X5xaypAPgTz6MAWSKFFQvD2Gpi5SuVlrRPRphtX2jIqR2zCBuDTBR082QVnlc+yUDXt65Mjgw=="
|
||||
},
|
||||
"cordova-plugin-chooser": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/cordova-plugin-chooser/-/cordova-plugin-chooser-1.3.1.tgz",
|
||||
"integrity": "sha512-xyTgu7T1WSk4XeHVwrez1ZB+iPDThae79OYuuPTJkgHm4fVeD5QzzgJVxo2AETztAOM20OQU6txedfBYB6RHhQ=="
|
||||
},
|
||||
"cordova-plugin-customurlscheme": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cordova-plugin-customurlscheme/-/cordova-plugin-customurlscheme-5.0.0.tgz",
|
||||
|
@ -2719,7 +2729,7 @@
|
|||
"integrity": "sha512-NwO3qDBNL/vJxUxBTPNOA1HvkDf9eTeGH8JSZiwy1jq2W2mJKQEDBwqWkaEQS19Yd/MQTiw0cykxg5D7u4J6cQ=="
|
||||
},
|
||||
"cordova-plugin-qrscanner": {
|
||||
"version": "git+https://github.com/moodlemobile/cordova-plugin-qrscanner.git#43952839ce97887d1c6cad53c7d668fe3370aedd",
|
||||
"version": "git+https://github.com/moodlemobile/cordova-plugin-qrscanner.git#857efee3a7a49104faabd108ff1f00a57d3aca94",
|
||||
"from": "git+https://github.com/moodlemobile/cordova-plugin-qrscanner.git#dist",
|
||||
"requires": {
|
||||
"qrcode-reader": "^1.0.4",
|
||||
|
@ -5114,8 +5124,7 @@
|
|||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"optional": true
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
@ -5136,14 +5145,12 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"optional": true
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -5158,20 +5165,17 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||
"optional": true
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"optional": true
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||
"optional": true
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -5182,10 +5186,7 @@
|
|||
"debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw=="
|
||||
},
|
||||
"deep-extend": {
|
||||
"version": "0.6.0",
|
||||
|
@ -5211,7 +5212,7 @@
|
|||
"integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minipass": "^2.6.0"
|
||||
"minipass": "^2.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"minipass": {
|
||||
|
@ -5299,8 +5300,7 @@
|
|||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||
"optional": true
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -5312,7 +5312,6 @@
|
|||
"version": "1.0.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -5327,7 +5326,6 @@
|
|||
"version": "3.0.4",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -5352,7 +5350,7 @@
|
|||
"integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minipass": "^2.9.0"
|
||||
"minipass": "^2.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"minipass": {
|
||||
|
@ -5371,25 +5369,17 @@
|
|||
"version": "0.5.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
"minimist": "0.0.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"optional": true
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
|
||||
"optional": true
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.14.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
|
||||
|
@ -5402,18 +5392,26 @@
|
|||
"integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"debug": "^3.2.6",
|
||||
"debug": "^4.1.0",
|
||||
"iconv-lite": "^0.4.4",
|
||||
"sax": "^1.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
||||
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5433,7 +5431,7 @@
|
|||
"rc": "^1.2.7",
|
||||
"rimraf": "^2.6.1",
|
||||
"semver": "^5.3.0",
|
||||
"tar": "^4.4.2"
|
||||
"tar": "^4"
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
|
@ -5459,8 +5457,7 @@
|
|||
"optional": true,
|
||||
"requires": {
|
||||
"ignore-walk": "^3.0.1",
|
||||
"npm-bundled": "^1.0.1",
|
||||
"npm-normalize-package-bin": "^1.0.1"
|
||||
"npm-bundled": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"npmlog": {
|
||||
|
@ -5478,8 +5475,7 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||
"optional": true
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -5491,7 +5487,6 @@
|
|||
"version": "1.4.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -5613,7 +5608,6 @@
|
|||
"version": "1.0.2",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -5633,7 +5627,6 @@
|
|||
"version": "3.0.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
@ -5652,11 +5645,11 @@
|
|||
"requires": {
|
||||
"chownr": "^1.1.1",
|
||||
"fs-minipass": "^1.2.5",
|
||||
"minipass": "^2.8.6",
|
||||
"minizlib": "^1.2.1",
|
||||
"minipass": "^2.3.4",
|
||||
"minizlib": "^1.1.1",
|
||||
"mkdirp": "^0.5.0",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.3"
|
||||
"yallist": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"minipass": {
|
||||
|
@ -5689,8 +5682,7 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"optional": true
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
|
@ -6124,8 +6116,7 @@
|
|||
"version": "2.1.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
@ -6149,15 +6140,13 @@
|
|||
"version": "1.0.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -6174,22 +6163,19 @@
|
|||
"version": "1.1.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -6320,8 +6306,7 @@
|
|||
"version": "2.0.3",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -6335,7 +6320,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -6352,7 +6336,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -6361,15 +6344,13 @@
|
|||
"version": "0.0.8",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -6390,7 +6371,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -6479,8 +6459,7 @@
|
|||
"version": "1.0.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -6494,7 +6473,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -6590,8 +6568,7 @@
|
|||
"version": "5.1.2",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
@ -6633,7 +6610,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -6655,7 +6631,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
@ -6704,15 +6679,13 @@
|
|||
"version": "1.0.2",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -9480,12 +9453,6 @@
|
|||
"once": "^1.3.2"
|
||||
}
|
||||
},
|
||||
"npm-normalize-package-bin": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
|
||||
"integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
|
||||
"optional": true
|
||||
},
|
||||
"npm-package-arg": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz",
|
||||
|
@ -12959,8 +12926,7 @@
|
|||
"version": "2.1.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
@ -12984,15 +12950,13 @@
|
|||
"version": "1.0.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -13009,22 +12973,19 @@
|
|||
"version": "1.1.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -13155,8 +13116,7 @@
|
|||
"version": "2.0.3",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -13170,7 +13130,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -13187,7 +13146,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -13196,15 +13154,13 @@
|
|||
"version": "0.0.8",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -13225,7 +13181,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -13314,8 +13269,7 @@
|
|||
"version": "1.0.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -13329,7 +13283,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -13425,8 +13378,7 @@
|
|||
"version": "5.1.2",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
@ -13468,7 +13420,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -13490,7 +13441,6 @@
|
|||
"resolved": false,
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
@ -13539,15 +13489,13 @@
|
|||
"version": "1.0.2",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
"@angular/platform-browser-dynamic": "5.2.11",
|
||||
"@ionic-native/badge": "4.20.0",
|
||||
"@ionic-native/camera": "4.20.0",
|
||||
"@ionic-native/chooser": "^4.20.0",
|
||||
"@ionic-native/clipboard": "4.20.0",
|
||||
"@ionic-native/core": "4.20.0",
|
||||
"@ionic-native/device": "4.20.0",
|
||||
|
@ -86,6 +87,7 @@
|
|||
"cordova-plugin-advanced-http": "2.4.1",
|
||||
"cordova-plugin-badge": "0.8.8",
|
||||
"cordova-plugin-camera": "4.1.0",
|
||||
"cordova-plugin-chooser": "1.3.1",
|
||||
"cordova-plugin-customurlscheme": "5.0.0",
|
||||
"cordova-plugin-device": "2.0.3",
|
||||
"cordova-plugin-file": "6.0.2",
|
||||
|
@ -200,7 +202,8 @@
|
|||
"OKHTTP_VERSION": "3.10.0"
|
||||
},
|
||||
"cordova-plugin-wkwebview-cookies": {},
|
||||
"cordova-plugin-qrscanner": {}
|
||||
"cordova-plugin-qrscanner": {},
|
||||
"cordova-plugin-chooser": {}
|
||||
}
|
||||
},
|
||||
"main": "desktop/electron.js",
|
||||
|
|
|
@ -1375,7 +1375,6 @@
|
|||
"core.confirmgotabrootdefault": "local_moodlemobileapp",
|
||||
"core.confirmloss": "local_moodlemobileapp",
|
||||
"core.confirmopeninbrowser": "local_moodlemobileapp",
|
||||
"core.confirmreadfiletoobig": "local_moodlemobileapp",
|
||||
"core.considereddigitalminor": "moodle",
|
||||
"core.content": "moodle",
|
||||
"core.contenteditingsynced": "local_moodlemobileapp",
|
||||
|
|
|
@ -1375,7 +1375,6 @@
|
|||
"core.confirmgotabrootdefault": "Are you sure you want to go to the initial page of the current tab?",
|
||||
"core.confirmloss": "Are you sure? All changes will be lost.",
|
||||
"core.confirmopeninbrowser": "Do you want to open it in a web browser?",
|
||||
"core.confirmreadfiletoobig": "It seems the app previously crashed when trying to read a file as big as this one. Are you sure you want to continue?<br><br>If this file is stored in a repository like Google Drive, please try to download the file to your device first and use the downloaded file.",
|
||||
"core.considereddigitalminor": "You are too young to create an account on this site.",
|
||||
"core.content": "Content",
|
||||
"core.contenteditingsynced": "The content you are editing has been synced.",
|
||||
|
|
|
@ -18,6 +18,7 @@ import { Platform } from 'ionic-angular';
|
|||
// Ionic Native services.
|
||||
import { Badge } from '@ionic-native/badge';
|
||||
import { Camera } from '@ionic-native/camera';
|
||||
import { Chooser } from '@ionic-native/chooser';
|
||||
import { Clipboard } from '@ionic-native/clipboard';
|
||||
import { Device } from '@ionic-native/device';
|
||||
import { File } from '@ionic-native/file';
|
||||
|
@ -114,6 +115,7 @@ export const IONIC_NATIVE_PROVIDERS = [
|
|||
return appProvider.isMobile() ? new Badge() : new BadgeMock(appProvider);
|
||||
}
|
||||
},
|
||||
Chooser,
|
||||
CoreEmulatorHelperProvider,
|
||||
CoreEmulatorCaptureHelperProvider,
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@ import { CoreFileUploaderHandler, CoreFileUploaderHandlerData } from './delegate
|
|||
import { CoreFileUploaderHelperProvider } from './helper';
|
||||
import { CoreFileUploaderProvider } from './fileuploader';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
/**
|
||||
* Handler to upload any type of file.
|
||||
*/
|
||||
|
@ -65,11 +66,24 @@ export class CoreFileUploaderFileHandler implements CoreFileUploaderHandler {
|
|||
getData(): CoreFileUploaderHandlerData {
|
||||
const isIOS = this.platform.is('ios');
|
||||
|
||||
return {
|
||||
const handler: CoreFileUploaderHandlerData = {
|
||||
title: isIOS ? 'core.fileuploader.more' : 'core.fileuploader.file',
|
||||
class: 'core-fileuploader-file-handler',
|
||||
icon: isIOS ? 'more' : 'folder',
|
||||
afterRender: (maxSize: number, upload: boolean, allowOffline: boolean, mimetypes: string[]): void => {
|
||||
};
|
||||
|
||||
if (this.appProvider.isMobile()) {
|
||||
handler.action = (maxSize?: number, upload?: boolean, allowOffline?: boolean, mimetypes?: string[]): Promise<any> => {
|
||||
return this.uploaderHelper.chooseAndUploadFile(maxSize, upload, mimetypes).then((result) => {
|
||||
return {
|
||||
treated: true,
|
||||
result: result
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
} else {
|
||||
handler.afterRender = (maxSize: number, upload: boolean, allowOffline: boolean, mimetypes: string[]): void => {
|
||||
// Add an invisible file input in the file handler.
|
||||
// It needs to be done like this because the action sheet items don't accept inputs.
|
||||
const element = document.querySelector('.core-fileuploader-file-handler');
|
||||
|
@ -134,7 +148,9 @@ export class CoreFileUploaderFileHandler implements CoreFileUploaderHandler {
|
|||
element.appendChild(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,12 +16,13 @@ import { Injectable } from '@angular/core';
|
|||
import { ActionSheetController, ActionSheet, Platform, Loading } from 'ionic-angular';
|
||||
import { MediaFile } from '@ionic-native/media-capture';
|
||||
import { Camera, CameraOptions } from '@ionic-native/camera';
|
||||
import { Chooser, ChooserResult } from '@ionic-native/chooser';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreFileProvider, CoreFileProgressEvent } from '@providers/file';
|
||||
import { CoreFileHelperProvider } from '@providers/file-helper';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreMimetypeUtils } from '@providers/utils/mimetype';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreUtilsProvider, PromiseDefer } from '@providers/utils/utils';
|
||||
import { CoreFileUploaderProvider, CoreFileUploaderOptions } from './fileuploader';
|
||||
|
@ -49,10 +50,37 @@ export class CoreFileUploaderHelperProvider {
|
|||
protected uploaderDelegate: CoreFileUploaderDelegate,
|
||||
protected camera: Camera,
|
||||
protected platform: Platform,
|
||||
protected fileHelper: CoreFileHelperProvider) {
|
||||
protected fileChooser: Chooser) {
|
||||
this.logger = logger.getInstance('CoreFileUploaderProvider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose any type of file and upload it.
|
||||
*
|
||||
* @param maxSize Max size of the upload. -1 for no max size.
|
||||
* @param upload True if the file should be uploaded, false to return the picked file.
|
||||
* @param mimetypes List of supported mimetypes. If undefined, all mimetypes supported.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
async chooseAndUploadFile(maxSize: number, upload?: boolean, mimetypes?: string[]): Promise<any> {
|
||||
|
||||
const result = await this.fileChooser.getFile(mimetypes ? mimetypes.join(',') : undefined);
|
||||
|
||||
if (!result) {
|
||||
// User canceled.
|
||||
throw this.domUtils.createCanceledError();
|
||||
}
|
||||
|
||||
if (result.name == 'File') {
|
||||
// In some Android 4.4 devices the file name cannot be retrieved. Try to use the one from the URI.
|
||||
result.name = this.getChosenFileNameFromPath(result) || result.name;
|
||||
}
|
||||
|
||||
const options = this.fileUploaderProvider.getFileUploadOptions(result.uri, result.name, result.mediaType, true);
|
||||
|
||||
return this.uploadFile(result.uri, maxSize, true, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a confirmation modal to the user if the size of the file is bigger than the allowed threshold.
|
||||
*
|
||||
|
@ -108,7 +136,7 @@ export class CoreFileUploaderHelperProvider {
|
|||
const filePath = this.textUtils.concatenatePaths(CoreFileProvider.TMPFOLDER, newName);
|
||||
|
||||
// Write the data into the file.
|
||||
return this.fileHelper.writeFileDataInFile(file, filePath, (progress: CoreFileProgressEvent) => {
|
||||
return this.fileProvider.writeFileDataInFile(file, filePath, (progress: CoreFileProgressEvent) => {
|
||||
this.showProgressModal(modal, 'core.fileuploader.readingfileperc', progress);
|
||||
});
|
||||
}).catch((error) => {
|
||||
|
@ -193,9 +221,7 @@ export class CoreFileUploaderHelperProvider {
|
|||
}
|
||||
});
|
||||
|
||||
this.domUtils.showErrorModal(errorMessage);
|
||||
|
||||
return Promise.reject(null);
|
||||
return Promise.reject(errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -224,6 +250,33 @@ export class CoreFileUploaderHelperProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the result of choosing a file, try to get its file name from the path.
|
||||
*
|
||||
* @param result Chosen file data.
|
||||
* @return File name, undefined if cannot get it.
|
||||
*/
|
||||
protected getChosenFileNameFromPath(result: ChooserResult): string {
|
||||
const nameAndDir = this.fileProvider.getFileAndDirectoryFromPath(result.uri);
|
||||
|
||||
if (!nameAndDir.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
let extension = CoreMimetypeUtils.instance.getFileExtension(nameAndDir.name);
|
||||
|
||||
if (!extension) {
|
||||
// The URI doesn't have an extension, add it now.
|
||||
extension = CoreMimetypeUtils.instance.getExtension(result.mediaType);
|
||||
|
||||
if (extension) {
|
||||
nameAndDir.name += '.' + extension;
|
||||
}
|
||||
}
|
||||
|
||||
return decodeURIComponent(nameAndDir.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the "file picker" to select and upload a file.
|
||||
*
|
||||
|
@ -632,7 +685,7 @@ export class CoreFileUploaderHelperProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved if the file is uploaded, rejected otherwise.
|
||||
*/
|
||||
protected uploadFile(path: string, maxSize: number, checkSize: boolean, options: CoreFileUploaderOptions, siteId?: string)
|
||||
uploadFile(path: string, maxSize: number, checkSize: boolean, options: CoreFileUploaderOptions, siteId?: string)
|
||||
: Promise<any> {
|
||||
|
||||
const errorStr = this.translate.instant('core.error'),
|
||||
|
@ -649,7 +702,7 @@ export class CoreFileUploaderHelperProvider {
|
|||
this.fileProvider.removeExternalFile(path);
|
||||
}
|
||||
|
||||
return Promise.reject(null);
|
||||
return Promise.reject(this.domUtils.createCanceledError());
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
"confirmgotabrootdefault": "Are you sure you want to go to the initial page of the current tab?",
|
||||
"confirmloss": "Are you sure? All changes will be lost.",
|
||||
"confirmopeninbrowser": "Do you want to open it in a web browser?",
|
||||
"confirmreadfiletoobig": "It seems the app previously crashed when trying to read a file as big as this one. Are you sure you want to continue?<br><br>If this file is stored in a repository like Google Drive, please try to download the file to your device first and use the downloaded file.",
|
||||
"considereddigitalminor": "You are too young to create an account on this site.",
|
||||
"content": "Content",
|
||||
"contenteditingsynced": "The content you are editing has been synced.",
|
||||
|
|
|
@ -15,16 +15,13 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreAppProvider } from './app';
|
||||
import { CoreConfigProvider } from './config';
|
||||
import { CoreFileProvider, CoreFileProgressFunction } from './file';
|
||||
import { CoreFileProvider } from './file';
|
||||
import { CoreFilepoolProvider } from './filepool';
|
||||
import { CoreSitesProvider } from './sites';
|
||||
import { CoreWSProvider } from './ws';
|
||||
import { CoreDomUtilsProvider } from './utils/dom';
|
||||
import { CoreUrlUtils } from './utils/url';
|
||||
import { CoreUtilsProvider } from './utils/utils';
|
||||
import { CoreConstants } from '@core/constants';
|
||||
import { FileEntry } from '@ionic-native/file';
|
||||
import { makeSingleton } from '@singletons/core.singletons';
|
||||
|
||||
/**
|
||||
|
@ -33,23 +30,13 @@ import { makeSingleton } from '@singletons/core.singletons';
|
|||
@Injectable()
|
||||
export class CoreFileHelperProvider {
|
||||
|
||||
// Variables for reading files in chunks.
|
||||
protected MAX_CHUNK_SIZE_NAME = 'file_max_chunk_size';
|
||||
protected READ_CHUNK_ATTEMPT_NAME = 'file_read_chunk_attempt';
|
||||
protected maxChunkSize = -1;
|
||||
|
||||
constructor(protected fileProvider: CoreFileProvider,
|
||||
protected filepoolProvider: CoreFilepoolProvider,
|
||||
protected sitesProvider: CoreSitesProvider,
|
||||
protected appProvider: CoreAppProvider,
|
||||
protected translate: TranslateService,
|
||||
protected utils: CoreUtilsProvider,
|
||||
protected wsProvider: CoreWSProvider,
|
||||
protected configProvider: CoreConfigProvider,
|
||||
protected domUtils: CoreDomUtilsProvider) {
|
||||
|
||||
this.initMaxChunkSize();
|
||||
}
|
||||
protected wsProvider: CoreWSProvider) { }
|
||||
|
||||
/**
|
||||
* Convenience function to open a file, downloading it if needed.
|
||||
|
@ -258,34 +245,6 @@ export class CoreFileHelperProvider {
|
|||
return file.timemodified || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the max chunk size.
|
||||
*
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async initMaxChunkSize(): Promise<void> {
|
||||
const sizes = await Promise.all([
|
||||
await this.configProvider.get(this.READ_CHUNK_ATTEMPT_NAME, -1), // Check if there is any attempt pending.
|
||||
await this.configProvider.get(this.MAX_CHUNK_SIZE_NAME, -1), // Retrieve current max chunk size from DB.
|
||||
]);
|
||||
|
||||
const attemptSize = sizes[0];
|
||||
const maxChunkSize = sizes[1];
|
||||
|
||||
if (attemptSize != -1 && (maxChunkSize == -1 || attemptSize < maxChunkSize)) {
|
||||
// Store the attempt's size as the max size.
|
||||
this.storeMaxChunkSize(attemptSize);
|
||||
} else {
|
||||
// No attempt or the max size is already lower. Keep current max size.
|
||||
this.maxChunkSize = maxChunkSize;
|
||||
}
|
||||
|
||||
if (attemptSize != -1) {
|
||||
// Clean pending attempt.
|
||||
await this.configProvider.delete(this.READ_CHUNK_ATTEMPT_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a state is downloaded or outdated.
|
||||
*
|
||||
|
@ -380,99 +339,6 @@ export class CoreFileHelperProvider {
|
|||
|
||||
throw new Error('Couldn\'t determine file size: ' + file.fileurl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save max chunk size.
|
||||
*
|
||||
* @param size Size to store.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async storeMaxChunkSize(size: number): Promise<void> {
|
||||
this.maxChunkSize = size;
|
||||
|
||||
await this.configProvider.set(this.MAX_CHUNK_SIZE_NAME, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write some file data into a filesystem file.
|
||||
* It's done in chunks to prevent crashing the app for big files.
|
||||
*
|
||||
* @param file The data to write.
|
||||
* @param path Path where to store the data.
|
||||
* @param onProgress Function to call on progress.
|
||||
* @param offset Offset where to start reading from.
|
||||
* @param append Whether to append the data to the end of the file.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
async writeFileDataInFile(file: Blob, path: string, onProgress?: CoreFileProgressFunction, offset: number = 0,
|
||||
append?: boolean): Promise<FileEntry> {
|
||||
|
||||
offset = offset || 0;
|
||||
|
||||
// Get the chunk to read and write.
|
||||
const readWholeFile = offset === 0 && CoreFileProvider.CHUNK_SIZE >= file.size;
|
||||
const chunk = readWholeFile ? file : file.slice(offset, Math.min(offset + CoreFileProvider.CHUNK_SIZE, file.size));
|
||||
|
||||
try {
|
||||
const fileEntry = await this.fileProvider.writeFileDataInFileChunk(chunk, path, append);
|
||||
|
||||
offset += CoreFileProvider.CHUNK_SIZE;
|
||||
|
||||
onProgress && onProgress({
|
||||
lengthComputable: true,
|
||||
loaded: offset,
|
||||
total: file.size
|
||||
});
|
||||
|
||||
if (offset >= file.size) {
|
||||
// Done, stop.
|
||||
return fileEntry;
|
||||
}
|
||||
|
||||
// Read the next chunk.
|
||||
return this.writeFileDataInFile(file, path, onProgress, offset, true);
|
||||
} catch (error) {
|
||||
if (readWholeFile || !error || error.name != 'NotReadableError') {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
// Permission error when reading file in chunks. This usually happens with Google Drive files.
|
||||
// Try to read the whole file at once.
|
||||
return this.writeBigFileDataInFile(file, path, onProgress);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a big file data into a filesystem file without using chunks.
|
||||
* The app can crash when doing this with big files, so this function will try to control the max size that works
|
||||
* and warn the user if he's trying to upload a file that is too big.
|
||||
*
|
||||
* @param file The data to write.
|
||||
* @param path Path where to store the data.
|
||||
* @param onProgress Function to call on progress.
|
||||
* @return Promise resolved with the file.
|
||||
*/
|
||||
protected async writeBigFileDataInFile(file: Blob, path: string, onProgress?: CoreFileProgressFunction): Promise<FileEntry> {
|
||||
if (this.maxChunkSize != -1 && file.size >= this.maxChunkSize) {
|
||||
// The file size is bigger than the max allowed size. Ask the user to confirm.
|
||||
await this.domUtils.showConfirm(this.translate.instant('core.confirmreadfiletoobig'));
|
||||
}
|
||||
|
||||
// Store the "attempt".
|
||||
await this.configProvider.set(this.READ_CHUNK_ATTEMPT_NAME, file.size);
|
||||
|
||||
// Write the whole file.
|
||||
const fileEntry = await this.fileProvider.writeFileDataInFileChunk(file, path, false);
|
||||
|
||||
// Success, remove the attempt and increase the max chunk size if needed.
|
||||
await this.configProvider.delete(this.READ_CHUNK_ATTEMPT_NAME);
|
||||
|
||||
if (file.size > this.maxChunkSize) {
|
||||
await this.storeMaxChunkSize(file.size + 1);
|
||||
}
|
||||
|
||||
return fileEntry;
|
||||
}
|
||||
}
|
||||
|
||||
export class CoreFileHelper extends makeSingleton(CoreFileHelperProvider) {}
|
||||
|
|
|
@ -65,7 +65,7 @@ export class CoreFileProvider {
|
|||
static SITESFOLDER = 'sites';
|
||||
static TMPFOLDER = 'tmp';
|
||||
|
||||
static CHUNK_SIZE = 10485760; // 10 MB.
|
||||
static CHUNK_SIZE = 1048576; // 1 MB. Same chunk size as Ionic Native.
|
||||
|
||||
protected logger;
|
||||
protected initialized = false;
|
||||
|
@ -639,6 +639,7 @@ export class CoreFileProvider {
|
|||
/**
|
||||
* Write some file data into a filesystem file.
|
||||
* It's done in chunks to prevent crashing the app for big files.
|
||||
* Please notice Ionic Native writeFile function already splits by chunks, but it doesn't have an onProgress function.
|
||||
*
|
||||
* @param file The data to write.
|
||||
* @param path Path where to store the data.
|
||||
|
@ -646,19 +647,17 @@ export class CoreFileProvider {
|
|||
* @param offset Offset where to start reading from.
|
||||
* @param append Whether to append the data to the end of the file.
|
||||
* @return Promise resolved when done.
|
||||
* @deprecated since 3.8.3. Please use CoreFileHelperProvider.writeFileDataInFile instead.
|
||||
*/
|
||||
async writeFileDataInFile(file: Blob, path: string, onProgress?: CoreFileProgressFunction, offset: number = 0,
|
||||
append?: boolean): Promise<FileEntry> {
|
||||
|
||||
offset = offset || 0;
|
||||
|
||||
// Get the chunk to read and write.
|
||||
const readWholeFile = offset === 0 && CoreFileProvider.CHUNK_SIZE >= file.size;
|
||||
const chunk = readWholeFile ? file : file.slice(offset, Math.min(offset + CoreFileProvider.CHUNK_SIZE, file.size));
|
||||
|
||||
try {
|
||||
const fileEntry = await this.writeFileDataInFileChunk(chunk, path, append);
|
||||
// Get the chunk to write.
|
||||
const chunk = file.slice(offset, Math.min(offset + CoreFileProvider.CHUNK_SIZE, file.size));
|
||||
|
||||
const fileEntry = await this.writeFile(path, chunk, append);
|
||||
|
||||
offset += CoreFileProvider.CHUNK_SIZE;
|
||||
|
||||
|
@ -676,32 +675,15 @@ export class CoreFileProvider {
|
|||
// Read the next chunk.
|
||||
return this.writeFileDataInFile(file, path, onProgress, offset, true);
|
||||
} catch (error) {
|
||||
if (readWholeFile || !error || error.name != 'NotReadableError') {
|
||||
return Promise.reject(error);
|
||||
if (error && error.target && error.target.error) {
|
||||
// Error returned by the writer, get the "real" error.
|
||||
error = error.target.error;
|
||||
}
|
||||
|
||||
// Permission error when reading file in chunks. This usually happens with Google Drive files.
|
||||
// Try to read the whole file at once.
|
||||
return this.writeFileDataInFileChunk(file, path, false);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a chunk of data into a file.
|
||||
*
|
||||
* @param chunkData The chunk of data.
|
||||
* @param path Path where to store the data.
|
||||
* @param append Whether to append the data to the end of the file.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
writeFileDataInFileChunk(chunkData: Blob, path: string, append?: boolean): Promise<FileEntry> {
|
||||
// Read the chunk data.
|
||||
return this.readFileData(chunkData, CoreFileProvider.FORMATARRAYBUFFER).then((fileData) => {
|
||||
// Write the data in the file.
|
||||
return this.writeFile(path, fileData, append);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a file that might be outside the app's folder.
|
||||
*
|
||||
|
@ -957,7 +939,7 @@ export class CoreFileProvider {
|
|||
* path/ -> directory: 'path', name: ''
|
||||
* path -> directory: '', name: 'path'
|
||||
*/
|
||||
getFileAndDirectoryFromPath(path: string): any {
|
||||
getFileAndDirectoryFromPath(path: string): {directory: string, name: string} {
|
||||
const file = {
|
||||
directory: '',
|
||||
name: ''
|
||||
|
|
|
@ -901,7 +901,7 @@ export class CoreWSProvider {
|
|||
|
||||
return transfer.upload(filePath, uploadUrl, options, true).then((success) => {
|
||||
const data = this.textUtils.parseJSON(success.response, null,
|
||||
this.logger.error.bind(this.logger, 'Error parsing response from upload'));
|
||||
this.logger.error.bind(this.logger, 'Error parsing response from upload', success.response));
|
||||
if (data === null) {
|
||||
return Promise.reject(this.translate.instant('core.errorinvalidresponse'));
|
||||
}
|
||||
|
|
|
@ -32,6 +32,21 @@ interface UrlParts {
|
|||
*/
|
||||
port?: string;
|
||||
|
||||
/**
|
||||
* Url credentials: username and password (if any).
|
||||
*/
|
||||
credentials?: string;
|
||||
|
||||
/**
|
||||
* Url's username.
|
||||
*/
|
||||
username?: string;
|
||||
|
||||
/**
|
||||
* Url's password.
|
||||
*/
|
||||
password?: string;
|
||||
|
||||
/**
|
||||
* Url path.
|
||||
*/
|
||||
|
@ -71,15 +86,21 @@ export class CoreUrl {
|
|||
return null;
|
||||
}
|
||||
|
||||
// Split host into domain and port.
|
||||
const host = match[4] || '';
|
||||
const [domain, port]: string[] = host.indexOf(':') === -1 ? [host] : host.split(':');
|
||||
|
||||
// Get the credentials and the port from the host.
|
||||
const [domainAndPort, credentials]: string[] = host.split('@').reverse();
|
||||
const [domain, port]: string[] = domainAndPort.split(':');
|
||||
const [username, password]: string[] = credentials ? credentials.split(':') : [];
|
||||
|
||||
// Prepare parts replacing empty strings with undefined.
|
||||
return {
|
||||
protocol: match[2] || undefined,
|
||||
domain: domain || undefined,
|
||||
port: port || undefined,
|
||||
credentials: credentials || undefined,
|
||||
username: username || undefined,
|
||||
password: password || undefined,
|
||||
path: match[5] || undefined,
|
||||
query: match[7] || undefined,
|
||||
fragment: match[9] || undefined,
|
||||
|
|
Loading…
Reference in New Issue