diff --git a/.gitignore b/.gitignore index 4798254e..71e1d6be 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ www/lib/angular-ui-router www/lib/angular-moment www/lib/moment www/lib/waves +www/dist diff --git a/app/config.json b/app/config.json index 2018d1bd..5023d74c 100644 --- a/app/config.json +++ b/app/config.json @@ -4,37 +4,15 @@ "DUNITER_NODE": "cgeek.fr:9330", "NEW_ISSUE_LINK": "https://github.com/duniter/cesium/issues/new?labels=bug", "TIMEOUT": 4000, - "DEBUG": false, - "NATIVE_TRANSITION": false - } - }, - - "duniter-fr": { - "APP_CONFIG": { - "DUNITER_NODE": "cgeek.fr:9330", - "NEW_ISSUE_LINK": "https://github.com/duniter/cesium/issues/new?labels=bug", - "TIMEOUT": 4000, - "DEBUG": false, - "NATIVE_TRANSITION": false - } - }, - - "android": { - "APP_CONFIG": { - "DUNITER_NODE": "cgeek.fr:9330", - "NEW_ISSUE_LINK": "https://github.com/duniter/cesium/issues/new?labels=bug", - "TIMEOUT": 6000, - "DEBUG": false, - "NATIVE_TRANSITION": true + "DEBUG": false } }, "dev": { "APP_CONFIG": { "DUNITER_NODE": "localhost:9201", - "TIMEOUT": 4000, - "DEBUG": false, - "NATIVE_TRANSITION": true + "TIMEOUT": 6000, + "DEBUG": true } } } diff --git a/config.xml b/config.xml index 8044726e..deb1d45d 100644 --- a/config.xml +++ b/config.xml @@ -3,28 +3,32 @@ xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" id="fr.duniter.cesium" - version="0.1.15" - android-versionCode="3" + version="0.1.16" + android-versionCode="4" > - Cesium - - A webapp client for Duniter - - - Duniter team - - - - - - - - - - - - - + Cesium + + A webapp client for Duniter + + + Duniter team + + + + + + + + + + + + + + + + + @@ -73,5 +77,5 @@ - + diff --git a/gulpfile.js b/gulpfile.js index a20e9fc0..c35ec637 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -13,15 +13,34 @@ var fs = require("fs"); var argv = require('yargs').argv; var header = require('gulp-header'); var removeCode = require('gulp-remove-code'); -//var bump = require('gulp-bump'); +var removeHtml = require('gulp-html-remove'); +var templateCache = require('gulp-angular-templatecache'); +var ngTranslate = require('gulp-angular-translate'); +var ngAnnotate = require('gulp-ng-annotate'); +var es = require('event-stream'); +var zip = require('gulp-zip'); +var del = require('del'); +var useref = require('gulp-useref'); +var filter = require('gulp-filter'); +var uglify = require('gulp-uglify'); +var csso = require('gulp-csso'); +var rev = require('gulp-rev'); +var revReplace = require('gulp-rev-replace'); +var clean = require('gulp-clean'); +var htmlmin = require('gulp-htmlmin'); +var deleteEmpty = require('delete-empty'); +var jshint = require('gulp-jshint'); var paths = { sass: ['./scss/**/*.scss'], config: ['./app/config.json'], - templates: ['./www/templates/**/*.html'] + templates: ['./www/templates/**/*.html'], + templatecache: ['./www/templates/**/*.html'], + ng_translate: ['./www/i18n/locale-*.json'], + ng_annotate: ['./www/js/*.js'] }; -gulp.task('default', ['sass', 'config']); +gulp.task('default', ['sass', 'config', 'templatecache', 'ng_translate', 'ng_annotate']); gulp.task('sass', function(done) { gulp.src('./scss/ionic.app.scss') @@ -35,18 +54,12 @@ gulp.task('sass', function(done) { .on('end', done); }); -// TODO : enable to have a special buidl for phone -//gulp.task('removeCode', function(done) { -// gulp.src('./www/templates/**/*.html') -// .pipe(removeCode({ production: true })) -// .pipe(gulp.dest('./dist/templates')) -// .on('end', done); -//}); gulp.task('watch', function() { gulp.watch(paths.sass, ['sass']); - //gulp.watch(paths.config, ['config']); - //gulp.watch(paths.templates, ['removeCode']); + gulp.watch(paths.templatecache, ['templatecache']); + gulp.watch(paths.ng_translate, ['ng_translate']); + gulp.watch(paths.ng_annotate, ['ng_annotate']); }); gulp.task('install', ['git-check'], function() { @@ -102,3 +115,180 @@ gulp.task('config', function (done) { .pipe(gulp.dest('www/js')) ; }); + +gulp.task('templatecache', function (done) { + gulp.src('./www/templates/**/*.html') + .pipe(templateCache({ + standalone:true, + module:"cesium.templates", + root: "templates/" + })) + .pipe(gulp.dest('./www/dist/dist_js/app')) + .on('end', done); +}); + +gulp.task('ng_annotate', function (done) { + gulp.src('./www/js/**/*.js') + .pipe(ngAnnotate({single_quotes: true})) + .pipe(gulp.dest('./www/dist/dist_js/app')) + .on('end', done); +}); + +gulp.task('ng_translate', function() { + return gulp.src('www/i18n/locale-*.json') + .pipe(ngTranslate({standalone:true, module: 'cesium.translations'})) + .pipe(gulp.dest('www/dist/dist_js/app')); +}); + +gulp.task('clean:tmp', function(done) { + return del([ + './tmp' + ]); +}); + +gulp.task('clean:web', function(done) { + return del([ + './platforms/web/www', + './platforms/web/build' + ]); +}); + +gulp.task('copy-files:web', ['clean:tmp', 'clean:web', 'sass', 'config'], function(done) { + var tmpPath = './platforms/web/www'; + es.concat( + // Copy Js (and remove unused code) + gulp.src('./www/js/**/*.js') + .pipe(removeCode({"no-device": true})) + .pipe(jshint()) + .pipe(gulp.dest(tmpPath + '/js')), + + // Copy HTML templates (and remove unused code) + gulp.src('./www/templates/**/*.html') + .pipe(removeCode({"no-device": true})) + .pipe(removeHtml('.hidden-no-device')) + .pipe(removeHtml('[remove-if][remove-if="no-device"]')) + .pipe(htmlmin()) + .pipe(gulp.dest(tmpPath + '/templates')), + + // Copy index.html (and remove unused code) + gulp.src('./www/index.html') + .pipe(removeCode({"no-device": true})) + .pipe(removeHtml('.hidden-no-device')) + .pipe(removeHtml('[remove-if][remove-if="no-device"]')) + .pipe(htmlmin()) + .pipe(gulp.dest(tmpPath)), + + // Copy CSS + gulp.src('./www/css/**/*.*') + .pipe(gulp.dest(tmpPath + '/css')), + + // Copy i18n + gulp.src('./www/i18n/locale-*.json') + .pipe(ngTranslate({standalone:true, module: 'cesium.translations'})) + .pipe(gulp.dest(tmpPath + '/js')), + + // Copy img + gulp.src('./www/img/**/*.*') + .pipe(gulp.dest(tmpPath + '/img')), + + // Copy lib/ionic + gulp.src('./www/lib/ionic/**/*.*') + .pipe(gulp.dest(tmpPath + '/lib/ionic')) + ) + .on('end', done); +}); + +gulp.task('templatecache:web', ['copy-files:web'], function (done) { + var tmpPath = './platforms/web/www'; + gulp.src(tmpPath + '/templates/**/*.html') + .pipe(templateCache({ + standalone:true, + module:"cesium.templates", + root: "templates/" + })) + .pipe(gulp.dest(tmpPath + '/js')) + .on('end', done); +}); + +gulp.task('ng_annotate:web', ['templatecache:web'], function (done) { + var tmpPath = './platforms/web/www'; + var jsFilter = filter(["**/*.js", "!**/vendor/*"]); + + gulp.src(tmpPath + '/js/**/*.js') + .pipe(jsFilter) + .pipe(ngAnnotate({single_quotes: true})) + .pipe(gulp.dest(tmpPath + '/dist/dist_js/app')) + .on('end', done); +}); + +gulp.task('optimize-files:web', ['ng_annotate:web'], function(done) { + var tmpPath = './platforms/web/www'; + var jsFilter = filter(["**/*.js", "!**/vendor/*"], { restore: true }); + var cssFilter = filter("**/*.css", { restore: true }); + var indexHtmlFilter = filter(['**/*', '!**/index.html'], { restore: true }); + + gulp.src(tmpPath + '/index.html') + .pipe(useref()) // Concatenate with gulp-useref + .pipe(jsFilter) + .pipe(uglify()) // Minify any javascript sources + .pipe(jsFilter.restore) + .pipe(cssFilter) + .pipe(csso()) // Minify any CSS sources + .pipe(cssFilter.restore) + .pipe(indexHtmlFilter) + .pipe(rev()) // Rename the concatenated files (but not index.html) + .pipe(indexHtmlFilter.restore) + .pipe(revReplace()) // Substitute in new filenames + .pipe(gulp.dest(tmpPath)) + .on('end', done); +}); + +gulp.task('clean-unused-files:web', ['optimize-files:web'], function(done) { + var tmpPath = './platforms/web/www'; + var jsFilter = filter(["**/*.js", "!**/cesium-*.js"]); + var cssFilter = filter(["**/*.css", "!**/cesium-*.css"]); + + es.concat( + gulp.src(tmpPath + '/js/**/*.js', {read: false}) + .pipe(jsFilter) + .pipe(clean()), + + gulp.src(tmpPath + '/css/**/*.css', {read: false}) + .pipe(cssFilter) + .pipe(clean()) + ) + .on ('end', done); +}); + +gulp.task('clean-unused-directories:web', ['clean-unused-files:web'], function(done) { + var tmpPath = './platforms/web/www'; + return del([ + tmpPath + '/css', + tmpPath + '/templates', + tmpPath + '/js', + tmpPath + '/dist', + tmpPath + '/lib/ionic/scss', + tmpPath + '/lib/ionic/css', + tmpPath + '/lib/ionic/js' + ]); +}); + +gulp.task('zip:web', ['clean-unused-directories:web'], function(done) { + var tmpPath = './platforms/web/www'; + var version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version; + var fileFilter = filter(['**', '!*/templates', '!*/css', '!*/js']); + + gulp.src(tmpPath + '/**/*.*') + .pipe(zip('cesium-web-'+version+'.zip')) + .pipe(fileFilter) + .pipe(gulp.dest('./platforms/web/build')) + .on('end', done); +}); + +gulp.task('build:web', ['zip:web'], function(done) { + var version = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version; + gutil.log(gutil.colors.green("Build for web created at: 'plateforms/web/build/cesium-web-" + version + ".zip'")); + return del([ + './tmp' + ]); +}); diff --git a/hooks/after_prepare/020_remove_code.js b/hooks/after_prepare/020_remove_code.js new file mode 100755 index 00000000..b0d2e089 --- /dev/null +++ b/hooks/after_prepare/020_remove_code.js @@ -0,0 +1,64 @@ +#!/usr/bin/env node +"use strict"; +var gulp = require('gulp'); +var gutil = require('gulp-util'); +var path = require("path"); +var removeCode = require('gulp-remove-code'); +var removeHtml = require('gulp-html-remove'); +var es = require('event-stream'); +var ngAnnotate = require('gulp-ng-annotate'); +var htmlmin = require('gulp-htmlmin'); + +var cmd = process.env.CORDOVA_CMDLINE; +var rootdir = process.argv[2]; +var argv = require('yargs').argv; + +if (rootdir) { + + // go through each of the platform directories that have been prepared + var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []); + + for(var x=0; x -1 || cmd.indexOf("--useref") > -1) { + skip = false; +} + +if (rootdir && !skip) { + + // go through each of the platform directories that have been prepared + var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []); + + for(var x=0; x -1 || cmd.indexOf("--useref") > -1) { + skip = false; +} + +if (rootdir && !skip) { + + // go through each of the platform directories that have been prepared + var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []); + + for(var x=0; x -1 || cmd.indexOf("--minify") > -1) { - if (cmd.indexOf("--release") > -1) { - console.log("WARN: The use of the --release flag is deprecated!! Use --minify instead!"); - } - minify = true; -} -config.showErrStack = (config.showErrStack || false); -config.jsOptions.fromString = true; -if (minify === true) { - var ionicMinify = new ionic_minify_1.Minifier(config, platforms, platformPath); - console.log("Starting minifying your files..."); - ionicMinify.run(); -} diff --git a/hooks/minify-conf.json b/hooks/minify-conf.json deleted file mode 100755 index 0d62bf6d..00000000 --- a/hooks/minify-conf.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "foldersToProcess": [ - "js", - "css", - "img" - ], - "jpgOptions":{ - "quality": 50 - }, - "jsOptions": { - "compress": { - "drop_console": true - } - }, - "cssOptions": { - "keepSpecialComments": 0 - }, - "alwaysRun": false, - "showErrStack": false -} diff --git a/ionic.project b/ionic.project index 60c28f09..614a09d1 100644 --- a/ionic.project +++ b/ionic.project @@ -7,6 +7,9 @@ ], "gulpStartupTasks": [ "sass", + "templatecache", + "ng_translate", + "ng_annotate", "watch" ], "defaultBrowser": "chrome", diff --git a/package.json b/package.json index 74871fa2..6a651a0e 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,9 @@ { "name": "cesium", - "version": "0.1.15", + "version": "0.1.16", "description": "A webapp client for Duniter network", "dependencies": { + "delete-empty": "^0.1.3", "gulp": "^3.9.1", "gulp-bump": "^2.1.0", "gulp-concat": "^2.2.0", @@ -14,11 +15,31 @@ }, "devDependencies": { "bower": "^1.7.3", + "cordova-uglify": "^0.2.3", + "del": "^2.2.0", + "fs": "0.0.2", + "gulp": "^3.9.1", + "gulp-angular-templatecache": "^1.8.0", + "gulp-angular-translate": "^0.1.4", + "gulp-clean": "^0.3.2", + "gulp-csso": "^2.0.0", + "gulp-filter": "^4.0.0", "gulp-header": "^1.7.1", + "gulp-html-remove": "^0.1.1", + "gulp-htmlmin": "^2.0.0", + "gulp-jshint": "^2.0.1", + "gulp-ng-annotate": "^2.0.0", "gulp-ng-constant": "^1.1.0", "gulp-remove-code": "^1.0.2", + "gulp-rev": "^7.0.0", + "gulp-rev-replace": "^0.4.3", + "gulp-uglify": "^1.5.3", + "gulp-useref": "^3.1.0", "gulp-util": "^2.2.14", + "gulp-zip": "^3.2.0", "ionic-minify": "^2.0.8", + "jshint": "^2.9.2", + "mv": "^2.1.1", "shelljs": "^0.3.0", "yargs": "^4.3.1" }, @@ -34,7 +55,8 @@ { "locator": "https://github.com/phonegap/phonegap-plugin-barcodescanner.git", "id": "phonegap-plugin-barcodescanner" - } + }, + "cordova-plugin-camera" ], "cordovaPlatforms": [ "ios", diff --git a/scripts/afterBuild.js b/scripts/afterBuild.js new file mode 100644 index 00000000..3bf6bcdf --- /dev/null +++ b/scripts/afterBuild.js @@ -0,0 +1,23 @@ +module.exports = function(ctx) { + // make sure android platform is part of build + if (ctx.opts.platforms.indexOf('android') < 0) { + return; + } + var fs = ctx.requireCordovaModule('fs'), + path = ctx.requireCordovaModule('path'), + deferral = ctx.requireCordovaModule('q').defer(); + + var platformRoot = path.join(ctx.opts.projectRoot, 'platforms/android'); + var apkFileLocation = path.join(platformRoot, 'build/outputs/apk/android-debug.apk'); + + fs.stat(apkFileLocation, function(err,stats) { + if (err) { + deferral.reject('Operation failed'); + } else { + console.log('Size of ' + apkFileLocation + ' is ' + stats.size +' bytes'); + deferral.resolve(); + } + }); + + return deferral.promise; +}; diff --git a/www/css/style-no-device.css b/www/css/style-no-device.css new file mode 100644 index 00000000..ee28d331 --- /dev/null +++ b/www/css/style-no-device.css @@ -0,0 +1,3 @@ +.hidden-no-device { + display: none !important; +} diff --git a/www/i18n/locale-en.json b/www/i18n/locale-en.json index ae589684..0f42130a 100644 --- a/www/i18n/locale-en.json +++ b/www/i18n/locale-en.json @@ -39,7 +39,7 @@ "CURRENCY": "Currency", "CURRENCIES": "Currencies", "ACCOUNT": "My Account", - "TRANSFER": "Pay", + "TRANSFER": "Send", "SCAN": "Scan", "SETTINGS": "Settings" }, @@ -146,8 +146,7 @@ "BTN_MEMBERSHIP_RENEW": "Renew membership", "BTN_MEMBERSHIP_OUT": "Revoke membership", "BTN_SEND_IDENTITY": "Publish pseudonym (without register)", - "BTN_DETAILS": "Display technical details", - "BTN_HIDE_DETAILS": "Hide technical details", + "BTN_SHOW_DETAILS": "Display technical details", "NEW": { "TITLE": "New Account", "SLIDE_1_TITLE": "Select a money:", diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json index cef3ceb4..7e1ad202 100644 --- a/www/i18n/locale-fr-FR.json +++ b/www/i18n/locale-fr-FR.json @@ -147,7 +147,6 @@ "BTN_MEMBERSHIP_OUT": "Arrêter son adhésion", "BTN_SEND_IDENTITY": "Publier le pseudonyme", "BTN_SHOW_DETAILS": "Afficher les infos techniques", - "BTN_HIDE_DETAILS": "Masquer les infos techniques", "NEW": { "TITLE": "Inscription", "SLIDE_1_TITLE": "Choix de la monnaie :", diff --git a/www/index.html b/www/index.html index c672d2c1..d3a7ee04 100644 --- a/www/index.html +++ b/www/index.html @@ -5,73 +5,81 @@ + + + + + + + - + + + + + + + + - - + + + + + + + + + - + + + + + - - - - - - - + + + + - - - - - - - - - + + - - - - - + + + + + + + + - - - + + - - + + + + + + + + + + + - - - - - - - + + + - - - - - - - - - - - - - - - - - + + + - + diff --git a/www/js/app.js b/www/js/app.js index 36c6aa4c..fb11723c 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -4,7 +4,12 @@ // 'starter' is the name of this angular module example (also set in a attribute in index.html) // the 2nd parameter is an array of 'requires' // 'starter.controllers' is found in controllers.js -angular.module('cesium', ['ionic', 'ngCordova', 'ionic-material', 'ngMessages', 'pascalprecht.translate', 'angularMoment', 'cesium.controllers', 'ngAnimate', 'ionic-native-transitions']) +angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'ngAnimate', 'pascalprecht.translate', 'angularMoment', + 'cesium.controllers', 'cesium.templates','cesium.translations', + // removeIf(no-device) + 'ngCordova', 'ionic-native-transitions', + // endRemoveIf(no-device) + ]) .filter('formatInteger', function() { return function(input) { @@ -85,10 +90,9 @@ angular.module('cesium', ['ionic', 'ngCordova', 'ionic-material', 'ngMessages', // Translation i18n .config(function ($translateProvider) { - $translateProvider.useStaticFilesLoader({ - prefix: 'i18n/locale-', - suffix: '.json' - }) + 'ngInject'; + + $translateProvider .uniformLanguageTag('bcp47') .determinePreferredLanguage() // Cela fait bugger les placeholder (pb d'affichage des accents en FR) @@ -99,51 +103,42 @@ angular.module('cesium', ['ionic', 'ngCordova', 'ionic-material', 'ngMessages', .useStorage('localStorage'); }) - .config(['$httpProvider', 'APP_CONFIG', function($httpProvider, APP_CONFIG) { + .config(function($httpProvider, APP_CONFIG) { + 'ngInject'; + // Set default timeout $httpProvider.defaults.timeout = !!APP_CONFIG.TIMEOUT ? APP_CONFIG.TIMEOUT : 4000 /* default timeout */; - }]) - .config(['$compileProvider', 'APP_CONFIG', function($compileProvider, APP_CONFIG) { - $compileProvider.debugInfoEnabled(!!APP_CONFIG.DEBUG); - }]) + //Enable cross domain calls + $httpProvider.defaults.useXDomain = true; + + //Remove the header used to identify ajax call that would prevent CORS from working + delete $httpProvider.defaults.headers.common['X-Requested-With']; + }) + + .config(function($compileProvider, APP_CONFIG) { + 'ngInject'; + + $compileProvider.debugInfoEnabled(!!APP_CONFIG.DEBUG); + }) .config(function($animateProvider) { - $animateProvider.classNameFilter( /\banimate-/ ); - }) - - .config(['$ionicNativeTransitionsProvider', 'APP_CONFIG', function($ionicNativeTransitionsProvider, APP_CONFIG){ - if (!!APP_CONFIG.NATIVE_TRANSITION) { - $ionicNativeTransitionsProvider.enable(true); - $ionicNativeTransitionsProvider.setDefaultOptions({ - duration: 400, // in milliseconds (ms), default 400, - slowdownfactor: 4, // overlap views (higher number is more) or no overlap (1), default 4 - iosdelay: -1, // ms to wait for the iOS webview to update before animation kicks in, default -1 - androiddelay: -1, // same as above but for Android, default -1 - winphonedelay: -1, // same as above but for Windows Phone, default -1, - fixedPixelsTop: 0, // the number of pixels of your fixed header, default 0 (iOS and Android) - fixedPixelsBottom: 0, // the number of pixels of your fixed footer (f.i. a tab bar), default 0 (iOS and Android) - triggerTransitionEvent: '$ionicView.afterEnter', // internal ionic-native-transitions option - backInOppositeDirection: false // Takes over default back transition and state back transition to use the opposite direction transition to go back - }); - $ionicNativeTransitionsProvider.setDefaultTransition({ - type: 'slide', - direction: 'left' - }); - $ionicNativeTransitionsProvider.setDefaultBackTransition({ - type: 'slide', - direction: 'right' - }); - } - else { - $ionicNativeTransitionsProvider.enable(false); - } - }]) + 'ngInject'; + $animateProvider.classNameFilter( /\banimate-/ ); + }) + + // removeIf(no-device) + .config(function($ionicNativeTransitionsProvider){ + 'ngInject'; + // Use native transition + var enableNativeTransitions = ionic.Platform.isAndroid() || ionic.Platform.isIOS(); + $ionicNativeTransitionsProvider.enable(enableNativeTransitions); + }) + // endRemoveIf(no-device) .config(function($ionicConfigProvider) { - if (ionic.Platform.isAndroid()) { - $ionicConfigProvider.scrolling.jsScrolling(false); - } - $ionicConfigProvider.views.maxCache(5); + 'ngInject'; + $ionicConfigProvider.scrolling.jsScrolling(false); + $ionicConfigProvider.views.maxCache(5); }) // Add new compare-to directive (need for form validation) @@ -167,28 +162,30 @@ angular.module('cesium', ['ionic', 'ngCordova', 'ionic-material', 'ngMessages', }) // Add a copy-on-click directive - .directive('copyOnClick', ['$window', 'Device', function ($window, Device) { - return { - restrict: 'A', - link: function (scope, element, attrs) { - element.bind('click', function () { - if (!Device.clipboard.enable) { - if ($window.getSelection && !$window.getSelection().toString() && this.value) { - this.setSelectionRange(0, this.value.length); - } - } - }); - element.bind('hold', function () { - if (Device.clipboard.enable && this.value) { - Device.clipboard.copy(this.value); - } - }); + .directive('copyOnClick', function ($window, Device) { + 'ngInject'; + return { + restrict: 'A', + link: function (scope, element, attrs) { + element.bind('click', function () { + if (!Device.clipboard.enable) { + if ($window.getSelection && !$window.getSelection().toString() && this.value) { + this.setSelectionRange(0, this.value.length); + } } - }; - }]) + }); + element.bind('hold', function () { + if (Device.clipboard.enable && this.value) { + Device.clipboard.copy(this.value); + } + }); + } + }; + }) // Add a select-on-click directive - .directive('selectOnClick', ['$window', function ($window) { + .directive('selectOnClick', function ($window) { + 'ngInject'; return { restrict: 'A', link: function (scope, element, attrs) { @@ -199,20 +196,29 @@ angular.module('cesium', ['ionic', 'ngCordova', 'ionic-material', 'ngMessages', }); } }; - }]) + }) .run(function($rootScope, amMoment, $translate, Device) { - - $rootScope.translations = []; + 'ngInject'; // We use 'Device.ready()' instead of '$ionicPlatform.ready()', because it could be call many times Device.ready() .then(function() { - // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard - // for form inputs) + + // Keyboard if (window.cordova && window.cordova.plugins.Keyboard) { + // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard + // for form inputs) cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); + + // iOS: do not push header up when opening keyboard + // (see http://ionicframework.com/docs/api/page/keyboard/) + if (ionic.Platform.isIOS()) { + cordova.plugins.Keyboard.disableScroll(true); + } } + + // Status bar if (window.StatusBar) { // org.apache.cordova.statusbar required StatusBar.styleDefault(); @@ -227,6 +233,5 @@ angular.module('cesium', ['ionic', 'ngCordova', 'ionic-material', 'ngMessages', // Set up moment translation $rootScope.$on('$translateChangeSuccess', $rootScope.onLanguageChange); - }) ; diff --git a/www/js/config.js b/www/js/config.js index 38d6abed..a3bb9fc0 100644 --- a/www/js/config.js +++ b/www/js/config.js @@ -13,9 +13,8 @@ angular.module("cesium.config", []) "NEW_ISSUE_LINK": "https://github.com/duniter/cesium/issues/new?labels=bug", "TIMEOUT": 4000, "DEBUG": false, - "NATIVE_TRANSITION": false, - "VERSION": "0.1.15", - "BUILD_DATE": "2016-06-09T19:28:59.710Z" + "VERSION": "0.1.16", + "BUILD_DATE": "2016-06-13T13:42:57.980Z" }) ; \ No newline at end of file diff --git a/www/js/controllers.js b/www/js/controllers.js index 0dadbc69..aaef8c84 100644 --- a/www/js/controllers.js +++ b/www/js/controllers.js @@ -9,12 +9,4 @@ angular.module('cesium.controllers', [ 'cesium.transfer.controllers', 'cesium.settings.controllers' ]) - - .config(function($httpProvider) { - //Enable cross domain calls - $httpProvider.defaults.useXDomain = true; - - //Remove the header used to identify ajax call that would prevent CORS from working - delete $httpProvider.defaults.headers.common['X-Requested-With']; - }) ; diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js index a0c61a98..14b48ce1 100644 --- a/www/js/controllers/app-controllers.js +++ b/www/js/controllers/app-controllers.js @@ -2,14 +2,18 @@ angular.module('cesium.app.controllers', ['cesium.services']) .config(function($httpProvider) { + 'ngInject'; + //Enable cross domain calls - $httpProvider.defaults.useXDomain = true; + $httpProvider.defaults.useXDomain = true; //Remove the header used to identify ajax call that would prevent CORS from working delete $httpProvider.defaults.headers.common['X-Requested-With']; }) .config(function($stateProvider, $urlRouterProvider) { + 'ngInject'; + $stateProvider .state('app', { @@ -29,6 +33,8 @@ angular.module('cesium.app.controllers', ['cesium.services']) ; function LoginModalController($scope, $rootScope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate, $ionicHistory) { + 'ngInject'; + // Login modal $scope.loginModal = null; $scope.loginData = { @@ -134,6 +140,11 @@ function LoginModalController($scope, $rootScope, $ionicModal, Wallet, CryptoUti if(!$scope.loginForm.$valid) { return; } + // removeIf(no-device) + if (window.cordova && cordova.plugins.Keyboard) { + cordova.plugins.Keyboard.close(); + } + // endRemoveIf(no-device) UIUtils.loading.show(); $scope.loginModal.hide() @@ -233,12 +244,10 @@ function LoginModalController($scope, $rootScope, $ionicModal, Wallet, CryptoUti function AppController($scope, $rootScope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, CryptoUtils, BMA, Wallet, APP_CONFIG, $ionicHistory, Device, $translate, $ionicPopover ) { + 'ngInject'; $scope.knownCurrencies = null; $scope.search = { text: '', results: {} }; - $scope.isExpanded = false; - $scope.hasHeaderFabLeft = false; - $scope.hasHeaderFabRight = false; $scope.config = APP_CONFIG; LoginModalController.call(this, $scope, $rootScope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate, $ionicHistory); @@ -304,70 +313,6 @@ function AppController($scope, $rootScope, $ionicModal, $state, $ionicSideMenuDe //////////////////////////////////////// // Layout Methods //////////////////////////////////////// - /*var navIcons = document.getElementsByClassName('ion-navicon'); - for (var i = 0; i < navIcons.length; i++) { - navIcons.addEventListener('click', function() { - this.classList.toggle('active'); - }); - }*/ - - $scope.hideNavBar = function() { - document.getElementsByTagName('ion-nav-bar')[0].style.display = 'none'; - }; - - $scope.showNavBar = function() { - document.getElementsByTagName('ion-nav-bar')[0].style.display = 'block'; - }; - - $scope.noHeader = function() { - var content = document.getElementsByTagName('ion-content'); - for (var i = 0; i < content.length; i++) { - if (content[i].classList.contains('has-header')) { - content[i].classList.toggle('has-header'); - } - } - }; - - $scope.setExpanded = function(bool) { - $scope.isExpanded = bool; - }; - - $scope.setHeaderFab = function(location) { - var hasHeaderFabLeft = false; - var hasHeaderFabRight = false; - - switch (location) { - case 'left': - hasHeaderFabLeft = true; - break; - case 'right': - hasHeaderFabRight = true; - break; - } - - $scope.hasHeaderFabLeft = hasHeaderFabLeft; - $scope.hasHeaderFabRight = hasHeaderFabRight; - }; - - $scope.hasHeader = function() { - var content = document.getElementsByTagName('ion-content'); - for (var i = 0; i < content.length; i++) { - if (!content[i].classList.contains('has-header')) { - content[i].classList.toggle('has-header'); - } - } - }; - - $scope.hideHeader = function() { - $scope.hideNavBar(); - $scope.noHeader(); - }; - - $scope.showHeader = function() { - $scope.showNavBar(); - $scope.hasHeader(); - }; - $scope.showFab = function(id, timeout) { if (!timeout) { timeout = 900; diff --git a/www/js/controllers/currency-charts-controllers.js b/www/js/controllers/currency-charts-controllers.js index 7ea54720..57189f67 100644 --- a/www/js/controllers/currency-charts-controllers.js +++ b/www/js/controllers/currency-charts-controllers.js @@ -2,10 +2,16 @@ angular.module('cesium.currency-charts.controllers', ['cesium.services']) .config(function($stateProvider, $urlRouterProvider) { + 'ngInject'; + $stateProvider .state('app.currency_ud', { url: "/currency/ud", + nativeTransitions: { + "type": "flip", + "direction": "up" + }, views: { 'menuContent': { templateUrl: "templates/currency/charts/ud.html", @@ -21,6 +27,7 @@ angular.module('cesium.currency-charts.controllers', ['cesium.services']) ; function CurrencyUdController($scope, BMA, $q) { + 'ngInject'; $scope.$on('$ionicView.enter', function(e, $state) { $scope.loadUds() diff --git a/www/js/controllers/currency-controllers.js b/www/js/controllers/currency-controllers.js index c2b8c6ab..fbe7871e 100644 --- a/www/js/controllers/currency-controllers.js +++ b/www/js/controllers/currency-controllers.js @@ -2,6 +2,8 @@ angular.module('cesium.currency.controllers', ['cesium.services']) .config(function($stateProvider, $urlRouterProvider) { + 'ngInject'; + $stateProvider .state('app.currency_lookup', { @@ -36,6 +38,10 @@ angular.module('cesium.currency.controllers', ['cesium.services']) .state('app.view_peer', { url: "/peer/:server", + nativeTransitions: { + "type": "flip", + "direction": "right" + }, views: { 'menuContent': { templateUrl: "templates/currency/view_peer.html", @@ -54,6 +60,7 @@ angular.module('cesium.currency.controllers', ['cesium.services']) ; function CurrencyLookupController($scope, $state, $q, $timeout, UIUtils, APP_CONFIG, BMA) { + 'ngInject'; $scope.selectedCurrency = ''; $scope.knownCurrencies = []; diff --git a/www/js/controllers/home-controllers.js b/www/js/controllers/home-controllers.js index 7bcb615d..15e35ca9 100644 --- a/www/js/controllers/home-controllers.js +++ b/www/js/controllers/home-controllers.js @@ -2,6 +2,7 @@ angular.module('cesium.home.controllers', ['cesium.services']) .config(function($stateProvider, $urlRouterProvider) { + 'ngInject'; $stateProvider .state('app.home', { @@ -37,6 +38,7 @@ angular.module('cesium.home.controllers', ['cesium.services']) function NewAccountWizardController($scope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, CryptoUtils, BMA, Wallet) { + 'ngInject'; $scope.accountData = {}; $scope.accountForm = {}; @@ -196,12 +198,14 @@ function NewAccountWizardController($scope, $ionicModal, $state, $ionicSideMenuD } function HomeController($scope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, CryptoUtils, BMA, Wallet, APP_CONFIG) { + 'ngInject'; NewAccountWizardController.call(this, $scope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, CryptoUtils, BMA, Wallet); } function JoinController($scope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, CryptoUtils, BMA, Wallet, APP_CONFIG) { + 'ngInject'; NewAccountWizardController.call(this, $scope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, CryptoUtils, BMA, Wallet); diff --git a/www/js/controllers/peer-controllers.js b/www/js/controllers/peer-controllers.js index 54fe5bbb..e0a1cce0 100644 --- a/www/js/controllers/peer-controllers.js +++ b/www/js/controllers/peer-controllers.js @@ -1,5 +1,6 @@ function PeerController($scope, $rootScope, $ionicSlideBoxDelegate, $ionicModal, BMA, $controller) { + 'ngInject'; $scope.$on('$ionicView.enter', function(e, $state) { $scope.showPeer($state.stateParams.server); diff --git a/www/js/controllers/settings-controllers.js b/www/js/controllers/settings-controllers.js index 5e4ba0c0..2acb70ac 100644 --- a/www/js/controllers/settings-controllers.js +++ b/www/js/controllers/settings-controllers.js @@ -1,7 +1,8 @@ angular.module('cesium.settings.controllers', ['cesium.services', 'cesium.currency.controllers']) - .config(function($stateProvider, $urlRouterProvider) { + 'ngInject'; + $stateProvider .state('app.settings', { @@ -20,6 +21,7 @@ angular.module('cesium.settings.controllers', ['cesium.services', 'cesium.curren ; function SettingsController($scope, $state, UIUtils, Wallet, $translate, BMA, $q, $ionicPopup, $timeout, localStorage) { + 'ngInject'; $scope.locales = [ {id:'fr-FR', label:'Français'}, diff --git a/www/js/controllers/transfer-controllers.js b/www/js/controllers/transfer-controllers.js index 8e418bf5..bc56de1a 100644 --- a/www/js/controllers/transfer-controllers.js +++ b/www/js/controllers/transfer-controllers.js @@ -1,6 +1,7 @@ angular.module('cesium.transfer.controllers', ['cesium.services', 'cesium.currency.controllers']) .config(function($stateProvider, $urlRouterProvider) { + 'ngInject'; $stateProvider .state('app.new_transfer', { @@ -39,6 +40,7 @@ angular.module('cesium.transfer.controllers', ['cesium.services', 'cesium.curren ; function TransferController($scope, $rootScope, $ionicModal, $state, BMA, Wallet, UIUtils, $timeout, Device, $ionicPopover) { + 'ngInject'; TransferModalController.call(this, $scope, $rootScope, $ionicModal, $state, BMA, Wallet, UIUtils, $timeout, Device, $ionicPopover); @@ -64,6 +66,7 @@ function TransferController($scope, $rootScope, $ionicModal, $state, BMA, Wallet } function TransferModalController($scope, $rootScope, $ionicModal, $state, BMA, Wallet, UIUtils, $timeout, Device, $ionicPopover) { + 'ngInject'; $scope.walletData = {}; $scope.convertedBalance = 0; diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js index fbece05c..26a81259 100644 --- a/www/js/controllers/wallet-controllers.js +++ b/www/js/controllers/wallet-controllers.js @@ -2,6 +2,7 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency.controllers']) .config(function($stateProvider, $urlRouterProvider) { + 'ngInject'; $stateProvider .state('app.view_wallet', { @@ -21,6 +22,7 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency function WalletController($scope, $rootScope, $state, $q, $ionicPopup, $ionicActionSheet, $timeout, UIUtils, Wallet, BMA, $translate, Device, $ionicPopover) { + 'ngInject'; $scope.walletData = null; $scope.convertedBalance = null; @@ -276,53 +278,6 @@ function WalletController($scope, $rootScope, $state, $q, $ionicPopup, $ionicAct .catch(UIUtils.onError('ERROR.REFRESH_WALLET_DATA')); }; - // Triggered on a button click, or some other target - $scope.showActionsheet = function() { - - $translate(['ACCOUNT.MENU_TITLE', 'ACCOUNT.BTN_MEMBERSHIP_IN', 'ACCOUNT.BTN_MEMBERSHIP_RENEW', 'ACCOUNT.BTN_MEMBERSHIP_OUT', 'ACCOUNT.BTN_SEND_IDENTITY', - 'ACCOUNT.POPUP_REGISTER.HELP', 'ACCOUNT.BTN_DETAILS', 'COMMON.BTN_ADD_ACCOUNT', 'COMMON.BTN_CANCEL']) - .then(function (translations) { - - var buttons = []; - var callbacks = []; - if ($scope.walletData.requirements.needMembership) { - buttons.push({text: translations['ACCOUNT.BTN_MEMBERSHIP_IN']}); - callbacks.push(function(){$scope.membershipIn();}); - } - if ($scope.walletData.requirements.needRenew) { - buttons.push({text: translations['ACCOUNT.BTN_MEMBERSHIP_RENEW']}); - callbacks.push(function(){$scope.membershipRenew();}); - } - if ($scope.walletData.requirements.needSelf) { - buttons.push({text: translations['ACCOUNT.BTN_SEND_IDENTITY']}); - callbacks.push(function(){$scope.self();}); - } - if ($scope.walletData.requirements.needMembershipOut) { - buttons.push({text: translations['ACCOUNT.BTN_MEMBERSHIP_OUT']}); - callbacks.push(function(){$scope.membershipOut();}); - } - - // Show the action sheet - var hideMenu = $ionicActionSheet.show({ - buttons: buttons, - titleText: translations['ACCOUNT.MENU_TITLE'], - cancelText: translations['COMMON.BTN_CANCEL'], - cancel: function() { - // add cancel code.. - }, - buttonClicked: function(index) { - callbacks[index](); - return true; - } - }); - - // Hide the sheet after 3 seconds - $timeout(function() { - hideMenu(); - }, 3000); - }); - }; - $scope.showQRCode = function(id, text, timeout) { if (!!$scope.qrcode) { return; diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js index d69eafbb..3311175a 100644 --- a/www/js/controllers/wot-controllers.js +++ b/www/js/controllers/wot-controllers.js @@ -1,6 +1,7 @@ angular.module('cesium.wot.controllers', ['cesium.services']) .config(function($stateProvider, $urlRouterProvider) { + 'ngInject'; $stateProvider .state('app.wot_lookup', { @@ -25,6 +26,10 @@ angular.module('cesium.wot.controllers', ['cesium.services']) .state('app.view_certifications', { url: "/wot/cert/:pub", + nativeTransitions: { + "type": "flip", + "direction": "right" + }, views: { 'menuContent': { templateUrl: "templates/wot/view_certifications.html", @@ -43,6 +48,7 @@ angular.module('cesium.wot.controllers', ['cesium.services']) ; function WotLookupController($scope, BMA, $state, UIUtils, $timeout, Device, Wallet) { + 'ngInject'; $scope.onWotSearchChanged = function() { $scope.search.looking = true; @@ -126,6 +132,7 @@ function WotLookupController($scope, BMA, $state, UIUtils, $timeout, Device, Wal } function WotIdentityViewController($scope, $state, BMA, Wallet, UIUtils, $q, $timeout, Device) { + 'ngInject'; $scope.identity = {}; $scope.hasSelf = false; @@ -228,26 +235,6 @@ function WotIdentityViewController($scope, $state, BMA, Wallet, UIUtils, $q, $ti }); }; - // Certify click - $scope.certifyIdentity = function(identity) { - $scope.loadWallet() - .then(function(walletData) { - UIUtils.loading.show(); - - // TODO: ask user confirm - see issue https://github.com/duniter/cesium/issues/12 - Wallet.certify($scope.identity.uid, - $scope.identity.pub, - $scope.identity.timestamp, - $scope.identity.sig) - .then(function() { - UIUtils.loading.hide(); - UIUtils.alert.info('INFO.CERTIFICATION_DONE'); - }) - .catch(UIUtils.onError('ERROR.SEND_CERTIFICATION_FAILED')); - }) - .catch(UIUtils.onError('ERROR.LOGIN_FAILED')); - }; - // Copy $scope.copy = function(value) { if (value && Device.isEnable()) { @@ -264,15 +251,11 @@ function WotIdentityViewController($scope, $state, BMA, Wallet, UIUtils, $q, $ti } }; - // Set Header - $scope.$parent.showHeader(); - $scope.isExpanded = false; - $scope.$parent.setExpanded(false); - $scope.$parent.setHeaderFab(false); $scope.showFab('fab-transfer'); } function WotCertificationsViewController($scope, $state, BMA, Wallet, UIUtils, $q, $timeout, Device) { + 'ngInject'; $scope.certifications = []; $scope.identity = {}; @@ -430,11 +413,4 @@ function WotCertificationsViewController($scope, $state, BMA, Wallet, UIUtils, $ $scope.doUpdate = function() { $scope.loadCertifications($scope.identity.pub, true); }; - - // Set Header - $scope.$parent.showHeader(); - $scope.isExpanded = false; - $scope.$parent.setExpanded(false); - $scope.$parent.setHeaderFab(false); - } diff --git a/www/js/services.js b/www/js/services.js index d93c2aab..6e0d3ed9 100644 --- a/www/js/services.js +++ b/www/js/services.js @@ -3,6 +3,7 @@ angular.module('cesium.services', [ 'cesium.bma.services', 'cesium.crypto.services', 'cesium.utils.services', + 'cesium.storage.services', 'cesium.device.services', 'cesium.wallet.services' ]) diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js index a4329586..39027054 100644 --- a/www/js/services/bma-services.js +++ b/www/js/services/bma-services.js @@ -4,6 +4,7 @@ angular.module('cesium.bma.services', ['ngResource', 'cesium.config']) .factory('BMA', function($http, $q, APP_CONFIG) { + 'ngInject'; function BMA(server, timeout) { diff --git a/www/js/services/crypto-services.js b/www/js/services/crypto-services.js index 112356b5..c386bba2 100644 --- a/www/js/services/crypto-services.js +++ b/www/js/services/crypto-services.js @@ -3,168 +3,169 @@ angular.module('cesium.crypto.services', ['ngResource']) .factory('CryptoUtils', function($q, $timeout) { + 'ngInject'; - var async_load_scrypt = function() { - if (typeof module !== 'undefined' && module.exports) { - // add node.js implementations - require('scrypt-em'); - return scrypt_module_factory(); - } - else if (scrypt_module_factory !== null){ - return scrypt_module_factory(); - } - else { - return $timeout(async_load_scrypt, 100); - } - }, + var async_load_scrypt = function() { + if (typeof module !== 'undefined' && module.exports) { + // add node.js implementations + require('scrypt-em'); + return scrypt_module_factory(); + } + else if (scrypt_module_factory !== null){ + return scrypt_module_factory(); + } + else { + return $timeout(async_load_scrypt, 100); + } + }, - async_load_nacl = function() { - if (typeof module !== 'undefined' && module.exports) { - // add node.js implementations - require('nacl_factory'); - return nacl_factory.instantiate(); - } - else if (nacl_factory !== null){ - return nacl_factory.instantiate(); - } - else { - return $timeout(async_load_nacl, 100); - } - }, + async_load_nacl = function() { + if (typeof module !== 'undefined' && module.exports) { + // add node.js implementations + require('nacl_factory'); + return nacl_factory.instantiate(); + } + else if (nacl_factory !== null){ + return nacl_factory.instantiate(); + } + else { + return $timeout(async_load_nacl, 100); + } + }, - async_load_base58 = function() { - if (typeof module !== 'undefined' && module.exports) { - // add node.js implementations - require('base58'); - return Base58; - } - else if (Base58 !== null){ - return Base58; - } - else { - return $timeout(async_load_base58, 100); - } - }, + async_load_base58 = function() { + if (typeof module !== 'undefined' && module.exports) { + // add node.js implementations + require('base58'); + return Base58; + } + else if (Base58 !== null){ + return Base58; + } + else { + return $timeout(async_load_base58, 100); + } + }, - async_load_base64 = function() { - if (typeof module !== 'undefined' && module.exports) { - // add node.js implementations - require('base58'); - return Base64; - } - else if (Base64 !== null){ - return Base64; - } - else { - return setTimetout(async_load_base64, 100); - } - }; + async_load_base64 = function() { + if (typeof module !== 'undefined' && module.exports) { + // add node.js implementations + require('base58'); + return Base64; + } + else if (Base64 !== null){ + return Base64; + } + else { + return setTimetout(async_load_base64, 100); + } + }; - function CryptoUtils() { - var - // Const - crypto_sign_BYTES= 64, - SEED_LENGTH= 32, // Length of the key - SCRYPT_PARAMS= { - "N":4096, - "r":16, - "p":1 - }, + function CryptoUtils() { + var + // Const + crypto_sign_BYTES= 64, + SEED_LENGTH= 32, // Length of the key + SCRYPT_PARAMS= { + "N":4096, + "r":16, + "p":1 + }, - // load libraries - scrypt = async_load_scrypt(), - nacl = async_load_nacl(), - base58 = async_load_base58(), - base64 = async_load_base64(), - decode_utf8 = function(s) { - var i, d = unescape(encodeURIComponent(s)), b = new Uint8Array(d.length); - for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i); - return b; - }, - encode_base58 = function(a) { - return base58.encode(a); - }, - hash_sha256 = function(message) { - return $q(function(resolve, reject) { - var msg = decode_utf8(message); - var hash = nacl.to_hex(nacl.crypto_hash_sha256(msg)); - resolve(hash.toUpperCase()); - }); - }, - - /** - * Create a key pair, from salt+password, and return a wallet object - */ - connect = function(salt, password) { - return $q(function(resolve, reject) { - var seed = scrypt.crypto_scrypt( - nacl.encode_utf8(password), - nacl.encode_utf8(salt), - 4096, 16, 1, 32 // TODO: put in var SCRYPT_PARAMS - ); - var keypair = nacl.crypto_sign_keypair_from_seed(seed); - resolve(keypair); - }); - }, + // load libraries + scrypt = async_load_scrypt(), + nacl = async_load_nacl(), + base58 = async_load_base58(), + base64 = async_load_base64(), + decode_utf8 = function(s) { + var i, d = unescape(encodeURIComponent(s)), b = new Uint8Array(d.length); + for (i = 0; i < d.length; i++) b[i] = d.charCodeAt(i); + return b; + }, + encode_base58 = function(a) { + return base58.encode(a); + }, + hash_sha256 = function(message) { + return $q(function(resolve, reject) { + var msg = decode_utf8(message); + var hash = nacl.to_hex(nacl.crypto_hash_sha256(msg)); + resolve(hash.toUpperCase()); + }); + }, - /** - * Verify a signature of a message, for a pubkey - */ - verify = function (message, signature, pubkey) { + /** + * Create a key pair, from salt+password, and return a wallet object + */ + connect = function(salt, password) { return $q(function(resolve, reject) { - var msg = decode_utf8(message); - var sig = base64.decode(signature); - var pub = base58.decode(pubkey); - var m = new Uint8Array(crypto_sign_BYTES + msg.length); - var sm = new Uint8Array(crypto_sign_BYTES + msg.length); - var i; - for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; - for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; - - // Call to verification lib... - var verified = nacl.crypto_sign_open(sm, pub) !== null; - resolve(verified); - }); + var seed = scrypt.crypto_scrypt( + nacl.encode_utf8(password), + nacl.encode_utf8(salt), + 4096, 16, 1, 32 // TODO: put in var SCRYPT_PARAMS + ); + var keypair = nacl.crypto_sign_keypair_from_seed(seed); + resolve(keypair); + }); }, - /** - * Sign a message, from a wallet - */ - sign = function(message, keypair) { + /** + * Verify a signature of a message, for a pubkey + */ + verify = function (message, signature, pubkey) { return $q(function(resolve, reject) { - var m = decode_utf8(message); - var sk = keypair.signSk; - var signedMsg = nacl.crypto_sign(m, sk); - var sig = new Uint8Array(crypto_sign_BYTES); - for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; - var signature = base64.encode(sig); - resolve(signature); - }); - }; + var msg = decode_utf8(message); + var sig = base64.decode(signature); + var pub = base58.decode(pubkey); + var m = new Uint8Array(crypto_sign_BYTES + msg.length); + var sm = new Uint8Array(crypto_sign_BYTES + msg.length); + var i; + for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; + for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; + + // Call to verification lib... + var verified = nacl.crypto_sign_open(sm, pub) !== null; + resolve(verified); + }); + }, - // Service's exposed methods - return { - /* - TODO: uncomment if need to expose - nacl: nacl, - scrypt: scrypt, - base58: base58, - base64: base64,*/ - util: { - encode_utf8: nacl.encode_utf8, - decode_utf8: decode_utf8, - encode_base58: encode_base58, - hash: hash_sha256 - }, - connect: connect, - sign: sign, - verify: verify - //,isCompatible: isCompatible - }; - } + /** + * Sign a message, from a wallet + */ + sign = function(message, keypair) { + return $q(function(resolve, reject) { + var m = decode_utf8(message); + var sk = keypair.signSk; + var signedMsg = nacl.crypto_sign(m, sk); + var sig = new Uint8Array(crypto_sign_BYTES); + for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; + var signature = base64.encode(sig); + resolve(signature); + }); + }; + + // Service's exposed methods + return { + /* + TODO: uncomment if need to expose + nacl: nacl, + scrypt: scrypt, + base58: base58, + base64: base64,*/ + util: { + encode_utf8: nacl.encode_utf8, + decode_utf8: decode_utf8, + encode_base58: encode_base58, + hash: hash_sha256 + }, + connect: connect, + sign: sign, + verify: verify + //,isCompatible: isCompatible + }; + } - var service = CryptoUtils(); - service.instance = CryptoUtils; + var service = CryptoUtils(); + service.instance = CryptoUtils; return service; }) ; diff --git a/www/js/services/device-services.js b/www/js/services/device-services.js index c5a3146e..a15ff562 100644 --- a/www/js/services/device-services.js +++ b/www/js/services/device-services.js @@ -1,8 +1,14 @@ angular.module('cesium.device.services', ['ngResource', 'cesium.utils.services']) -.factory('Device', ['UIUtils', '$translate', '$ionicPopup', '$cordovaClipboard', '$cordovaBarcodeScanner', '$q', '$cordovaCamera', '$ionicPlatform', - function(UIUtils, $translate, $ionicPopup, $cordovaClipboard, $cordovaBarcodeScanner, $q, $cordovaCamera, $ionicPlatform) { +.factory('Device', + function(UIUtils, $translate, $ionicPopup, $q, + // removeIf(no-device) + $cordovaClipboard, $cordovaBarcodeScanner, $cordovaCamera, + // endRemoveIf(no-device) + $ionicPlatform + ) { + 'ngInject'; var CONST = { MAX_HEIGHT: 400, @@ -132,6 +138,6 @@ angular.module('cesium.device.services', ['ngResource', 'cesium.utils.services'] scan: scan } }; -}]) +}) ; diff --git a/www/js/services/storage-services.js b/www/js/services/storage-services.js new file mode 100644 index 00000000..f4e68fb3 --- /dev/null +++ b/www/js/services/storage-services.js @@ -0,0 +1,20 @@ +angular.module('cesium.storage.services', ['ngResource']) + +.factory('localStorage', function($window) { + 'ngInject'; + return { + put: function(key, value) { + $window.localStorage[key] = value; + }, + get: function(key, defaultValue) { + return $window.localStorage[key] || defaultValue; + }, + setObject: function(key, value) { + $window.localStorage[key] = JSON.stringify(value); + }, + getObject: function(key) { + return JSON.parse($window.localStorage[key] || '{}'); + } + }; +}) +; diff --git a/www/js/services/utils-services.js b/www/js/services/utils-services.js index 8e45b7ba..69441573 100644 --- a/www/js/services/utils-services.js +++ b/www/js/services/utils-services.js @@ -1,9 +1,8 @@ -//var Base58, Base64, scrypt_module_factory = null, nacl_factory = null; - angular.module('cesium.utils.services', ['ngResource']) -.factory('UIUtils', ['$ionicLoading', '$ionicPopup', '$translate', '$q', 'ionicMaterialInk', 'ionicMaterialMotion', '$window', '$timeout', +.factory('UIUtils', function($ionicLoading, $ionicPopup, $translate, $q, ionicMaterialInk, ionicMaterialMotion, $window, $timeout) { + 'ngInject'; var loadingTextCache=null; @@ -215,9 +214,10 @@ angular.module('cesium.utils.services', ['ngResource']) resize: resizeImageFromFile } }; -}]) +}) -.factory('localStorage', ['$window', function($window) { +.factory('localStorage', function($window) { + 'ngInject'; return { put: function(key, value) { $window.localStorage[key] = value; @@ -232,71 +232,5 @@ angular.module('cesium.utils.services', ['ngResource']) return JSON.parse($window.localStorage[key] || '{}'); } }; -}]) - -// See http://plnkr.co/edit/vJQXtsZiX4EJ6Uvw9xtG?p=preview -.factory('$focus', ['$timeout', '$window', function($timeout, $window) { - return function(id) { - // timeout makes sure that it is invoked after any other event has been triggered. - // e.g. click events that need to run before the focus or - // inputs elements that are in a disabled state but are enabled when those events - // are triggered. - $timeout(function() { - var element = $window.document.getElementById(id); - if(element) - element.focus(); - }); - }; -}]) - -.service('ModalService', ['$ionicModal', '$rootScope', '$q', '$controllers', function($ionicModal, $rootScope, $q, $controllers) { - - var show = function(tpl, $scope) { - - var promise; - $scope = $scope || $rootScope.$new(); - - promise = $q(function(resolve, reject){ - $ionicModal.fromTemplateUrl(tpl, { - scope: $scope, - animation: 'slide-in-up' - }).then(function(modal) { - $scope.modal = modal; - $scope.modal.show(); - }); - }); - - $scope.openModal = function() { - $scope.modal.show(); - }; - $scope.closeModal = function(result) { - $scope.modal.hide(); - resolve(result); - }; - $scope.$on('$destroy', function() { - $scope.modal.remove(); - }); - - return promise; - }; - - return { - show: show - }; - -}]) - -.directive('eventFocus', function(focus) { - return function(scope, elem, attr) { - elem.on(attr.eventFocus, function() { - focus(attr.eventFocusId); - }); - - // Removes bound events in the element itself - // when the scope is destroyed - scope.$on('$destroy', function() { - elem.off(attr.eventFocus); - }); - }; }) ; diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index cf08f8c6..67246131 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -1,8 +1,8 @@ -//var Base58, Base64, scrypt_module_factory = null, nacl_factory = null; angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', 'cesium.crypto.services', 'cesium.utils.services']) -.factory('Wallet', ['$q', 'CryptoUtils', 'BMA', '$translate', 'localStorage', function($q, CryptoUtils, BMA, $translate, localStorage) { +.factory('Wallet', function($q, CryptoUtils, BMA, $translate, localStorage) { + 'ngInject'; Wallet = function(id) { @@ -823,5 +823,4 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' service.instance = Wallet; return service; -}]) -; +}); diff --git a/www/js/vendor/qrcode.js b/www/js/vendor/qrcode.js deleted file mode 100644 index 5507c154..00000000 --- a/www/js/vendor/qrcode.js +++ /dev/null @@ -1,614 +0,0 @@ -/** - * @fileoverview - * - Using the 'QRCode for Javascript library' - * - Fixed dataset of 'QRCode for Javascript library' for support full-spec. - * - this library has no dependencies. - * - * @author davidshimjs - * @see http://www.d-project.com/ - * @see http://jeromeetienne.github.com/jquery-qrcode/ - */ -var QRCode; - -(function () { - //--------------------------------------------------------------------- - // QRCode for JavaScript - // - // Copyright (c) 2009 Kazuhiko Arase - // - // URL: http://www.d-project.com/ - // - // Licensed under the MIT license: - // http://www.opensource.org/licenses/mit-license.php - // - // The word "QR Code" is registered trademark of - // DENSO WAVE INCORPORATED - // http://www.denso-wave.com/qrcode/faqpatent-e.html - // - //--------------------------------------------------------------------- - function QR8bitByte(data) { - this.mode = QRMode.MODE_8BIT_BYTE; - this.data = data; - this.parsedData = []; - - // Added to support UTF-8 Characters - for (var i = 0, l = this.data.length; i < l; i++) { - var byteArray = []; - var code = this.data.charCodeAt(i); - - if (code > 0x10000) { - byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18); - byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12); - byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6); - byteArray[3] = 0x80 | (code & 0x3F); - } else if (code > 0x800) { - byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12); - byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6); - byteArray[2] = 0x80 | (code & 0x3F); - } else if (code > 0x80) { - byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6); - byteArray[1] = 0x80 | (code & 0x3F); - } else { - byteArray[0] = code; - } - - this.parsedData.push(byteArray); - } - - this.parsedData = Array.prototype.concat.apply([], this.parsedData); - - if (this.parsedData.length != this.data.length) { - this.parsedData.unshift(191); - this.parsedData.unshift(187); - this.parsedData.unshift(239); - } - } - - QR8bitByte.prototype = { - getLength: function (buffer) { - return this.parsedData.length; - }, - write: function (buffer) { - for (var i = 0, l = this.parsedData.length; i < l; i++) { - buffer.put(this.parsedData[i], 8); - } - } - }; - - function QRCodeModel(typeNumber, errorCorrectLevel) { - this.typeNumber = typeNumber; - this.errorCorrectLevel = errorCorrectLevel; - this.modules = null; - this.moduleCount = 0; - this.dataCache = null; - this.dataList = []; - } - - QRCodeModel.prototype={addData:function(data){var newData=new QR8bitByte(data);this.dataList.push(newData);this.dataCache=null;},isDark:function(row,col){if(row<0||this.moduleCount<=row||col<0||this.moduleCount<=col){throw new Error(row+","+col);} - return this.modules[row][col];},getModuleCount:function(){return this.moduleCount;},make:function(){this.makeImpl(false,this.getBestMaskPattern());},makeImpl:function(test,maskPattern){this.moduleCount=this.typeNumber*4+17;this.modules=new Array(this.moduleCount);for(var row=0;row=7){this.setupTypeNumber(test);} - if(this.dataCache==null){this.dataCache=QRCodeModel.createData(this.typeNumber,this.errorCorrectLevel,this.dataList);} - this.mapData(this.dataCache,maskPattern);},setupPositionProbePattern:function(row,col){for(var r=-1;r<=7;r++){if(row+r<=-1||this.moduleCount<=row+r)continue;for(var c=-1;c<=7;c++){if(col+c<=-1||this.moduleCount<=col+c)continue;if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}},getBestMaskPattern:function(){var minLostPoint=0;var pattern=0;for(var i=0;i<8;i++){this.makeImpl(true,i);var lostPoint=QRUtil.getLostPoint(this);if(i==0||minLostPoint>lostPoint){minLostPoint=lostPoint;pattern=i;}} - return pattern;},createMovieClip:function(target_mc,instance_name,depth){var qr_mc=target_mc.createEmptyMovieClip(instance_name,depth);var cs=1;this.make();for(var row=0;row>i)&1)==1);this.modules[Math.floor(i/3)][i%3+this.moduleCount-8-3]=mod;} - for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[i%3+this.moduleCount-8-3][Math.floor(i/3)]=mod;}},setupTypeInfo:function(test,maskPattern){var data=(this.errorCorrectLevel<<3)|maskPattern;var bits=QRUtil.getBCHTypeInfo(data);for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<6){this.modules[i][8]=mod;}else if(i<8){this.modules[i+1][8]=mod;}else{this.modules[this.moduleCount-15+i][8]=mod;}} - for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<8){this.modules[8][this.moduleCount-i-1]=mod;}else if(i<9){this.modules[8][15-i-1+1]=mod;}else{this.modules[8][15-i-1]=mod;}} - this.modules[this.moduleCount-8][8]=(!test);},mapData:function(data,maskPattern){var inc=-1;var row=this.moduleCount-1;var bitIndex=7;var byteIndex=0;for(var col=this.moduleCount-1;col>0;col-=2){if(col==6)col--;while(true){for(var c=0;c<2;c++){if(this.modules[row][col-c]==null){var dark=false;if(byteIndex>>bitIndex)&1)==1);} - var mask=QRUtil.getMask(maskPattern,row,col-c);if(mask){dark=!dark;} - this.modules[row][col-c]=dark;bitIndex--;if(bitIndex==-1){byteIndex++;bitIndex=7;}}} - row+=inc;if(row<0||this.moduleCount<=row){row-=inc;inc=-inc;break;}}}}};QRCodeModel.PAD0=0xEC;QRCodeModel.PAD1=0x11;QRCodeModel.createData=function(typeNumber,errorCorrectLevel,dataList){var rsBlocks=QRRSBlock.getRSBlocks(typeNumber,errorCorrectLevel);var buffer=new QRBitBuffer();for(var i=0;itotalDataCount*8){throw new Error("code length overflow. (" - +buffer.getLengthInBits() - +">" - +totalDataCount*8 - +")");} - if(buffer.getLengthInBits()+4<=totalDataCount*8){buffer.put(0,4);} - while(buffer.getLengthInBits()%8!=0){buffer.putBit(false);} - while(true){if(buffer.getLengthInBits()>=totalDataCount*8){break;} - buffer.put(QRCodeModel.PAD0,8);if(buffer.getLengthInBits()>=totalDataCount*8){break;} - buffer.put(QRCodeModel.PAD1,8);} - return QRCodeModel.createBytes(buffer,rsBlocks);};QRCodeModel.createBytes=function(buffer,rsBlocks){var offset=0;var maxDcCount=0;var maxEcCount=0;var dcdata=new Array(rsBlocks.length);var ecdata=new Array(rsBlocks.length);for(var r=0;r=0)?modPoly.get(modIndex):0;}} - var totalCodeCount=0;for(var i=0;i=0){d^=(QRUtil.G15<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)));} - return((data<<10)|d)^QRUtil.G15_MASK;},getBCHTypeNumber:function(data){var d=data<<12;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)>=0){d^=(QRUtil.G18<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)));} - return(data<<12)|d;},getBCHDigit:function(data){var digit=0;while(data!=0){digit++;data>>>=1;} - return digit;},getPatternPosition:function(typeNumber){return QRUtil.PATTERN_POSITION_TABLE[typeNumber-1];},getMask:function(maskPattern,i,j){switch(maskPattern){case QRMaskPattern.PATTERN000:return(i+j)%2==0;case QRMaskPattern.PATTERN001:return i%2==0;case QRMaskPattern.PATTERN010:return j%3==0;case QRMaskPattern.PATTERN011:return(i+j)%3==0;case QRMaskPattern.PATTERN100:return(Math.floor(i/2)+Math.floor(j/3))%2==0;case QRMaskPattern.PATTERN101:return(i*j)%2+(i*j)%3==0;case QRMaskPattern.PATTERN110:return((i*j)%2+(i*j)%3)%2==0;case QRMaskPattern.PATTERN111:return((i*j)%3+(i+j)%2)%2==0;default:throw new Error("bad maskPattern:"+maskPattern);}},getErrorCorrectPolynomial:function(errorCorrectLength){var a=new QRPolynomial([1],0);for(var i=0;i5){lostPoint+=(3+sameCount-5);}}} - for(var row=0;row=256){n-=255;} - return QRMath.EXP_TABLE[n];},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)};for(var i=0;i<8;i++){QRMath.EXP_TABLE[i]=1<>>(7-index%8))&1)==1;},put:function(num,length){for(var i=0;i>>(length-i-1))&1)==1);}},getLengthInBits:function(){return this.length;},putBit:function(bit){var bufIndex=Math.floor(this.length/8);if(this.buffer.length<=bufIndex){this.buffer.push(0);} - if(bit){this.buffer[bufIndex]|=(0x80>>>(this.length%8));} - this.length++;}};var QRCodeLimitLength=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]]; - - function _isSupportCanvas() { - return typeof CanvasRenderingContext2D != "undefined"; - } - - // android 2.x doesn't support Data-URI spec - function _getAndroid() { - var android = false; - var sAgent = navigator.userAgent; - - if (/android/i.test(sAgent)) { // android - android = true; - var aMat = sAgent.toString().match(/android ([0-9]\.[0-9])/i); - - if (aMat && aMat[1]) { - android = parseFloat(aMat[1]); - } - } - - return android; - } - - var svgDrawer = (function() { - - var Drawing = function (el, htOption) { - this._el = el; - this._htOption = htOption; - }; - - Drawing.prototype.draw = function (oQRCode) { - var _htOption = this._htOption; - var _el = this._el; - var nCount = oQRCode.getModuleCount(); - var nWidth = Math.floor(_htOption.width / nCount); - var nHeight = Math.floor(_htOption.height / nCount); - - this.clear(); - - function makeSVG(tag, attrs) { - var el = document.createElementNS('http://www.w3.org/2000/svg', tag); - for (var k in attrs) - if (attrs.hasOwnProperty(k)) el.setAttribute(k, attrs[k]); - return el; - } - - var svg = makeSVG("svg" , {'viewBox': '0 0 ' + String(nCount) + " " + String(nCount), 'width': '100%', 'height': '100%', 'fill': _htOption.colorLight}); - svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"); - _el.appendChild(svg); - - svg.appendChild(makeSVG("rect", {"fill": _htOption.colorLight, "width": "100%", "height": "100%"})); - svg.appendChild(makeSVG("rect", {"fill": _htOption.colorDark, "width": "1", "height": "1", "id": "template"})); - - for (var row = 0; row < nCount; row++) { - for (var col = 0; col < nCount; col++) { - if (oQRCode.isDark(row, col)) { - var child = makeSVG("use", {"x": String(col), "y": String(row)}); - child.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#template") - svg.appendChild(child); - } - } - } - }; - Drawing.prototype.clear = function () { - while (this._el.hasChildNodes()) - this._el.removeChild(this._el.lastChild); - }; - return Drawing; - })(); - - var useSVG = document.documentElement.tagName.toLowerCase() === "svg"; - - // Drawing in DOM by using Table tag - var Drawing = useSVG ? svgDrawer : !_isSupportCanvas() ? (function () { - var Drawing = function (el, htOption) { - this._el = el; - this._htOption = htOption; - }; - - /** - * Draw the QRCode - * - * @param {QRCode} oQRCode - */ - Drawing.prototype.draw = function (oQRCode) { - var _htOption = this._htOption; - var _el = this._el; - var nCount = oQRCode.getModuleCount(); - var nWidth = Math.floor(_htOption.width / nCount); - var nHeight = Math.floor(_htOption.height / nCount); - var aHTML = ['']; - - for (var row = 0; row < nCount; row++) { - aHTML.push(''); - - for (var col = 0; col < nCount; col++) { - aHTML.push(''); - } - - aHTML.push(''); - } - - aHTML.push('
'); - _el.innerHTML = aHTML.join(''); - - // Fix the margin values as real size. - var elTable = _el.childNodes[0]; - var nLeftMarginTable = (_htOption.width - elTable.offsetWidth) / 2; - var nTopMarginTable = (_htOption.height - elTable.offsetHeight) / 2; - - if (nLeftMarginTable > 0 && nTopMarginTable > 0) { - elTable.style.margin = nTopMarginTable + "px " + nLeftMarginTable + "px"; - } - }; - - /** - * Clear the QRCode - */ - Drawing.prototype.clear = function () { - this._el.innerHTML = ''; - }; - - return Drawing; - })() : (function () { // Drawing in Canvas - function _onMakeImage() { - this._elImage.src = this._elCanvas.toDataURL("image/png"); - this._elImage.style.display = "block"; - this._elCanvas.style.display = "none"; - } - - // Android 2.1 bug workaround - // http://code.google.com/p/android/issues/detail?id=5141 - if (this._android && this._android <= 2.1) { - var factor = 1 / window.devicePixelRatio; - var drawImage = CanvasRenderingContext2D.prototype.drawImage; - CanvasRenderingContext2D.prototype.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) { - if (("nodeName" in image) && /img/i.test(image.nodeName)) { - for (var i = arguments.length - 1; i >= 1; i--) { - arguments[i] = arguments[i] * factor; - } - } else if (typeof dw == "undefined") { - arguments[1] *= factor; - arguments[2] *= factor; - arguments[3] *= factor; - arguments[4] *= factor; - } - - drawImage.apply(this, arguments); - }; - } - - /** - * Check whether the user's browser supports Data URI or not - * - * @private - * @param {Function} fSuccess Occurs if it supports Data URI - * @param {Function} fFail Occurs if it doesn't support Data URI - */ - function _safeSetDataURI(fSuccess, fFail) { - var self = this; - self._fFail = fFail; - self._fSuccess = fSuccess; - - // Check it just once - if (self._bSupportDataURI === null) { - var el = document.createElement("img"); - var fOnError = function() { - self._bSupportDataURI = false; - - if (self._fFail) { - self._fFail.call(self); - } - }; - var fOnSuccess = function() { - self._bSupportDataURI = true; - - if (self._fSuccess) { - self._fSuccess.call(self); - } - }; - - el.onabort = fOnError; - el.onerror = fOnError; - el.onload = fOnSuccess; - el.src = "data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; // the Image contains 1px data. - return; - } else if (self._bSupportDataURI === true && self._fSuccess) { - self._fSuccess.call(self); - } else if (self._bSupportDataURI === false && self._fFail) { - self._fFail.call(self); - } - }; - - /** - * Drawing QRCode by using canvas - * - * @constructor - * @param {HTMLElement} el - * @param {Object} htOption QRCode Options - */ - var Drawing = function (el, htOption) { - this._bIsPainted = false; - this._android = _getAndroid(); - - this._htOption = htOption; - this._elCanvas = document.createElement("canvas"); - this._elCanvas.width = htOption.width; - this._elCanvas.height = htOption.height; - el.appendChild(this._elCanvas); - this._el = el; - this._oContext = this._elCanvas.getContext("2d"); - this._bIsPainted = false; - this._elImage = document.createElement("img"); - this._elImage.alt = "Scan me!"; - this._elImage.style.display = "none"; - this._el.appendChild(this._elImage); - this._bSupportDataURI = null; - }; - - /** - * Draw the QRCode - * - * @param {QRCode} oQRCode - */ - Drawing.prototype.draw = function (oQRCode) { - var _elImage = this._elImage; - var _oContext = this._oContext; - var _htOption = this._htOption; - - var nCount = oQRCode.getModuleCount(); - var nWidth = _htOption.width / nCount; - var nHeight = _htOption.height / nCount; - var nRoundedWidth = Math.round(nWidth); - var nRoundedHeight = Math.round(nHeight); - - _elImage.style.display = "none"; - this.clear(); - - for (var row = 0; row < nCount; row++) { - for (var col = 0; col < nCount; col++) { - var bIsDark = oQRCode.isDark(row, col); - var nLeft = col * nWidth; - var nTop = row * nHeight; - _oContext.strokeStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight; - _oContext.lineWidth = 1; - _oContext.fillStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight; - _oContext.fillRect(nLeft, nTop, nWidth, nHeight); - - // 안티 앨리어싱 방지 처리 - _oContext.strokeRect( - Math.floor(nLeft) + 0.5, - Math.floor(nTop) + 0.5, - nRoundedWidth, - nRoundedHeight - ); - - _oContext.strokeRect( - Math.ceil(nLeft) - 0.5, - Math.ceil(nTop) - 0.5, - nRoundedWidth, - nRoundedHeight - ); - } - } - - this._bIsPainted = true; - }; - - /** - * Make the image from Canvas if the browser supports Data URI. - */ - Drawing.prototype.makeImage = function () { - if (this._bIsPainted) { - _safeSetDataURI.call(this, _onMakeImage); - } - }; - - /** - * Return whether the QRCode is painted or not - * - * @return {Boolean} - */ - Drawing.prototype.isPainted = function () { - return this._bIsPainted; - }; - - /** - * Clear the QRCode - */ - Drawing.prototype.clear = function () { - this._oContext.clearRect(0, 0, this._elCanvas.width, this._elCanvas.height); - this._bIsPainted = false; - }; - - /** - * @private - * @param {Number} nNumber - */ - Drawing.prototype.round = function (nNumber) { - if (!nNumber) { - return nNumber; - } - - return Math.floor(nNumber * 1000) / 1000; - }; - - return Drawing; - })(); - - /** - * Get the type by string length - * - * @private - * @param {String} sText - * @param {Number} nCorrectLevel - * @return {Number} type - */ - function _getTypeNumber(sText, nCorrectLevel) { - var nType = 1; - var length = _getUTF8Length(sText); - - for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) { - var nLimit = 0; - - switch (nCorrectLevel) { - case QRErrorCorrectLevel.L : - nLimit = QRCodeLimitLength[i][0]; - break; - case QRErrorCorrectLevel.M : - nLimit = QRCodeLimitLength[i][1]; - break; - case QRErrorCorrectLevel.Q : - nLimit = QRCodeLimitLength[i][2]; - break; - case QRErrorCorrectLevel.H : - nLimit = QRCodeLimitLength[i][3]; - break; - } - - if (length <= nLimit) { - break; - } else { - nType++; - } - } - - if (nType > QRCodeLimitLength.length) { - throw new Error("Too long data"); - } - - return nType; - } - - function _getUTF8Length(sText) { - var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a'); - return replacedText.length + (replacedText.length != sText ? 3 : 0); - } - - /** - * @class QRCode - * @constructor - * @example - * new QRCode(document.getElementById("test"), "http://jindo.dev.naver.com/collie"); - * - * @example - * var oQRCode = new QRCode("test", { - * text : "http://naver.com", - * width : 128, - * height : 128 - * }); - * - * oQRCode.clear(); // Clear the QRCode. - * oQRCode.makeCode("http://map.naver.com"); // Re-create the QRCode. - * - * @param {HTMLElement|String} el target element or 'id' attribute of element. - * @param {Object|String} vOption - * @param {String} vOption.text QRCode link data - * @param {Number} [vOption.width=256] - * @param {Number} [vOption.height=256] - * @param {String} [vOption.colorDark="#000000"] - * @param {String} [vOption.colorLight="#ffffff"] - * @param {QRCode.CorrectLevel} [vOption.correctLevel=QRCode.CorrectLevel.H] [L|M|Q|H] - */ - QRCode = function (el, vOption) { - this._htOption = { - width : 256, - height : 256, - typeNumber : 4, - colorDark : "#000000", - colorLight : "#ffffff", - correctLevel : QRErrorCorrectLevel.H - }; - - if (typeof vOption === 'string') { - vOption = { - text : vOption - }; - } - - // Overwrites options - if (vOption) { - for (var i in vOption) { - this._htOption[i] = vOption[i]; - } - } - - if (typeof el == "string") { - el = document.getElementById(el); - } - - if (this._htOption.useSVG) { - Drawing = svgDrawer; - } - - this._android = _getAndroid(); - this._el = el; - this._oQRCode = null; - this._oDrawing = new Drawing(this._el, this._htOption); - - if (this._htOption.text) { - this.makeCode(this._htOption.text); - } - }; - - /** - * Make the QRCode - * - * @param {String} sText link data - */ - QRCode.prototype.makeCode = function (sText) { - this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel); - this._oQRCode.addData(sText); - this._oQRCode.make(); - this._el.title = sText; - this._oDrawing.draw(this._oQRCode); - this.makeImage(); - }; - - /** - * Make the Image from Canvas element - * - It occurs automatically - * - Android below 3 doesn't support Data-URI spec. - * - * @private - */ - QRCode.prototype.makeImage = function () { - if (typeof this._oDrawing.makeImage == "function" && (!this._android || this._android >= 3)) { - this._oDrawing.makeImage(); - } - }; - - /** - * Clear the QRCode - */ - QRCode.prototype.clear = function () { - this._oDrawing.clear(); - }; - - /** - * @name QRCode.CorrectLevel - */ - QRCode.CorrectLevel = QRErrorCorrectLevel; -})(); diff --git a/www/templates/currency/view_currency_lg.html b/www/templates/currency/view_currency_lg.html index 2cc9587a..a6e8f35e 100644 --- a/www/templates/currency/view_currency_lg.html +++ b/www/templates/currency/view_currency_lg.html @@ -5,19 +5,16 @@ -
-
-
+
-
-
- -
-
- -
-
-
+
+
+ +
+
+ +
+
diff --git a/www/templates/home/home.html b/www/templates/home/home.html index c8d94771..23a97f2b 100644 --- a/www/templates/home/home.html +++ b/www/templates/home/home.html @@ -1,40 +1,38 @@ - - - - -

HOME.MESSAGE_SHORT

+ + +

HOME.MESSAGE_SHORT

-
- -
- - - - +
+ +
+ + + + + - - + + @@ -69,8 +67,7 @@

HOME.MESSAGE_SHORT

- +
@@ -78,11 +75,9 @@

HOME.MESSAGE_SHORT

style="position: absolute; top: 0px; right: 0; margin: 0; padding: 0; border: 0;" target="_blank" href="https://github.com/duniter/cesium"> - Fork me on GitHub + Fork me on GitHub - - diff --git a/www/templates/market/edit_record.html b/www/templates/market/edit_record.html index c1c94bca..f2dfba46 100644 --- a/www/templates/market/edit_record.html +++ b/www/templates/market/edit_record.html @@ -32,14 +32,14 @@

{{picture.title}}

-
+
MARKET.EDIT.BTN_ADD_PICTURES
-
+
MARKET.EDIT.BTN_ADD_PICTURES - - + + @@ -14,7 +15,11 @@ - +

MENU.TITLE @@ -60,9 +65,6 @@

MENU.ACCOUNT - MENU.SETTINGS @@ -83,6 +85,7 @@

+ COMMON.BTN_LOGOUT - diff --git a/www/templates/registry/record_form.html b/www/templates/registry/record_form.html index da276e37..5fcdb48d 100644 --- a/www/templates/registry/record_form.html +++ b/www/templates/registry/record_form.html @@ -24,14 +24,14 @@

{{picture.title}}

-
+
REGISTRY.EDIT.BTN_ADD_PICTURES
-
+
REGISTRY.EDIT.BTN_ADD_PICTURES + + +
+ + +
+ + + + + {{'ACCOUNT.CERTIFICATION_COUNT'|translate}} + {{walletData.requirements.certificationCount}} + + + + + + {{'ACCOUNT.EVENTS' | translate}} + + + +

+ + {{'ACCOUNT.WAITING_MEMBERSHIP' | translate}} +

+
+ +

+ + {{'ACCOUNT.WAITING_CERTIFICATIONS' | translate:walletData.requirements}} +

+
+ +

+ + {{'ACCOUNT.WILL_MISSING_CERTIFICATIONS' | translate:walletData.requirements}} +

+
+ + + + +

{{walletData.pubkey}}

+
+ + + + ACCOUNT.LAST_TX +
+ ({{unit | abbreviate}}) + ({{'COMMON.UD' | translate}}{{unit | abbreviate}})
- -
- - - -
- - -
- - - - - {{'ACCOUNT.CERTIFICATION_COUNT'|translate}} - {{walletData.requirements.certificationCount}} - - - - - - {{'ACCOUNT.EVENTS' | translate}} - - - -

- - {{'ACCOUNT.WAITING_MEMBERSHIP' | translate}} -

-
- -

- - {{'ACCOUNT.WAITING_CERTIFICATIONS' | translate:walletData.requirements}} -

-
- -

- - {{'ACCOUNT.WILL_MISSING_CERTIFICATIONS' | translate:walletData.requirements}} -

-
- - - - -

{{walletData.pubkey}}

-
- - - - ACCOUNT.LAST_TX -
- ({{unit | abbreviate}}) - ({{'COMMON.UD' | translate}}{{unit | abbreviate}}) -
-
- - -

ACCOUNT.NO_TX

-
- - -

- - - {{::tx.uid}} - - - - {{::tx.pubkey | formatPubkey}} - - - - {{'COMMON.UNIVERSAL_DIVIDEND' | translate}} - - -

-

- - {{::tx.comment}}
-

-

- {{::tx.time | formatFromNow}} - -

-
- {{tx.amount | formatInteger}} - {{tx.amount/walletData.currentUD | formatDecimal}} -
-
-
- - -
-
-
- - - - + + + +

ACCOUNT.NO_TX

+
+ + +

+ + + + {{::tx.uid}} + + + + {{::tx.pubkey | formatPubkey}} + + + + {{'COMMON.UNIVERSAL_DIVIDEND' | translate}} + + +

+

+ + {{::tx.comment}}
+

+

+ {{::tx.time | formatFromNow}} + +

+
+ {{tx.amount | formatInteger}} + {{tx.amount/walletData.currentUD | formatDecimal}} +
+
+
+ + +
+ + + diff --git a/www/templates/wot/lookup.html b/www/templates/wot/lookup.html index 8c3c89ae..80910a03 100644 --- a/www/templates/wot/lookup.html +++ b/www/templates/wot/lookup.html @@ -1,7 +1,6 @@ - diff --git a/www/templates/wot/modal_lookup.html b/www/templates/wot/modal_lookup.html index a6e6397f..64446cda 100644 --- a/www/templates/wot/modal_lookup.html +++ b/www/templates/wot/modal_lookup.html @@ -3,7 +3,7 @@

WOT.MODAL.TITLE

- diff --git a/www/templates/wot/view_identity.html b/www/templates/wot/view_identity.html index 9a5e6728..dfe429b1 100644 --- a/www/templates/wot/view_identity.html +++ b/www/templates/wot/view_identity.html @@ -2,7 +2,7 @@ - +
-
+ -