diff --git a/bower.json b/bower.json deleted file mode 100644 index 7a42c76f9462f6e0fe439d8c560e792434b354c4..0000000000000000000000000000000000000000 --- a/bower.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "cesium", - "private": "false", - "dependencies": { - "ionic": "driftyco/ionic-bower#1.3.5", - "ionic-material": "0.4.2", - "angular-messages": "^1.5.11", - "robotodraft": "1.1.0", - "angular": "^1.5.11", - "angular-moment": "^1.3.0", - "angular-animate": "^1.5.11", - "angular-sanitize": "^1.5.11", - "angular-resource": "^1.5.11", - "angular-bind-notifier": "^1.1.11", - "angular-image-crop": "duniter-cesium/angular-image-crop#^2.0.2", - "angular-ui-router": "^0.2.18", - "angular-cache": "^4.6.0", - "ng-idle": "HackedByChinese/ng-idle#1.3.2", - "chart.js": "2.9.3", - "leaflet.awesome-markers": "2.0.2", - "leaflet-search": "2.7.2", - "angular-leaflet-directive": "duniter-cesium/angular-leaflet-directive#^0.10.1", - "Leaflet.EasyButton": "^2.4.0", - "leaflet.loading": "Leaflet.loading#^0.1.24", - "ui-leaflet": "^2.0.0", - "leaflet.markercluster": "Leaflet.markercluster#0.5.0", - "Leaflet.FeatureGroup.SubGroup": "0.1.2", - "ion-digit-keyboard": "skol-pro/ion-digit-keyboard#973b90c2fc", - "angular-expose-api": "duniter-cesium/angular-expose-api#0.3.1", - "angular-screenmatch": "^1.0.1", - "angular-file-saver": "^1.1.3", - "angular-simple-logger": "^0.1.7", - "angular-chart.js": "jtblin/angular-chart#1.1.1", - "angular-fullscreen-toggle": "duniter-cesium/angular-fullscreen-toggle#1.0.4", - "leaflet": "0.7.7", - "moment": "^2.24.0", - "numeral": "1.5.6", - "underscore": "1.10.2", - "aes-js": "ricmoo/aes-js#3.1.2", - "ngCordova": "0.1.27-alpha", - "js-scrypt": "1.2.0", - "js-nacl": "1.3.2", - "angular-translate": "^2.18.2", - "socket.io": "socketio/socket.io#^1.7.4", - "socket.io-client": "^1.7.4" - }, - "resolutions": { - "angular": "1.5.11", - "angular-animate": "^1.5.11", - "angular-sanitize": "^1.5.11", - "angular-ui-router": "0.2.18", - "angular-messages": "1.5.11", - "angular-expose-api": "0.3.1", - "Leaflet.EasyButton": "~1.3.2", - "leaflet": "0.7.7", - "leaflet.markercluster": "0.5", - "Leaflet.FeatureGroup.SubGroup": "0.1.2", - "moment": ">=2.8.0 <2.24.0", - "numeral": "1.5.6", - "ionic": "1.3.5" - } -} diff --git a/config.xml b/config.xml index d4ec8238818dfcf53f2ab3cbfeafb76996fc6154..7356932293311090112fc8f765bfd7ddb0b4a664 100644 --- a/config.xml +++ b/config.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='utf-8'?> -<widget android-versionCode="106070" id="fr.duniter.cesium" ios-CFBundleIdentifier="org.duniter.cesium" version="1.6.7" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> +<widget android-versionCode="106070" id="fr.duniter.cesium" ios-CFBundleIdentifier="org.duniter.cesium" version="1.6.7" xmlns="http://www.w3.org/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cdv="http://cordova.apache.org/ns/1.0"> <name>Cesium</name> <description> An simple App for Duniter wallet @@ -15,9 +15,13 @@ <allow-intent href="sms:*" /> <allow-intent href="mailto:*" /> <allow-intent href="geo:*" /> + <allow-intent href="june://*/*" /> + <allow-intent href="web+june://*/*" /> <allow-navigation href="http://*/*" /> <allow-navigation href="https://*/*" /> <allow-navigation href="data:*" /> + <allow-navigation href="june://*/*" /> + <allow-navigation href="web+june://*/*" /> <icon src="www/img/logo_96px.png" /> <preference name="webviewbounce" value="false" /> <preference name="UIWebViewBounce" value="false" /> @@ -109,6 +113,9 @@ <edit-config file="*-Info.plist" mode="merge" target="NSPhotoLibraryUsageDescription"> <string>To choose a profile picture</string> </edit-config> + <edit-config file="*-Info.plist" mode="merge" target="CFBundleURLSchemes"> + <string>june</string> + </edit-config> <config-file mode="add" parent="ITSAppUsesNonExemptEncryption" target="*-Info.plist"> <false /> </config-file> @@ -122,30 +129,41 @@ <icon height="512" src="resources/osx/icon-512.png" width="512" /> <icon height="1024" src="resources/osx/icon-1024.png" width="1024" /> </platform> + <plugin name="cordova-plugin-minisodium" spec="git+https://github.com/duniter-cesium/cordova-plugin-minisodium.git#v1.0.1" /> + <plugin name="cordova-plugin-secure-storage-android10" spec="git+https://github.com/duniter-cesium/cordova-plugin-secure-storage-android10#6.0.4" /> <plugin name="cordova-plugin-camera" spec="^4.1.0"> + <variable name="CAMERA_USAGE_DESCRIPTION" value="Add picture to the user profile" /> + <variable name="PHOTOLIBRARY_USAGE_DESCRIPTION" value="Take a picture for the user profile" /> <variable name="ANDROID_SUPPORT_V4_VERSION" value="28.+" /> </plugin> - <plugin name="cordova-plugin-ionic-webview" spec="^4.1.3"> + <plugin name="cordova-plugin-ionic-webview" spec="^4.2.1"> <variable name="ANDROID_SUPPORT_ANNOTATIONS_VERSION" value="28.+" /> </plugin> <plugin name="cordova-plugin-device" spec="^2.0.3" /> <plugin name="cordova-plugin-dialogs" spec="^2.0.2" /> <plugin name="cordova-clipboard" spec="^1.3.0" /> - <plugin name="cordova-plugin-secure-storage-android10" spec="git+https://github.com/duniter-cesium/cordova-plugin-secure-storage-android10#6.0.4" /> - <plugin name="cordova-plugin-splashscreen" spec="^5.0.3" /> + <plugin name="cordova-plugin-splashscreen" spec="^5.0.4" /> <plugin name="cordova-plugin-statusbar" spec="^2.4.3" /> <plugin name="cordova-plugin-file" spec="^6.0.2" /> <plugin name="cordova-plugin-vibration" spec="^3.1.1" /> <plugin name="cordova-plugin-websocket" spec="^0.12.2" /> <plugin name="cordova-plugin-whitelist" spec="^1.3.4" /> <plugin name="cordova-plugin-x-toast" spec="^2.7.2" /> - <plugin name="cordova-plugin-ionic-keyboard" spec="^2.2.1" /> - <plugin name="cordova-plugin-minisodium" spec="git+https://github.com/duniter-cesium/cordova-plugin-minisodium.git#v1.0.1" /> + <plugin name="cordova-plugin-ionic-keyboard" spec="^2.2.0" /> <plugin name="phonegap-plugin-barcodescanner" spec="^8.1.0"> <variable name="CAMERA_USAGE_DESCRIPTION" value="To scan QRCode" /> <variable name="ANDROID_SUPPORT_V4_VERSION" value="28.+" /> </plugin> + <plugin name="cordova-plugin-customurlscheme" spec="^5.0.2"> + <variable name="URL_SCHEME" value="june" /> + <variable name="ANDROID_SCHEME" value=" " /> + <variable name="ANDROID_HOST" value=" " /> + <variable name="ANDROID_PATHPREFIX" value="/" /> + </plugin> + <plugin name="ionic-plugin-keyboard" spec="^2.2.1" /> + <plugin name="cordova-plugin-androidx" spec="^1.0.2" /> + <plugin name="cordova-plugin-androidx-adapter" spec="^1.1.0" /> <engine name="ios" spec="git+https://github.com/duniter-cesium/cordova-ios.git#5.1.0" /> <engine name="osx" spec="^5.0.0" /> - <engine name="android" spec="^8.1.0" /> + <engine name="android" spec="^9.0.0" /> </widget> diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..b6517bb1d165022c80a76e51260106186d93bed6 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/gulpfile.js b/gulpfile.js index cf4ded7556f9414107b716269e4117d76a7f1ea8..f1b30e3a4f3262cbd81e29becc6170928a0534be 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -16,6 +16,7 @@ const gulp = require('gulp'), ngAnnotate = require('gulp-ng-annotate'), zip = require('gulp-zip'), del = require('del'), + debug = require('gulp-debug'), useref = require('gulp-useref'), filter = require('gulp-filter'), uglify = require('gulp-uglify-es').default, @@ -302,10 +303,19 @@ function webCopyFiles() { log(colors.green('Preparing dist/web files...')); let htmlminOptions = {removeComments: true, collapseWhitespace: true}; + const debugOptions = { + title: 'Copying', + minimal: true, + showFiles: argv.debug || false, + showCount: argv.debug || false, + logger: m => log(colors.grey(m)) + }; + var tmpPath = './dist/web/www'; return merge( // Copy Js (and remove unused code) gulp.src('./www/js/**/*.js') + .pipe(debug(debugOptions)) .pipe(removeCode({"no-device": true})) .pipe(jshint()) .pipe(gulp.dest(tmpPath + '/js')), @@ -336,10 +346,12 @@ function webCopyFiles() { // Copy fonts gulp.src('./www/fonts/**/*.*') + .pipe(debug(debugOptions)) .pipe(gulp.dest(tmpPath + '/fonts')), // Copy CSS gulp.src('./www/css/**/*.*') + .pipe(debug(debugOptions)) .pipe(gulp.dest(tmpPath + '/css')), // Copy i18n @@ -348,18 +360,22 @@ function webCopyFiles() { .pipe(jsonlint.reporter()) .pipe(sort()) .pipe(ngTranslate({standalone:true, module: 'cesium.translations'})) + .pipe(debug(debugOptions)) .pipe(gulp.dest(tmpPath + '/js')), // Copy img gulp.src('./www/img/**/*.*') + .pipe(debug(debugOptions)) .pipe(gulp.dest(tmpPath + '/img')), // Copy manifest.json gulp.src('./www/manifest.json') + .pipe(debug(debugOptions)) .pipe(gulp.dest(tmpPath)), // Copy lib (JS, CSS and fonts) gulp.src(['./www/lib/**/*.js', './www/lib/**/*.css', './www/lib/**/fonts/**/*.*']) + .pipe(debug(debugOptions)) .pipe(gulp.dest(tmpPath + '/lib')), // Copy license into HTML @@ -517,18 +533,32 @@ function webUglify(done) { if (done) done(); } -function webIntegrity() { +function webIntegrity(done) { const wwwPath = './dist/web/www'; - log(colors.green('Add integrity hash to <script src> tag...')); + const enableIntegrity = argv.release || false; + + if (enableIntegrity) { + log(colors.green('Add integrity hash to <script src> tag...')); + + // Process index.html + return gulp.series( + gulp.src(wwwPath + '/index.html', {base: wwwPath}) + + // Add an integrity hash + .pipe(sriHash()) + + .pipe(rename({ extname: '.integrity.html' })) + .pipe(gulp.dest(wwwPath)), - // Process index.html - return gulp.src(wwwPath + '/index.html', {base: wwwPath}) + gulp.src(wwwPath + '/index.html', {base: wwwPath}) + .pipe(rename({ extname: '.test.html' })) + .pipe(gulp.dest(wwwPath)) + ) + .on('end', done); + } - // Add an integrity hash - .pipe(sriHash()) - .pipe(rename({ extname: '.integrity.html' })) - .pipe(gulp.dest(wwwPath)); + if (done) done(); } function webApiUglify() { @@ -591,7 +621,7 @@ function webApiUglify() { } else { - log(colors.red('API: Minify JS and CSS files. Skip') + colors.grey(' (missing options --release or --uglify)')); + log(colors.red('API: Skipping minify JS and CSS files') + colors.grey(' (missing options --release or --uglify)')); return gulp.src(tmpPath + '/*/index.html') .pipe(useref()) // Concatenate with gulp-useref @@ -608,26 +638,36 @@ function webApiUglify() { function webCleanUnusedFiles(done) { log(colors.green('Clean unused files...')); - const cleanSources = argv.release || argv.uglify || false; + const enableUglify = argv.release || argv.useref || argv.uglify || false; + const cleanSources = enableUglify; + const debugOptions = { + title: 'Deleting', + minimal: true, + showFiles: argv.debug || false, + showCount: !argv.debug, + logger: m => log(colors.grey(m)) + }; const wwwPath = './dist/web/www'; if (cleanSources) { return merge( - // Clean core JS + CSS + // Clean core JS gulp.src(wwwPath + '/js/**/*.js', {read: false}) - .pipe(clean()), - gulp.src(wwwPath + '/css/**/*.css', {read: false}) + .pipe(debug(debugOptions)) .pipe(clean()), // Clean plugins JS + CSS gulp.src(wwwPath + '/plugins/**/*.js', {read: false}) + .pipe(debug(debugOptions)) .pipe(clean()), gulp.src(wwwPath + '/plugins/**/*.css', {read: false}) + .pipe(debug(debugOptions)) .pipe(clean()), // Unused maps/config.js.map gulp.src(wwwPath + '/maps/config.js.map', {read: false, allowEmpty: true}) + .pipe(debug(debugOptions)) .pipe(clean()) ) .on('end', done); @@ -640,6 +680,13 @@ function webCleanUnusedFiles(done) { function webCleanUnusedDirectories() { log(colors.green('Clean unused directories...')); const enableUglify = argv.release || argv.uglify || false; + const debugOptions = { + title: 'Deleting', + minimal: true, + showFiles: argv.debug || false, + showCount: !argv.debug, + logger: m => log(colors.grey(m)) + }; // Clean dir const wwwPath = './dist/web/www'; @@ -676,7 +723,7 @@ function webCleanUnusedDirectories() { } return gulp.src(patterns, {read: false, allowEmpty: true}) - //.pipe(debug({title: 'deleting '})) + .pipe(debug(debugOptions)) .pipe(clean()); } diff --git a/hooks/after_prepare/010_add_platform_class.js b/hooks/after_prepare/010_add_platform_class.js index 73302b26639c4317eeda8201d9a73bcfbc2fe2d9..4254793e15729ff5fda3e59a7cd277d214864dd8 100755 --- a/hooks/after_prepare/010_add_platform_class.js +++ b/hooks/after_prepare/010_add_platform_class.js @@ -76,7 +76,8 @@ if (rootdir) { const platform = platforms[x].trim().toLowerCase(); let indexPath; - if(platform == 'android') { + if(platform === 'android') { + //indexPath = path.join(rootdir, 'platforms', platform, 'app', 'src', 'main', 'assets', 'www', 'index.html'); indexPath = path.join('platforms', platform, 'assets', 'www', 'index.html'); } else { indexPath = path.join('platforms', platform, 'www', 'index.html'); diff --git a/hooks/after_prepare/020_remove_code.js b/hooks/after_prepare/020_remove_code.js index bfc0b0bffab614dd74c9c8bd0a9224e99812f82f..6c2c29570595b629fd6316492873428fad49eea3 100755 --- a/hooks/after_prepare/020_remove_code.js +++ b/hooks/after_prepare/020_remove_code.js @@ -22,6 +22,7 @@ if (rootdir) { let wwwPath; if(platform === 'android') { + //wwwPath = path.join(rootdir, 'platforms', platform, 'app', 'src', 'main', 'assets', 'www'); wwwPath = path.join(rootdir, 'platforms', platform, 'assets', 'www'); } else { wwwPath = path.join(rootdir, 'platforms', platform, 'www'); diff --git a/hooks/after_prepare/021_template_cache.js b/hooks/after_prepare/021_template_cache.js index 2a0a27143dbf9b02873271cf3757ecf813123c3d..c5983a3d103745bb46e61daa91a379021b02f4e8 100755 --- a/hooks/after_prepare/021_template_cache.js +++ b/hooks/after_prepare/021_template_cache.js @@ -16,7 +16,8 @@ if (rootdir) { let platform = platforms[x].trim().toLowerCase(); let wwwPath; - if(platform == 'android') { + if (platform === 'android') { + //wwwPath = path.join(rootdir, 'platforms', platform, 'app', 'src', 'main', 'assets', 'www'); wwwPath = path.join(rootdir, 'platforms', platform, 'assets', 'www'); } else { wwwPath = path.join(rootdir, 'platforms', platform, 'www'); diff --git a/hooks/after_prepare/022_translate.js b/hooks/after_prepare/022_translate.js index ba998762ad7a25c79767981c88969db5b40e5eb6..a4cf7b902baa181d9ccf320d5d4f07e59401276b 100755 --- a/hooks/after_prepare/022_translate.js +++ b/hooks/after_prepare/022_translate.js @@ -17,6 +17,7 @@ if (rootdir) { let wwwPath; if(platform === 'android') { + //wwwPath = path.join(rootdir, 'platforms', platform, 'app', 'src', 'main', 'assets', 'www'); wwwPath = path.join(rootdir, 'platforms', platform, 'assets', 'www'); } else { wwwPath = path.join(rootdir, 'platforms', platform, 'www'); diff --git a/hooks/after_prepare/040_useref.js b/hooks/after_prepare/040_useref.js index 0b8d93dccdfc086febb8634d25114846721571fb..9aa438ed007b61c95431e2441d50e44cc3eaab06 100755 --- a/hooks/after_prepare/040_useref.js +++ b/hooks/after_prepare/040_useref.js @@ -33,6 +33,7 @@ if (rootdir && !skip) { let wwwPath; if(platform === 'android') { + //wwwPath = path.join(rootdir, 'platforms', platform, 'app', 'src', 'main', 'assets', 'www'); wwwPath = path.join(rootdir, 'platforms', platform, 'assets', 'www'); } else { wwwPath = path.join(rootdir, 'platforms', platform, 'www'); diff --git a/hooks/after_prepare/050_clean_unused_directories.js b/hooks/after_prepare/050_clean_unused_directories.js index 8e0b1c37dc92adb232716d3978037e03a25475ab..31023fc4f14917ef1d496e319c71cc80a910bb9f 100755 --- a/hooks/after_prepare/050_clean_unused_directories.js +++ b/hooks/after_prepare/050_clean_unused_directories.js @@ -23,6 +23,7 @@ if (rootdir && !skip) { let wwwPath; if(platform === 'android') { + //wwwPath = path.join(rootdir, 'platforms', platform, 'app', 'src', 'main', 'assets', 'www'); wwwPath = path.join(rootdir, 'platforms', platform, 'assets', 'www'); } else { wwwPath = path.join(rootdir, 'platforms', platform, 'www'); diff --git a/hooks/after_prepare/060_prepare_android_manifest.js b/hooks/after_prepare/060_prepare_android_manifest.js index fb6e20a198214d8de118ccfeaa6ca639f2867d7a..1769005180e812c82af2ee5a472c96e004ee6fab 100755 --- a/hooks/after_prepare/060_prepare_android_manifest.js +++ b/hooks/after_prepare/060_prepare_android_manifest.js @@ -15,9 +15,10 @@ if (rootdir) { let platform = platforms[x].trim().toLowerCase(); - if(platform = 'android') { - let platformPath = path.join(rootdir, 'platforms', platform); - let androidManifestFile = path.join(platformPath, 'AndroidManifest.xml'); + if (platform === 'android') { + //let srcMainPath = path.join(rootdir, 'platforms', platform, 'app', 'src', 'main'); + let srcMainPath = path.join(rootdir, 'platforms', platform); + let androidManifestFile = path.join(srcMainPath, 'AndroidManifest.xml'); // Clean unused directories console.log('-----------------------------------------'); @@ -38,7 +39,7 @@ if (rootdir) { // add <uses-sdk> (replace 'targetSdkversion' and add tools:overrideLibrary) .pipe(replace(/(<\/manifest>)/, ' <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="29" tools:overrideLibrary="org.kaliumjni.lib" />\n$1')) - .pipe(gulp.dest(platformPath)); + .pipe(gulp.dest(srcMainPath)); console.log('-----------------------------------------'); diff --git a/hooks/after_prepare/061_copy_build_extras.js b/hooks/after_prepare/061_copy_build_extras.js index 117a6c8327253d1682835a7fd3923cda58a3b83d..b648ed504ee05f7c4e093a7b1c7b498d1101d019 100755 --- a/hooks/after_prepare/061_copy_build_extras.js +++ b/hooks/after_prepare/061_copy_build_extras.js @@ -65,13 +65,13 @@ if (rootdir) { } const signing_file = build_dir + '/release-signing.properties'; - if (!fs.existsSync(signing_file)) { + if (!fs.existsSync(signing_file) && !fs.existsSync(android_dir + '/release-signing.properties')) { log(colors.red(' File ' + signing_file + 'not found. Skipping copy to ' + android_dir)); log(colors.red(' WARNING: Release APK files will not be signed !')); } } else { - log(colors.orange(' Directory ' + build_dir + 'not found. Skipping copy to ' + android_dir)); + log(colors.red(' Directory ' + build_dir + 'not found. Skipping copy to ' + android_dir)); } } } catch (e) { diff --git a/package.json b/package.json index c79fcb08071be4187bdb2fdcb51bc59fb1ea35cb..375dfb65483196e5bad21646a7aa110c15b4e9f0 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "start:firefox": "gulp webExtCompile && web-ext run --source-dir ./dist/web/ext/", "docker:build": "sudo docker build . -t cesium/release", "docker:run": "sudo docker run -ti --rm -p 8100:8100 -p 35729:35729 -v .:/cesium:rw cesium/release", - "build:web": "gulp config --env default && gulp webBuild --release" + "build:web": "gulp config --env default && gulp webBuild --release", + "build:webExt": "gulp config --env default && gulp webExtBuild --release" }, "keywords": [ "duniter", @@ -78,6 +79,14 @@ "@bower_components/socket.io-client": "socketio/socket.io-client#^1.7.4", "@bower_components/ui-leaflet": "angular-ui/ui-leaflet#v2.0.0", "@bower_components/underscore": "jashkenas/underscore#1.10.2", + "through2": "^4.0.2", + "uuid": "3.2.1" + }, + "devDependencies": { + "@ionic/cli": "^6.11.0", + "@ionic/v1-toolkit": "^3.2.0", + "@prantlf/gulp-jsonlint": "^2.4.0", + "ansi-colors": "^4.1.1", "cordova": "^8.1.2", "cordova-android": "^8.1.0", "cordova-clipboard": "^1.3.0", @@ -91,10 +100,8 @@ "cordova-plugin-dialogs": "^2.0.2", "cordova-plugin-file": "^6.0.2", "cordova-plugin-ionic-keyboard": "^2.2.0", - "cordova-plugin-ionic-webview": "^4.1.3", - "cordova-plugin-minisodium": "git+https://github.com/duniter-cesium/cordova-plugin-minisodium#v1.0.1", - "cordova-plugin-secure-storage-android10": "git+https://github.com/duniter-cesium/cordova-plugin-secure-storage-android10.git#6.0.4", - "cordova-plugin-splashscreen": "^5.0.3", + "cordova-plugin-ionic-webview": "^4.2.1", + "cordova-plugin-splashscreen": "^5.0.4", "cordova-plugin-statusbar": "^2.4.3", "cordova-plugin-vibration": "^3.1.1", "cordova-plugin-websocket": "^0.12.2", @@ -102,28 +109,27 @@ "cordova-plugin-x-toast": "^2.7.2", "ionic-plugin-keyboard": "^2.2.1", "phonegap-plugin-barcodescanner": "^8.1.0", - "uuid": "3.2.1" - }, - "devDependencies": { - "@ionic/cli": "^6.11.0", - "@ionic/v1-toolkit": "^3.2.3", - "@prantlf/gulp-jsonlint": "git+https://github.com/prantlf/gulp-jsonlint#2.4.0", + "cordova-plugin-customurlscheme": "^5.0.2", + "cordova-plugin-minisodium": "git+https://github.com/duniter-cesium/cordova-plugin-minisodium.git#v1.0.1", + "cordova-plugin-secure-storage-android10": "git+https://github.com/duniter-cesium/cordova-plugin-secure-storage-android10.git#6.0.4", "cordova-uglify": "^0.3.4", "del": "^5.1.0", "delete-empty": "^0.1.3", "event-stream": "3.3.4", + "fancy-log": "^1.3.3", "glob": "^5.0.15", "graceful-fs": "^4.2.3", - "gulp": "4.0.2", + "gulp": "^4.0.2", "gulp-angular-templatecache": "^3.0.0", "gulp-angular-translate": "^0.1.4", - "gulp-base64": "^0.1.3", "gulp-base64-v2": "^1.0.4", "gulp-bump": "^3.1.3", "gulp-clean": "^0.4.0", "gulp-clean-css": "^4.3.0", + "gulp-cli": "^2.3.0", "gulp-css-base64": "^1.3.4", "gulp-csso": "^4.0.1", + "gulp-debug": "^4.0.0", "gulp-filter": "^6.0.0", "gulp-footer": "^2.0.2", "gulp-header": "^2.0.9", @@ -150,13 +156,20 @@ "node-sass": "^4.14.1", "playup": "^1.1.0", "vinyl-fs": "^3.0.3", - "yargs": "^5.0.0", - "web-ext": "^4.3.0" + "web-ext": "^4.3.0", + "yargs": "^5.0.0" }, "peerDependencies": { + "gulp": "^4.0.2", + "gulp-cli": "^2.3.0", "leaflet": "Leaflet/Leaflet#v0.7.7", "nopt": "4.0.1" }, + "resolutions": { + "gulp": "4.0.2", + "gulp-cli": "2.3.0", + "graceful-fs": "4.2.4" + }, "cordovaPlugins": [ "cordova-plugin-whitelist", "cordova-plugin-splashscreen", @@ -173,7 +186,8 @@ "cordova-plugin-minisodium", "phonegap-plugin-barcodescanner", "cordova-plugin-ionic-keyboard", - "cordova-plugin-ionic-webview@4.1.2" + "cordova-plugin-ionic-webview@4.1.2", + "cordova-plugin-customurlscheme" ], "cordovaPlatforms": [ { @@ -191,7 +205,8 @@ "plugins": { "cordova-plugin-camera": { "CAMERA_USAGE_DESCRIPTION": "Add picture to the user profile", - "PHOTOLIBRARY_USAGE_DESCRIPTION": "Take a picture for the user profile" + "PHOTOLIBRARY_USAGE_DESCRIPTION": "Take a picture for the user profile", + "ANDROID_SUPPORT_V4_VERSION": "28.+" }, "cordova-plugin-device": {}, "cordova-plugin-dialogs": {}, @@ -215,7 +230,13 @@ }, "cordova-plugin-file": {}, "cordova-plugin-androidx": {}, - "cordova-plugin-androidx-adapter": {} + "cordova-plugin-androidx-adapter": {}, + "cordova-plugin-customurlscheme": { + "URL_SCHEME": "june", + "ANDROID_SCHEME": " ", + "ANDROID_HOST": " ", + "ANDROID_PATHPREFIX": "/" + } }, "platforms": [ "ios", @@ -224,7 +245,7 @@ ] }, "engines": { - "node": ">= 10.20.0", + "node": ">= 12.18.3", "yarn": ">= 1.22.0" } } diff --git a/www/js/controllers/home-controllers.js b/www/js/controllers/home-controllers.js index 9898e8766b9e93d6a5d7b00fd6a2eb5ebb8497a8..8c0bd8980ea036de7644a4bbb76d042672cc30ff 100644 --- a/www/js/controllers/home-controllers.js +++ b/www/js/controllers/home-controllers.js @@ -26,7 +26,7 @@ angular.module('cesium.home.controllers', ['cesium.platform', 'cesium.services'] .controller('HomeCtrl', HomeController) ; -function HomeController($scope, $state, $timeout, $ionicHistory, $translate, $http, UIUtils, +function HomeController($scope, $state, $timeout, $ionicHistory, $translate, $http, UIUtils, BMA, csConfig, csCache, csPlatform, csCurrency, csSettings, csHttp) { 'ngInject'; @@ -185,39 +185,62 @@ function HomeController($scope, $state, $timeout, $ionicHistory, $translate, $ht console.debug("[home] Detecting external uri: ", uri); var parts = csHttp.uri.parse(uri); - if (parts.protocol === 'g1:') { - console.debug("[home] Applying g1 uri...", parts); + var state,stateParams; - // Transfer - if (parts.hostname && parts.search.indexOf('amount=') !== -1) { - return $state.go('app.new_transfer_pubkey', { - pubkey: parts.hostname - }); - } + if (parts.protocol === 'g1:' || parts.protocol === 'june:') { + console.debug("[home] Applying uri...", parts); // Pubkey - else if (parts.hostname && BMA.regexp.PUBKEY.test(parts.hostname)) { - var pubkey = parts.hostname; - return $state.go('app.wot_identity', { - pubkey: pubkey - }); + if (parts.hostname && BMA.regexp.PUBKEY.test(parts.hostname)) { + state = 'app.wot_identity'; + stateParams = {pubkey: parts.hostname}; + } + else if ((parts.hostname === 'wallet' || parts.hostname === 'pubkey') && BMA.regexp.PUBKEY.test(parts.pathSegments[0])) { + state = 'app.wot_identity'; + stateParams = {pubkey: parts.pathSegments[0]}; } - // Search by uid + // Block + else if (parts.hostname === 'block') { + state = 'app.view_block'; + stateParams = {number: parts.pathSegments[0]}; + } + + // Otherwise, try to a wot lookup else if (parts.hostname && BMA.regexp.USER_ID.test(parts.hostname)) { - var uid = parts.hostname; - return $state.go('app.wot_lookup.tab_search', { - q: uid - }); + state = 'app.wot_lookup.tab_search'; + stateParams = {q: parts.hostname}; } } - else { - console.error("[home] Unknown protocol, in URI: " + uri); + + if (state === 'app.wot_identity' && parts.searchParams && (angular.isDefined(parts.searchParams.action) || angular.isDefined(parts.searchParams.amount))) { + stateParams = angular.merge(stateParams, + // Add default actions + { action: 'transfer'}, + // Add path params + parts.searchParams); } - // Redirect to home - return $state.go('app.home'); - } + // Open the state + if (state) { + $ionicHistory.clearHistory(); + $ionicHistory.nextViewOptions({ + disableAnimate: false, + disableBack: true, + historyRoot: true + }); + return $state.go(state, stateParams, { + reload: true, + inherit: false, + notify: true + }); + } + else { + console.error("[home] Unknown URI format: " + uri); + this.loading = false; + return UIUtils.alert.error("ERROR.UNKNOWN_URI_FORMAT", uri); + } + }; // For DEV ONLY /*$timeout(function() { diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js index 2fe87e0f932e3b2996811efc9d7021fffdd2dcaf..4f109795863360d862e3fc27cc79ae9892c4fcfc 100644 --- a/www/js/controllers/wot-controllers.js +++ b/www/js/controllers/wot-controllers.js @@ -43,7 +43,7 @@ angular.module('cesium.wot.controllers', ['cesium.services']) }) .state('app.wot_identity', { - url: "/wot/:pubkey/:uid?action&block", + url: "/wot/:pubkey/:uid?action&block&amount&comment", views: { 'menuContent': { templateUrl: "templates/wot/view_identity.html", @@ -943,6 +943,8 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ // Reset action param stateParams.action = null; + stateParams.amount = null; + stateParams.comment = null; // Update location href $ionicHistory.nextViewOptions({ @@ -959,10 +961,10 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ }; $scope.doAction = function(action, options) { - if (action == 'certify') { + if (action === 'certify') { return $scope.certify(); } - if (action == 'transfer') { + if (action === 'transfer') { $scope.showTransferModal(options); } }; @@ -1057,7 +1059,7 @@ function WotIdentityViewController($scope, $rootScope, $controller, $timeout, $s $scope.doMotion(); if (state.stateParams && state.stateParams.action) { $timeout(function() { - $scope.doAction(state.stateParams.action.trim()); + $scope.doAction(state.stateParams.action.trim(), state.stateParams); }, 100); $scope.removeActionParamInLocationHref(state); diff --git a/www/js/platform.js b/www/js/platform.js index e081509882d99c2c7b92c71d03c567a79b5353fd..b0fffc3e6f3991030ecee97f1c7c702b07cefe41 100644 --- a/www/js/platform.js +++ b/www/js/platform.js @@ -229,14 +229,18 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] return $q.when(); } - function registerProtocol() { - console.debug("[platform] Register protocol g1://") - try { - navigator.registerProtocolHandler("web+june", "#/app/home?uri=%s", "Cesium"); - } - catch(err) { - console.error(err) - } + function registerProtocols() { + var protocols = ['web+june'/*, 'web+g1', 'g1'*/]; + + _.each(protocols, function(protocol) { + console.debug("[platform] Registering protocol '%s'...".format(protocol)); + try { + navigator.registerProtocolHandler(protocol, "#/app/home?uri=%s", "Cesium"); + } + catch(err) { + console.error("[platform] Error while registering protocol '%s'".format(protocol), err); + } + }); } function addListeners() { @@ -271,7 +275,7 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] // Avoid change state disableChangeState(); - registerProtocol(); + registerProtocols(); // We use 'ionicReady()' instead of '$ionicPlatform.ready()', because this one is callable many times startPromise = ionicReady() diff --git a/www/js/services/http-services.js b/www/js/services/http-services.js index ad5f86cf5e75b4752c7e8c42f94ed53398e8e2ab..dc6f6b173a24393cae060095e14250f75c57bd25 100644 --- a/www/js/services/http-services.js +++ b/www/js/services/http-services.js @@ -317,12 +317,22 @@ angular.module('cesium.http.services', ['cesium.cache.services']) // See doc : https://gist.github.com/jlong/2428561 function parseUri(uri) { - var protocol; + var protocol, hostname; // G1 URI (see G1lien) - if (uri.startsWith('web+june://') || uri.startsWith('g1://')) { - protocol = 'g1:'; - uri = uri.replace(/^(g1|web+june):\/\//, 'http:'); + if (uri.startsWith('g1:') || uri.startsWith('june:') || uri.startsWith('web+june:')) { + protocol = 'june:'; + var path = uri.replace(/^(g1|web\+june|june):(\/\/)?/, ''); + + // Store hostname here, because parse will apply a lowercase + hostname = path; + if (hostname.indexOf('/') !== -1) { + hostname = hostname.substr(0, path.indexOf('/')); + } + if (hostname.indexOf('?') !== -1) { + hostname = hostname.substr(0, path.indexOf('?')); + } + uri = 'http://' + path; } var parser = document.createElement('a'); @@ -333,15 +343,33 @@ angular.module('cesium.http.services', ['cesium.cache.services']) pathname = pathname.substring(1); } + var searchParams; + if (parser.search && parser.search.startsWith('?')) { + searchParams = parser.search.substr(1).split('&') + .reduce(function(res, searchParam) { + if (searchParam.indexOf('=') !== -1) { + var key = searchParam.substr(0, searchParam.indexOf('=')); + var value = searchParam.substr(searchParam.indexOf('=') + 1); + res[key] = value; + } + else { + res[searchParam] = true; // default value + } + return res; + }, {}); + } + var result = { protocol: protocol ? protocol : parser.protocol, - hostname: parser.hostname, + hostname: hostname ? hostname : parser.hostname, host: parser.host, port: parser.port, username: parser.username, password: parser.password, pathname: pathname, + pathSegments: pathname ? pathname.split('/') : [], search: parser.search, + searchParams: searchParams, hash: parser.hash }; parser.remove();