From 3acc01535cc1ec66680905a12e3a7e78ad21125d Mon Sep 17 00:00:00 2001
From: blavenie <benoit.lavenier@e-is.pro>
Date: Fri, 7 Aug 2020 21:01:29 +0200
Subject: [PATCH] [enh] Manage #/app/home?uri= to parse g1:// link

---
 www/index.html                         |   1 +
 www/js/controllers.js                  |   1 +
 www/js/controllers/app-controllers.js  | 169 ------------------
 www/js/controllers/home-controllers.js | 226 +++++++++++++++++++++++++
 www/js/platform.js                     |  12 ++
 www/js/services/http-services.js       |   8 +-
 6 files changed, 245 insertions(+), 172 deletions(-)
 create mode 100644 www/js/controllers/home-controllers.js

diff --git a/www/index.html b/www/index.html
index 7e6cf4490..4e67c36fb 100644
--- a/www/index.html
+++ b/www/index.html
@@ -162,6 +162,7 @@
 
     <!-- controllers -->
     <script src="dist/dist_js/app/controllers/app-controllers.js"></script>
+    <script src="dist/dist_js/app/controllers/home-controllers.js"></script>
     <script src="dist/dist_js/app/controllers/join-controllers.js"></script>
     <script src="dist/dist_js/app/controllers/login-controllers.js"></script>
     <script src="dist/dist_js/app/controllers/help-controllers.js"></script>
diff --git a/www/js/controllers.js b/www/js/controllers.js
index 5ed49c515..b36e1e613 100644
--- a/www/js/controllers.js
+++ b/www/js/controllers.js
@@ -1,6 +1,7 @@
 
 angular.module('cesium.controllers', [
     'cesium.app.controllers',
+    'cesium.home.controllers',
     'cesium.join.controllers',
     'cesium.login.controllers',
     'cesium.help.controllers',
diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js
index 7a12d4e33..8fa7643ef 100644
--- a/www/js/controllers/app-controllers.js
+++ b/www/js/controllers/app-controllers.js
@@ -15,16 +15,6 @@ angular.module('cesium.app.controllers', ['cesium.platform', 'cesium.services'])
         }
       })
 
-      .state('app.home', {
-        url: "/home?error",
-        views: {
-          'menuContent': {
-            templateUrl: "templates/home/home.html",
-            controller: 'HomeCtrl'
-          }
-        }
-      })
-
       .state('app.lock', {
         cache: false,
         url: "/lock",
@@ -37,15 +27,10 @@ angular.module('cesium.app.controllers', ['cesium.platform', 'cesium.services'])
       })
     ;
 
-    // if none of the above states are matched, use this as the fallback
-    $urlRouterProvider.otherwise('/app/home');
-
   })
 
   .controller('AppCtrl', AppController)
 
-  .controller('HomeCtrl', HomeController)
-
   .controller('PluginExtensionPointCtrl', PluginExtensionPointController)
 
 ;
@@ -525,157 +510,3 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $
   $scope.askFullscreen();
   // endRemoveIf(device)
 }
-
-
-function HomeController($scope, $state, $timeout, $ionicHistory, $translate, $http, UIUtils,
-                        csConfig, csCache, csPlatform, csCurrency, csSettings) {
-  'ngInject';
-
-  $scope.loading = true;
-  $scope.locales = angular.copy(csSettings.locales);
-  $scope.smallscreen = UIUtils.screen.isSmall();
-  $scope.showInstallHelp = false;
-
-  $scope.enter = function(e, state) {
-    if (ionic.Platform.isIOS()) {
-      if(window.StatusBar) {
-        // needed to fix Xcode 9 / iOS 11 issue with blank space at bottom of webview
-        // https://github.com/meteor/meteor/issues/9041
-        StatusBar.overlaysWebView(false);
-        StatusBar.overlaysWebView(true);
-      }
-    }
-
-    if (state && state.stateParams && state.stateParams.error) { // Error query parameter
-      $scope.error = state.stateParams.error;
-      $scope.node = csCurrency.data.node;
-      $scope.loading = false;
-      $ionicHistory.nextViewOptions({
-        disableAnimate: true,
-        disableBack: true,
-        historyRoot: true
-      });
-      $state.go('app.home', {error: undefined}, {
-        reload: false,
-        inherit: true,
-        notify: false});
-    }
-    else {
-      // Wait platform to be ready
-      csPlatform.ready()
-        .then(function() {
-          $scope.loading = false;
-          $scope.loadFeeds();
-        })
-        .catch(function(err) {
-          $scope.node =  csCurrency.data.node;
-          $scope.loading = false;
-          $scope.error = err;
-        });
-    }
-  };
-  $scope.$on('$ionicView.enter', $scope.enter);
-
-  $scope.reload = function() {
-    $scope.loading = true;
-    delete $scope.error;
-
-    $timeout($scope.enter, 200);
-  };
-
-  $scope.loadFeeds = function() {
-    var feedUrl = csSettings.getFeedUrl();
-    if (!feedUrl || typeof feedUrl !== 'string') return; // Skip
-
-    var maxContentLength = (csConfig.feed && csConfig.feed.maxContentLength) || 650;
-
-    var now = Date.now();
-    console.debug("[home] Loading feeds from {0}...".format(feedUrl));
-
-    $http.get(feedUrl, {responseType: 'json', cache: csCache.get(null, csCache.constants.LONG)})
-      .success(function(feed) {
-        console.debug('[home] Feeds loaded in {0}ms'.format(Date.now()-now));
-        if (!feed || !feed.items || !feed.items.length) return; // skip if empty
-
-        feed.items = feed.items.reduce(function(res, item) {
-          if (!item || (!item.title && !item.content_text && !item.content_html)) return res; // Skip
-
-          // Convert UTC time
-          if (item.date_published) {
-            item.time = moment.utc(item.date_published).unix();
-          }
-          // Convert content to HTML
-          if (item.content_html) {
-            item.content = item.content_html;
-          }
-          else {
-            item.content = (item.content_text||'').replace(/\n/g, '<br/>');
-          }
-
-          // Trunc content, if need
-          if (maxContentLength !== -1 && item.content && item.content.length > maxContentLength) {
-            var endIndex = Math.max(item.content.lastIndexOf(" ", maxContentLength), item.content.lastIndexOf("<", maxContentLength));
-            item.content = item.content.substr(0, endIndex) + ' (...)';
-            item.truncated = true;
-          }
-
-          // If author is missing, copy the main author
-          item.author = item.author || feed.author;
-
-          return res.concat(item);
-        }, []);
-
-        $scope.feed = feed;
-      })
-      .error(function(data, status) {
-        console.error('[home] Failed to load feeds.');
-        $scope.feed = null;
-      });
-  };
-
-  /**
-   * Catch click for quick fix
-   * @param event
-   */
-  $scope.doQuickFix = function(action) {
-    if (action === 'settings') {
-      $ionicHistory.nextViewOptions({
-        historyRoot: true
-      });
-      $state.go('app.settings');
-    }
-  };
-
-  $scope.changeLanguage = function(langKey) {
-    $translate.use(langKey);
-    $scope.hideLocalesPopover();
-    csSettings.data.locale = _.findWhere($scope.locales, {id: langKey});
-    csSettings.store();
-    $scope.loadFeeds();
-  };
-
-  /* -- show/hide locales popup -- */
-
-  $scope.showLocalesPopover = function(event) {
-    UIUtils.popover.show(event, {
-      templateUrl: 'templates/common/popover_locales.html',
-      scope: $scope,
-      autoremove: true,
-      afterShow: function(popover) {
-        $scope.localesPopover = popover;
-      }
-    });
-  };
-
-  $scope.hideLocalesPopover = function() {
-    if ($scope.localesPopover) {
-      $scope.localesPopover.hide();
-      $scope.localesPopover = null;
-    }
-  };
-
-  // For DEV ONLY
-  /*$timeout(function() {
-   $scope.loginAndGo();
-   }, 500);*/
-}
diff --git a/www/js/controllers/home-controllers.js b/www/js/controllers/home-controllers.js
new file mode 100644
index 000000000..9898e8766
--- /dev/null
+++ b/www/js/controllers/home-controllers.js
@@ -0,0 +1,226 @@
+angular.module('cesium.home.controllers', ['cesium.platform', 'cesium.services'])
+
+  .config(function($stateProvider, $urlRouterProvider) {
+    'ngInject';
+
+    $stateProvider
+
+
+      .state('app.home', {
+        url: "/home?error&uri",
+        views: {
+          'menuContent': {
+            templateUrl: "templates/home/home.html",
+            controller: 'HomeCtrl'
+          }
+        }
+      })
+
+    ;
+
+    // if none of the above states are matched, use this as the fallback
+    $urlRouterProvider.otherwise('/app/home');
+
+  })
+
+  .controller('HomeCtrl', HomeController)
+;
+
+function HomeController($scope, $state, $timeout, $ionicHistory, $translate, $http, UIUtils,
+                        csConfig, csCache, csPlatform, csCurrency, csSettings, csHttp) {
+  'ngInject';
+
+  $scope.loading = true;
+  $scope.locales = angular.copy(csSettings.locales);
+  $scope.smallscreen = UIUtils.screen.isSmall();
+  $scope.showInstallHelp = false;
+
+  $scope.enter = function(e, state) {
+    if (ionic.Platform.isIOS()) {
+      if(window.StatusBar) {
+        // needed to fix Xcode 9 / iOS 11 issue with blank space at bottom of webview
+        // https://github.com/meteor/meteor/issues/9041
+        StatusBar.overlaysWebView(false);
+        StatusBar.overlaysWebView(true);
+      }
+    }
+
+    if (state && state.stateParams && state.stateParams.uri) {
+      return $scope.redirectFromUri(state.stateParams.uri);
+    }
+    else if (state && state.stateParams && state.stateParams.error) { // Error query parameter
+      $scope.error = state.stateParams.error;
+      $scope.node = csCurrency.data.node;
+      $scope.loading = false;
+      $ionicHistory.nextViewOptions({
+        disableAnimate: true,
+        disableBack: true,
+        historyRoot: true
+      });
+      $state.go('app.home', {error: undefined}, {
+        reload: false,
+        inherit: true,
+        notify: false});
+    }
+    else {
+      // Wait platform to be ready
+      csPlatform.ready()
+        .then(function() {
+          $scope.loading = false;
+          $scope.loadFeeds();
+        })
+        .catch(function(err) {
+          $scope.node =  csCurrency.data.node;
+          $scope.loading = false;
+          $scope.error = err;
+        });
+    }
+  };
+  $scope.$on('$ionicView.enter', $scope.enter);
+
+  $scope.reload = function() {
+    $scope.loading = true;
+    delete $scope.error;
+
+    $timeout($scope.enter, 200);
+  };
+
+  $scope.loadFeeds = function() {
+    var feedUrl = csSettings.getFeedUrl();
+    if (!feedUrl || typeof feedUrl !== 'string') return; // Skip
+
+    var maxContentLength = (csConfig.feed && csConfig.feed.maxContentLength) || 650;
+
+    var now = Date.now();
+    console.debug("[home] Loading feeds from {0}...".format(feedUrl));
+
+    $http.get(feedUrl, {responseType: 'json', cache: csCache.get(null, csCache.constants.LONG)})
+      .success(function(feed) {
+        console.debug('[home] Feeds loaded in {0}ms'.format(Date.now()-now));
+        if (!feed || !feed.items || !feed.items.length) return; // skip if empty
+
+        feed.items = feed.items.reduce(function(res, item) {
+          if (!item || (!item.title && !item.content_text && !item.content_html)) return res; // Skip
+
+          // Convert UTC time
+          if (item.date_published) {
+            item.time = moment.utc(item.date_published).unix();
+          }
+          // Convert content to HTML
+          if (item.content_html) {
+            item.content = item.content_html;
+          }
+          else {
+            item.content = (item.content_text||'').replace(/\n/g, '<br/>');
+          }
+
+          // Trunc content, if need
+          if (maxContentLength !== -1 && item.content && item.content.length > maxContentLength) {
+            var endIndex = Math.max(item.content.lastIndexOf(" ", maxContentLength), item.content.lastIndexOf("<", maxContentLength));
+            item.content = item.content.substr(0, endIndex) + ' (...)';
+            item.truncated = true;
+          }
+
+          // If author is missing, copy the main author
+          item.author = item.author || feed.author;
+
+          return res.concat(item);
+        }, []);
+
+        $scope.feed = feed;
+      })
+      .error(function(data, status) {
+        console.error('[home] Failed to load feeds.');
+        $scope.feed = null;
+      });
+  };
+
+  /**
+   * Catch click for quick fix
+   * @param action
+   */
+  $scope.doQuickFix = function(action) {
+    if (action === 'settings') {
+      $ionicHistory.nextViewOptions({
+        historyRoot: true
+      });
+      $state.go('app.settings');
+    }
+  };
+
+  $scope.changeLanguage = function(langKey) {
+    $translate.use(langKey);
+    $scope.hideLocalesPopover();
+    csSettings.data.locale = _.findWhere($scope.locales, {id: langKey});
+    csSettings.store();
+    $scope.loadFeeds();
+  };
+
+  /* -- show/hide locales popup -- */
+
+  $scope.showLocalesPopover = function(event) {
+    UIUtils.popover.show(event, {
+      templateUrl: 'templates/common/popover_locales.html',
+      scope: $scope,
+      autoremove: true,
+      afterShow: function(popover) {
+        $scope.localesPopover = popover;
+      }
+    });
+  };
+
+  $scope.hideLocalesPopover = function() {
+    if ($scope.localesPopover) {
+      $scope.localesPopover.hide();
+      $scope.localesPopover = null;
+    }
+  };
+
+  /**
+   * Parse an URI (see g1lien)
+   * @param uri
+   * @returns {*}
+   */
+  $scope.redirectFromUri = function(uri) {
+    console.debug("[home] Detecting external uri: ", uri);
+    var parts = csHttp.uri.parse(uri);
+
+    if (parts.protocol === 'g1:') {
+      console.debug("[home] Applying g1 uri...", parts);
+
+      // Transfer
+      if (parts.hostname && parts.search.indexOf('amount=') !== -1) {
+        return $state.go('app.new_transfer_pubkey', {
+          pubkey: parts.hostname
+        });
+      }
+
+      // Pubkey
+      else if (parts.hostname && BMA.regexp.PUBKEY.test(parts.hostname)) {
+        var pubkey = parts.hostname;
+        return $state.go('app.wot_identity', {
+          pubkey: pubkey
+        });
+      }
+
+      // Search by uid
+      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
+        });
+      }
+    }
+    else {
+      console.error("[home] Unknown protocol, in URI: " + uri);
+    }
+
+    // Redirect to home
+    return $state.go('app.home');
+  }
+
+  // For DEV ONLY
+  /*$timeout(function() {
+   $scope.loginAndGo();
+   }, 500);*/
+}
diff --git a/www/js/platform.js b/www/js/platform.js
index e243bc417..e08150988 100644
--- a/www/js/platform.js
+++ b/www/js/platform.js
@@ -229,6 +229,16 @@ 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 addListeners() {
       listeners = [
         // Listen if node changed
@@ -261,6 +271,8 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']
       // Avoid change state
       disableChangeState();
 
+      registerProtocol();
+
       // 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 8ce34f453..ad5f86cf5 100644
--- a/www/js/services/http-services.js
+++ b/www/js/services/http-services.js
@@ -318,9 +318,11 @@ angular.module('cesium.http.services', ['cesium.cache.services'])
   // See doc : https://gist.github.com/jlong/2428561
   function parseUri(uri) {
     var protocol;
-    if (uri.startsWith('duniter://')) {
-      protocol = 'duniter';
-      uri = uri.replace('duniter://', 'http://');
+
+    // G1 URI (see G1lien)
+    if (uri.startsWith('web+june://') || uri.startsWith('g1://')) {
+      protocol = 'g1:';
+      uri = uri.replace(/^(g1|web+june):\/\//, 'http:');
     }
 
     var parser = document.createElement('a');
-- 
GitLab