diff --git a/src/popup/app/app.js b/src/popup/app/app.js
index 4e23deda23..230be7915c 100644
--- a/src/popup/app/app.js
+++ b/src/popup/app/app.js
@@ -24,6 +24,7 @@ import ComponentsModule from './components/components.module';
import ToolsModule from './tools/tools.module';
import ServicesModule from './services/services.module';
import LockModule from './lock/lock.module';
+import CurrentModule from './current/current.module';
// Model imports
import { Attachment } from '../../models/domain/attachment';
@@ -83,7 +84,7 @@ angular
'bit.global',
'bit.accounts',
- 'bit.current',
+ CurrentModule,
'bit.vault',
'bit.settings',
ToolsModule,
@@ -107,8 +108,6 @@ require('./accounts/accountsLoginTwoFactorController.js');
require('./accounts/accountsTwoFactorMethodsController.js');
require('./accounts/accountsHintController.js');
require('./accounts/accountsRegisterController.js');
-require('./current/currentModule.js');
-require('./current/currentController.js');
require('./vault/vaultModule.js');
require('./vault/vaultController.js');
require('./vault/vaultViewFolderController.js');
diff --git a/src/popup/app/components/cipher-items.component.ts b/src/popup/app/components/cipher-items.component.ts
index 35cd979030..fcace63579 100644
--- a/src/popup/app/components/cipher-items.component.ts
+++ b/src/popup/app/components/cipher-items.component.ts
@@ -9,11 +9,11 @@ class CipherItemsController implements ng.IController {
}
view(cipher: any) {
- return this.onView()(cipher);
+ return this.onView({cipher});
}
select(cipher: any) {
- return this.onSelected()(cipher);
+ return this.onSelected({cipher});
}
}
diff --git a/src/popup/app/config.js b/src/popup/app/config.js
index d679a3b1e2..b2aa814780 100644
--- a/src/popup/app/config.js
+++ b/src/popup/app/config.js
@@ -110,8 +110,7 @@ angular
})
.state('tabs.current', {
url: '/current',
- template: require('./current/views/current.html'),
- controller: 'currentController'
+ component: 'current'
})
.state('tabs.vault', {
url: '/vault',
diff --git a/src/popup/app/current/current.component.html b/src/popup/app/current/current.component.html
new file mode 100644
index 0000000000..de652cc253
--- /dev/null
+++ b/src/popup/app/current/current.component.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
{{$ctrl.i18n.autoFillInfo}}
+
+
+
+
+
+
+
+
{{$ctrl.i18n.noItemsInList}}
+
+
+
+
+
+
+
+
+
diff --git a/src/popup/app/current/current.component.ts b/src/popup/app/current/current.component.ts
new file mode 100644
index 0000000000..ec0756811f
--- /dev/null
+++ b/src/popup/app/current/current.component.ts
@@ -0,0 +1,161 @@
+import { UtilsService } from '../../../services/abstractions/utils.service';
+import * as template from './current.component.html';
+
+class CurrentController {
+ i18n: any;
+ pageDetails: any = [];
+ loaded: boolean = false;
+ otherCiphers: any = [];
+ loginCiphers: any = [];
+ url: any;
+ domain: any;
+ canAutofill: boolean = false;
+ searchText: string = null;
+ inSidebar: boolean = false;
+ disableSearch: boolean = false;
+
+ constructor($scope: any, private cipherService: any, private utilsService: UtilsService, private toastr: any,
+ private $window: any, private $state: any, private $timeout: any, private autofillService: any,
+ private $analytics: any, private i18nService: any, private constantsService: any,
+ private $filter: any) {
+
+ this.i18n = i18nService;
+ this.inSidebar = utilsService.inSidebar($window);
+ this.disableSearch = utilsService.isEdge();
+
+ document.getElementById('search').focus();
+
+ $scope.$on('syncCompleted', (event: any, successfully: boolean) => {
+ if (this.loaded) {
+ $timeout(this.loadVault.bind(this), 500);
+ }
+ });
+
+ $scope.$on('collectPageDetailsResponse', (event: any, details: any) => {
+ this.pageDetails.push(details);
+ });
+ }
+
+ $onInit() {
+ this.loadVault();
+ }
+
+ refresh() {
+ this.loadVault();
+ }
+
+ addCipher() {
+ this.$state.go('addCipher', {
+ animation: 'in-slide-up',
+ name: this.domain,
+ uri: this.url,
+ from: 'current',
+ });
+ }
+
+ viewCipher(cipher: any) {
+ this.$state.go('viewCipher', {
+ cipherId: cipher.id,
+ animation: 'in-slide-up',
+ from: 'current',
+ });
+ }
+
+ fillCipher(cipher: any) {
+ if (!this.canAutofill) {
+ this.$analytics.eventTrack('Autofilled Error');
+ this.toastr.error(this.i18nService.autofillError);
+ }
+
+ this.autofillService
+ .doAutoFill({
+ cipher,
+ pageDetails: this.pageDetails,
+ fromBackground: false,
+ })
+ .then((totpCode: string) => {
+ this.$analytics.eventTrack('Autofilled');
+ if (totpCode && this.utilsService.isFirefox()) {
+ this.utilsService.copyToClipboard(totpCode, document);
+ }
+ if (this.utilsService.inPopup(this.$window)) {
+ this.$window.close();
+ }
+ })
+ .catch(() => {
+ this.$analytics.eventTrack('Autofilled Error');
+ this.toastr.error(this.i18nService.autofillError);
+ });
+ }
+
+ searchVault() {
+ this.$state.go('tabs.vault', {
+ searchText: this.searchText,
+ });
+ }
+
+ private loadVault() {
+ chrome.tabs.query({ active: true, currentWindow: true }, (tabs: any) => {
+ if (tabs.length > 0) {
+ this.url = tabs[0].url;
+ } else {
+ this.$timeout(() => {
+ this.loaded = true;
+ });
+ return;
+ }
+
+ this.domain = this.utilsService.getDomain(this.url);
+
+ chrome.tabs.sendMessage(tabs[0].id, {
+ command: 'collectPageDetails',
+ tab: tabs[0],
+ sender: 'currentController',
+ }, () => {
+ this.canAutofill = true;
+ });
+
+ const otherTypes = [
+ this.constantsService.cipherType.card,
+ this.constantsService.cipherType.identity,
+ ];
+
+ this.cipherService.getAllDecryptedForDomain(this.domain, otherTypes).then((ciphers: any) => {
+ const loginCiphers: any = [];
+ const otherCiphers: any = [];
+
+ for (const cipher of ciphers) {
+ if (cipher.type === this.constantsService.cipherType.login) {
+ loginCiphers.push(cipher);
+ } else {
+ otherCiphers.push(cipher);
+ }
+ }
+
+ this.$timeout(() => {
+ this.loginCiphers = this.$filter('orderBy')(
+ loginCiphers,
+ [this.sortUriMatch, this.sortLastUsed, 'name', 'subTitle'],
+ );
+ this.otherCiphers = this.$filter('orderBy')(otherCiphers, [this.sortLastUsed, 'name', 'subTitle']);
+ this.loaded = true;
+ });
+ });
+ });
+ }
+
+ private sortUriMatch(cipher: any) {
+ // exact matches should sort earlier.
+ return this.url && this.url.startsWith(cipher.uri) ? 0 : 1;
+ }
+
+ private sortLastUsed(cipher: any) {
+ return cipher.localData && cipher.localData.lastUsedDate ? -1 * cipher.localData.lastUsedDate : 0;
+ }
+}
+
+export const CurrentComponent = {
+ bindings: {},
+ controller: CurrentController,
+ template,
+};
diff --git a/src/popup/app/current/current.module.ts b/src/popup/app/current/current.module.ts
new file mode 100644
index 0000000000..a3bbd942a4
--- /dev/null
+++ b/src/popup/app/current/current.module.ts
@@ -0,0 +1,9 @@
+import * as angular from 'angular';
+import { CurrentComponent } from './current.component';
+
+export default angular
+ .module('bit.current', ['toastr', 'ngclipboard'])
+
+ .component('current', CurrentComponent)
+
+ .name;
diff --git a/src/popup/app/current/currentController.js b/src/popup/app/current/currentController.js
deleted file mode 100644
index 1d448b4053..0000000000
--- a/src/popup/app/current/currentController.js
+++ /dev/null
@@ -1,139 +0,0 @@
-angular
- .module('bit.current')
-
- .controller('currentController', function ($scope, cipherService, utilsService, toastr, $window, $state, $timeout,
- autofillService, $analytics, i18nService, totpService, tokenService, constantsService, $filter) {
- $scope.i18n = i18nService;
-
- var pageDetails = [],
- url = null,
- domain = null,
- canAutofill = false;
-
- $scope.loginCiphers = [];
- $scope.otherCiphers = [];
- $scope.loaded = false;
- $scope.searchText = null;
- $scope.inSidebar = utilsService.inSidebar($window);
- $scope.disableSearch = utilsService.isEdge();
- document.getElementById('search').focus();
-
- $scope.$on('$viewContentLoaded', function () {
- $timeout(loadVault, 100);
- });
-
- function loadVault() {
- chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
- if (tabs.length > 0) {
- url = tabs[0].url;
- }
- else {
- $timeout(function () {
- $scope.loaded = true;
- });
- return;
- }
-
- domain = utilsService.getDomain(url);
-
- chrome.tabs.sendMessage(tabs[0].id, {
- command: 'collectPageDetails',
- tab: tabs[0],
- sender: 'currentController'
- }, function () {
- canAutofill = true;
- });
-
- var otherTypes = [constantsService.cipherType.card, constantsService.cipherType.identity];
- cipherService.getAllDecryptedForDomain(domain, otherTypes).then(function (ciphers) {
- var loginCiphers = [],
- otherCiphers = [];
-
- for (var i = 0; i < ciphers.length; i++) {
- if (ciphers[i].type === constantsService.cipherType.login) {
- loginCiphers.push(ciphers[i]);
- }
- else {
- otherCiphers.push(ciphers[i]);
- }
- }
-
- $timeout(function () {
- $scope.loginCiphers = $filter('orderBy')(loginCiphers, [sortUriMatch, sortLastUsed, 'name', 'subTitle']);
- $scope.otherCiphers = $filter('orderBy')(otherCiphers, [sortLastUsed, 'name', 'subTitle']);
- $scope.loaded = true;
- });
- });
- });
- }
-
- $scope.addCipher = function () {
- $state.go('addCipher', {
- animation: 'in-slide-up',
- name: domain,
- uri: url,
- from: 'current'
- });
- };
-
- $scope.fillCipher = function (cipher) {
- if (!canAutofill) {
- $analytics.eventTrack('Autofilled Error');
- toastr.error(i18nService.autofillError);
- }
-
- autofillService.doAutoFill({
- cipher: cipher,
- pageDetails: pageDetails,
- fromBackground: false
- }).then(function (totpCode) {
- $analytics.eventTrack('Autofilled');
- if (totpCode && utilsService.isFirefox()) {
- utilsService.copyToClipboard(totpCode, document);
- }
- if (utilsService.inPopup($window)) {
- $window.close();
- }
- }, function () {
- $analytics.eventTrack('Autofilled Error');
- toastr.error(i18nService.autofillError);
- });
- };
-
- $scope.viewCipher = function (cipher) {
- $state.go('viewCipher', {
- cipherId: cipher.id,
- animation: 'in-slide-up',
- from: 'current'
- });
- };
-
- function sortUriMatch(cipher) {
- // exact matches should sort earlier.
- return url && url.startsWith(cipher.uri) ? 0 : 1;
- }
-
- function sortLastUsed(cipher) {
- return cipher.localData && cipher.localData.lastUsedDate ? -1 * cipher.localData.lastUsedDate : 0;
- }
-
- $scope.searchVault = function () {
- $state.go('tabs.vault', {
- searchText: $scope.searchText
- });
- };
-
- $scope.refresh = function () {
- loadVault();
- };
-
- $scope.$on('syncCompleted', function (event, successfully) {
- if ($scope.loaded) {
- setTimeout(loadVault, 500);
- }
- });
-
- $scope.$on('collectPageDetailsResponse', function (event, details) {
- pageDetails.push(details);
- });
- });
diff --git a/src/popup/app/current/currentModule.js b/src/popup/app/current/currentModule.js
deleted file mode 100644
index 3334a742ac..0000000000
--- a/src/popup/app/current/currentModule.js
+++ /dev/null
@@ -1,2 +0,0 @@
-angular
- .module('bit.current', ['toastr', 'ngclipboard']);
diff --git a/src/popup/app/current/views/current.html b/src/popup/app/current/views/current.html
deleted file mode 100644
index 8c39fcde23..0000000000
--- a/src/popup/app/current/views/current.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
-
-
{{i18n.autoFillInfo}}
-
-
-
-
-
-
-
-
-
{{i18n.noItemsInList}}
-
-
-
-
-
-
-
-