From b0ec2c13d8eef4ab722d6993907151b50bbf0ba6 Mon Sep 17 00:00:00 2001 From: Lewis Liu Date: Sun, 30 Aug 2015 03:11:46 -0700 Subject: [PATCH 1/9] Added edit profile modal --- app/components/components.js | 2 ++ .../edit-profile-modal-directive.js | 16 +++++++++ .../edit-profile-modal.html | 34 +++++++++++++++++++ .../edit-profile-modal/edit-profile-modal.js | 6 ++++ 4 files changed, 58 insertions(+) create mode 100644 app/components/edit-profile-modal/edit-profile-modal-directive.js create mode 100644 app/components/edit-profile-modal/edit-profile-modal.html create mode 100644 app/components/edit-profile-modal/edit-profile-modal.js diff --git a/app/components/components.js b/app/components/components.js index 5bec6192..5a8f3af5 100644 --- a/app/components/components.js +++ b/app/components/components.js @@ -3,6 +3,7 @@ import angular from 'angular'; import autoFocus from './auto-focus/auto-focus'; import autoSelect from './auto-select/auto-select'; import equalTo from './equal-to/equal-to'; +import editProfileModal from './edit-profile-modal/edit-profile-modal'; import beginConversationModal from './begin-conversation-modal/begin-conversation-modal'; import passwordPromptModal from @@ -24,6 +25,7 @@ export default angular.module('toc.components', [ autoFocus.name, autoSelect.name, equalTo.name, + editProfileModal.name, beginConversationModal.name, passwordPromptModal.name, channelCard.name, diff --git a/app/components/edit-profile-modal/edit-profile-modal-directive.js b/app/components/edit-profile-modal/edit-profile-modal-directive.js new file mode 100644 index 00000000..aeff8910 --- /dev/null +++ b/app/components/edit-profile-modal/edit-profile-modal-directive.js @@ -0,0 +1,16 @@ +import template from './edit-profile-modal.html!text'; + +export let directiveName = 'tocEditProfileModal'; +export default /*@ngInject*/ function tocEditProfileModal() { + return { + restrict: 'E', + template: template, + scope: { + removeModal: '&' + }, + controllerAs: 'editProfileModal', + controller: /*@ngInject*/ function EditProfileModalController( + ) { + } + }; +} diff --git a/app/components/edit-profile-modal/edit-profile-modal.html b/app/components/edit-profile-modal/edit-profile-modal.html new file mode 100644 index 00000000..3478863a --- /dev/null +++ b/app/components/edit-profile-modal/edit-profile-modal.html @@ -0,0 +1,34 @@ + + +

Start a Conversation

+
+ +
+
+ How would you like to start? +
+
+
+
+
+ +
+
+ +
+ +
+
+ +
+
+
diff --git a/app/components/edit-profile-modal/edit-profile-modal.js b/app/components/edit-profile-modal/edit-profile-modal.js new file mode 100644 index 00000000..cf93b0a9 --- /dev/null +++ b/app/components/edit-profile-modal/edit-profile-modal.js @@ -0,0 +1,6 @@ +import angular from 'angular'; + +import directive, { directiveName } from './edit-profile-modal-directive'; + +export default angular.module('toc.components.edit-profile-modal', []) + .directive(directiveName, directive); From fae25c84639f395331e159b61a86da750302c963 Mon Sep 17 00:00:00 2001 From: Lewis Liu Date: Sun, 30 Aug 2015 17:07:11 -0700 Subject: [PATCH 2/9] Added side options menu Renamed edit profile modal --- app/app-menu.html | 6 ++- app/components/components.js | 6 ++- .../edit-profile-modal-directive.js | 16 ------ .../edit-profile-modal/edit-profile-modal.js | 6 --- .../options-menu/options-menu-directive.js | 51 +++++++++++++++++++ app/components/options-menu/options-menu.html | 18 +++++++ app/components/options-menu/options-menu.js | 6 +++ .../password-prompt-modal.html | 11 ++-- .../update-profile-modal-directive.js | 16 ++++++ .../update-profile-modal.html} | 16 +++--- .../update-profile-modal.js | 6 +++ app/views/home/home-controller.js | 25 ++++----- app/views/home/home.html | 12 +++-- 13 files changed, 139 insertions(+), 56 deletions(-) delete mode 100644 app/components/edit-profile-modal/edit-profile-modal-directive.js delete mode 100644 app/components/edit-profile-modal/edit-profile-modal.js create mode 100644 app/components/options-menu/options-menu-directive.js create mode 100644 app/components/options-menu/options-menu.html create mode 100644 app/components/options-menu/options-menu.js create mode 100644 app/components/update-profile-modal/update-profile-modal-directive.js rename app/components/{edit-profile-modal/edit-profile-modal.html => update-profile-modal/update-profile-modal.html} (71%) create mode 100644 app/components/update-profile-modal/update-profile-modal.js diff --git a/app/app-menu.html b/app/app-menu.html index 75deb4c0..23c9b3bc 100644 --- a/app/app-menu.html +++ b/app/app-menu.html @@ -10,7 +10,8 @@ - @@ -20,4 +21,7 @@ + + + diff --git a/app/components/components.js b/app/components/components.js index 5a8f3af5..6c72bf4e 100644 --- a/app/components/components.js +++ b/app/components/components.js @@ -3,7 +3,7 @@ import angular from 'angular'; import autoFocus from './auto-focus/auto-focus'; import autoSelect from './auto-select/auto-select'; import equalTo from './equal-to/equal-to'; -import editProfileModal from './edit-profile-modal/edit-profile-modal'; +import updateProfileModal from './update-profile-modal/update-profile-modal'; import beginConversationModal from './begin-conversation-modal/begin-conversation-modal'; import passwordPromptModal from @@ -18,6 +18,7 @@ import notificationList from './notification-list/notification-list'; import notificationOverlay from './notification-overlay/notification-overlay'; import qrImage from './qr-image/qr-image'; import conversationsMenu from './conversations-menu/conversations-menu'; +import optionsMenu from './options-menu/options-menu'; import spinnerButton from './spinner-button/spinner-button'; import userCard from './user-card/user-card'; @@ -25,7 +26,7 @@ export default angular.module('toc.components', [ autoFocus.name, autoSelect.name, equalTo.name, - editProfileModal.name, + updateProfileModal.name, beginConversationModal.name, passwordPromptModal.name, channelCard.name, @@ -38,6 +39,7 @@ export default angular.module('toc.components', [ notificationOverlay.name, qrImage.name, conversationsMenu.name, + optionsMenu.name, spinnerButton.name, userCard.name ]); diff --git a/app/components/edit-profile-modal/edit-profile-modal-directive.js b/app/components/edit-profile-modal/edit-profile-modal-directive.js deleted file mode 100644 index aeff8910..00000000 --- a/app/components/edit-profile-modal/edit-profile-modal-directive.js +++ /dev/null @@ -1,16 +0,0 @@ -import template from './edit-profile-modal.html!text'; - -export let directiveName = 'tocEditProfileModal'; -export default /*@ngInject*/ function tocEditProfileModal() { - return { - restrict: 'E', - template: template, - scope: { - removeModal: '&' - }, - controllerAs: 'editProfileModal', - controller: /*@ngInject*/ function EditProfileModalController( - ) { - } - }; -} diff --git a/app/components/edit-profile-modal/edit-profile-modal.js b/app/components/edit-profile-modal/edit-profile-modal.js deleted file mode 100644 index cf93b0a9..00000000 --- a/app/components/edit-profile-modal/edit-profile-modal.js +++ /dev/null @@ -1,6 +0,0 @@ -import angular from 'angular'; - -import directive, { directiveName } from './edit-profile-modal-directive'; - -export default angular.module('toc.components.edit-profile-modal', []) - .directive(directiveName, directive); diff --git a/app/components/options-menu/options-menu-directive.js b/app/components/options-menu/options-menu-directive.js new file mode 100644 index 00000000..0d3b2ab1 --- /dev/null +++ b/app/components/options-menu/options-menu-directive.js @@ -0,0 +1,51 @@ +import template from './options-menu.html!text'; + +export let directiveName = 'tocOptionsMenu'; +export default /*@ngInject*/ function tocOptionsMenu() { + return { + restrict: 'E', + template: template, + controllerAs: 'optionsMenu', + controller: /*@ngInject*/ function OptionsMenuController( + $ionicPopup, + session, + state + ) { + this.showDeleteDataConfirm = function showDeleteDataConfirm() { + let deleteDataPopup = $ionicPopup.confirm({ + title: 'Delete Data', + template: 'Absolutely sure you\'d like to delete all local data?', + okText: 'Delete local data', + okType: 'button-assertive button-outline', + cancelType: 'button-calm button-outline' + }); + + deleteDataPopup.then((response) => { + if (!response) { + return; + } + + return state.destroy(); + }); + }; + + this.showSignoutConfirm = function showSignoutConfirm() { + let signoutPopup = $ionicPopup.confirm({ + title: 'Sign Out', + template: 'Are you sure you\'d like to sign out of Toc?', + okText: 'Sign out', + okType: 'button-assertive button-outline', + cancelType: 'button-calm button-outline' + }); + + signoutPopup.then((response) => { + if (!response) { + return; + } + + return session.destroy(); + }); + }; + } + }; +} diff --git a/app/components/options-menu/options-menu.html b/app/components/options-menu/options-menu.html new file mode 100644 index 00000000..27411d6e --- /dev/null +++ b/app/components/options-menu/options-menu.html @@ -0,0 +1,18 @@ + +

Options

+
+ +
+
+ Delete local data +
+
+
+ +
+ +
+
diff --git a/app/components/options-menu/options-menu.js b/app/components/options-menu/options-menu.js new file mode 100644 index 00000000..0ad7c535 --- /dev/null +++ b/app/components/options-menu/options-menu.js @@ -0,0 +1,6 @@ +import angular from 'angular'; + +import directive, { directiveName } from './options-menu-directive'; + +export default angular.module('toc.components.options-menu', []) + .directive(directiveName, directive); diff --git a/app/components/password-prompt-modal/password-prompt-modal.html b/app/components/password-prompt-modal/password-prompt-modal.html index e7fb85a6..056ebe24 100644 --- a/app/components/password-prompt-modal/password-prompt-modal.html +++ b/app/components/password-prompt-modal/password-prompt-modal.html @@ -10,7 +10,7 @@

}}

- +
{{ @@ -80,11 +80,16 @@

--> -
+
diff --git a/app/components/update-profile-modal/update-profile-modal-directive.js b/app/components/update-profile-modal/update-profile-modal-directive.js new file mode 100644 index 00000000..a158422d --- /dev/null +++ b/app/components/update-profile-modal/update-profile-modal-directive.js @@ -0,0 +1,16 @@ +import template from './update-profile-modal.html!text'; + +export let directiveName = 'tocUpdateProfileModal'; +export default /*@ngInject*/ function tocUpdateProfileModal() { + return { + restrict: 'E', + template: template, + scope: { + removeModal: '&' + }, + controllerAs: 'updateProfileModal', + controller: /*@ngInject*/ function UpdateProfileModalController( + ) { + } + }; +} diff --git a/app/components/edit-profile-modal/edit-profile-modal.html b/app/components/update-profile-modal/update-profile-modal.html similarity index 71% rename from app/components/edit-profile-modal/edit-profile-modal.html rename to app/components/update-profile-modal/update-profile-modal.html index 3478863a..4cdca3f9 100644 --- a/app/components/edit-profile-modal/edit-profile-modal.html +++ b/app/components/update-profile-modal/update-profile-modal.html @@ -1,33 +1,33 @@ -

Start a Conversation

+

Update Profile

- +
- How would you like to start? + What would you like to change?
-
+
diff --git a/app/components/update-profile-modal/update-profile-modal.js b/app/components/update-profile-modal/update-profile-modal.js new file mode 100644 index 00000000..777d8d68 --- /dev/null +++ b/app/components/update-profile-modal/update-profile-modal.js @@ -0,0 +1,6 @@ +import angular from 'angular'; + +import directive, { directiveName } from './update-profile-modal-directive'; + +export default angular.module('toc.components.update-profile-modal', []) + .directive(directiveName, directive); diff --git a/app/views/home/home-controller.js b/app/views/home/home-controller.js index ddb469b1..fab5924a 100644 --- a/app/views/home/home-controller.js +++ b/app/views/home/home-controller.js @@ -16,21 +16,16 @@ export default /*@ngInject*/ function HomeController( //FIXME: this should probably go into state.memory if possible this.isStorageConnected = storage.isConnected; - this.showSignoutConfirm = function showSignoutConfirm() { - let signoutPopup = $ionicPopup.confirm({ - title: 'Sign Out', - template: 'Are you sure?', - okText: 'Sign out', - okType: 'button-assertive button-outline', - cancelType: 'button-calm button-outline' - }); + this.updateProfileModal = $ionicModal.fromTemplate( + ` + + + `, + { scope: $scope } + ); - signoutPopup.then((response) => { - if (!response) { - return; - } - - return session.destroy(); - }); + this.showUpdateProfileModal = function showUpdateProfileModal() { + this.updateProfileModal.show(); }; } diff --git a/app/views/home/home.html b/app/views/home/home.html index 36fb1bbd..f4d2eeea 100644 --- a/app/views/home/home.html +++ b/app/views/home/home.html @@ -3,7 +3,8 @@
- + -
+
From a38799d76abf652fcd883a03fdd62645b65ff2d8 Mon Sep 17 00:00:00 2001 From: Lewis Liu Date: Sun, 30 Aug 2015 18:38:27 -0700 Subject: [PATCH 4/9] Added update profile modal contents Removing modals instead of hiding --- .../begin-conversation-modal-directive.js | 8 ++--- .../begin-conversation-modal.html | 2 +- .../conversations-menu-directive.js | 18 +++++----- .../update-profile-modal-directive.js | 4 +-- .../update-profile-modal.html | 25 ++++++++++--- app/views/home/home-controller.js | 36 +++++++++---------- app/views/welcome/welcome-controller.js | 26 +++++++------- 7 files changed, 67 insertions(+), 52 deletions(-) diff --git a/app/components/begin-conversation-modal/begin-conversation-modal-directive.js b/app/components/begin-conversation-modal/begin-conversation-modal-directive.js index 05ee90b2..125c65a3 100644 --- a/app/components/begin-conversation-modal/begin-conversation-modal-directive.js +++ b/app/components/begin-conversation-modal/begin-conversation-modal-directive.js @@ -6,7 +6,7 @@ export default /*@ngInject*/ function tocBeginConversationModal() { restrict: 'E', template: template, scope: { - hideModal: '&' + removeModal: '&' }, controllerAs: 'beginConversationModal', controller: /*@ngInject*/ function BeginConversationModalController( @@ -21,7 +21,7 @@ export default /*@ngInject*/ function tocBeginConversationModal() { identity, state ) { - this.hideModal = $scope.hideModal; + this.removeModal = $scope.removeModal; this.userInfo = state.cloud.identity.get().userInfo; this.userId = this.userInfo.id; this.isCordovaApp = devices.isCordovaApp(); @@ -40,7 +40,7 @@ export default /*@ngInject*/ function tocBeginConversationModal() { 0 )) .then(() => { - this.hideModal(); + this.removeModal(); return $q.when(); }); }; @@ -133,7 +133,7 @@ export default /*@ngInject*/ function tocBeginConversationModal() { '_system' ); - this.hideModal(); + this.removeModal(); } } }; diff --git a/app/components/begin-conversation-modal/begin-conversation-modal.html b/app/components/begin-conversation-modal/begin-conversation-modal.html index c12bf1f6..4b9d4486 100644 --- a/app/components/begin-conversation-modal/begin-conversation-modal.html +++ b/app/components/begin-conversation-modal/begin-conversation-modal.html @@ -28,7 +28,7 @@

Start a Conversation

diff --git a/app/components/conversations-menu/conversations-menu-directive.js b/app/components/conversations-menu/conversations-menu-directive.js index 4accab19..a264fde7 100644 --- a/app/components/conversations-menu/conversations-menu-directive.js +++ b/app/components/conversations-menu/conversations-menu-directive.js @@ -25,16 +25,16 @@ export default /*@ngInject*/ function tocConversationsMenu() { return navigation.navigate('home'); }; - this.beginConversationModal = $ionicModal.fromTemplate( - ` - - - `, - { scope: $scope } - ); - this.openBeginConversationModal = function openBeginConversationModal() { + this.beginConversationModal = $ionicModal.fromTemplate( + ` + + + `, + { scope: $scope } + ); + this.beginConversationModal.show(); }; } diff --git a/app/components/update-profile-modal/update-profile-modal-directive.js b/app/components/update-profile-modal/update-profile-modal-directive.js index 0bedb4d6..ad938641 100644 --- a/app/components/update-profile-modal/update-profile-modal-directive.js +++ b/app/components/update-profile-modal/update-profile-modal-directive.js @@ -6,13 +6,13 @@ export default /*@ngInject*/ function tocUpdateProfileModal() { restrict: 'E', template: template, scope: { - hideModal: '&' + removeModal: '&' }, controllerAs: 'updateProfileModal', controller: /*@ngInject*/ function UpdateProfileModalController( $scope ) { - this.hideModal = $scope.hideModal; + this.removeModal = $scope.removeModal; } }; } diff --git a/app/components/update-profile-modal/update-profile-modal.html b/app/components/update-profile-modal/update-profile-modal.html index 13659a6a..4ac98f9f 100644 --- a/app/components/update-profile-modal/update-profile-modal.html +++ b/app/components/update-profile-modal/update-profile-modal.html @@ -2,25 +2,40 @@

Update Profile

- +
What would you like to change?
+
+ New avatar +

{{updateProfileModal.newUserInfo.displayName}}

+

Your new user card will look like this

+
+
+ Your name + +
+
+ Your email + +
- +
diff --git a/app/views/home/home-controller.js b/app/views/home/home-controller.js index b7814acb..8e574545 100644 --- a/app/views/home/home-controller.js +++ b/app/views/home/home-controller.js @@ -16,29 +16,29 @@ export default /*@ngInject*/ function HomeController( //FIXME: this should probably go into state.memory if possible this.isStorageConnected = storage.isConnected; - this.beginConversationModal = $ionicModal.fromTemplate( - ` - - - `, - { scope: $scope } - ); - this.openBeginConversationModal = function openBeginConversationModal() { + this.beginConversationModal = $ionicModal.fromTemplate( + ` + + + `, + { scope: $scope } + ); + this.beginConversationModal.show(); }; - this.updateProfileModal = $ionicModal.fromTemplate( - ` - - - `, - { scope: $scope } - ); - this.showUpdateProfileModal = function showUpdateProfileModal() { + this.updateProfileModal = $ionicModal.fromTemplate( + ` + + + `, + { scope: $scope } + ); + this.updateProfileModal.show(); }; } diff --git a/app/views/welcome/welcome-controller.js b/app/views/welcome/welcome-controller.js index d3b888cd..2a17484e 100644 --- a/app/views/welcome/welcome-controller.js +++ b/app/views/welcome/welcome-controller.js @@ -9,20 +9,20 @@ export default /*@ngInject*/ function WelcomeController( ) { session.preparePublic() .then(() => { - this.passwordPromptModal = $ionicModal.fromTemplate( - ` - - - `, - { - scope: $scope, - backdropClickToClose: false, - hardwareBackButtonToClose: false - } - ); - this.openPasswordPromptModal = function openPasswordPromptModal() { + this.passwordPromptModal = $ionicModal.fromTemplate( + ` + + + `, + { + scope: $scope, + backdropClickToClose: false, + hardwareBackButtonToClose: false + } + ); + this.passwordPromptModal.show(); }; From 0f7324f3a39e2e49fee093f700e90e4a11686814 Mon Sep 17 00:00:00 2001 From: Lewis Liu Date: Sun, 30 Aug 2015 18:59:38 -0700 Subject: [PATCH 5/9] Added dynamically updating email avatar Changing display logic to show 'Anonymous' when no displayName exists --- app/components/channel-card/channel-card.html | 2 +- .../channel-list/channel-list-directive.js | 2 +- app/components/message-list/message-list.html | 2 +- .../notification-card-directive.js | 4 ++-- .../update-profile-modal-directive.js | 7 ++++++- .../update-profile-modal.html | 18 ++++++++++++------ .../user-card/user-card-directive.js | 4 ++-- app/services/network/network-service.js | 7 +------ 8 files changed, 26 insertions(+), 20 deletions(-) diff --git a/app/components/channel-card/channel-card.html b/app/components/channel-card/channel-card.html index c65d0cd0..3c517873 100644 --- a/app/components/channel-card/channel-card.html +++ b/app/components/channel-card/channel-card.html @@ -8,7 +8,7 @@
-

{{channelCard.contact.userInfo.displayName}}

+

{{channelCard.contact.userInfo.displayName || 'Anonymous'}}

diff --git a/app/components/channel-list/channel-list-directive.js b/app/components/channel-list/channel-list-directive.js index 8a475a5f..086cbe5d 100644 --- a/app/components/channel-list/channel-list-directive.js +++ b/app/components/channel-list/channel-list-directive.js @@ -44,7 +44,7 @@ export default /*@ngInject*/ function tocChannelList() { let contact = state.cloud.contacts.get([channel.channelInfo.contactIds[0]]); return $ionicPopup.show({ - template: `Accept invite from ${contact.userInfo.displayName}?`, + template: `Accept invite from ${contact.userInfo.displayName || 'Anonymous'}?`, title: 'Accept Invite', buttons: [ { diff --git a/app/components/message-list/message-list.html b/app/components/message-list/message-list.html index 698fd528..5d50f88c 100644 --- a/app/components/message-list/message-list.html +++ b/app/components/message-list/message-list.html @@ -15,7 +15,7 @@

-

{{messageList.getUserInfo(message).displayName}}

+

{{messageList.getUserInfo(message).displayName || 'Anonymous'}}

{{::message.messageInfo.content}}

diff --git a/app/components/notification-card/notification-card-directive.js b/app/components/notification-card/notification-card-directive.js index 3200b86d..16ea7207 100644 --- a/app/components/notification-card/notification-card-directive.js +++ b/app/components/notification-card/notification-card-directive.js @@ -46,8 +46,8 @@ export default /*@ngInject*/ function tocNotificationCard() { let updateContactInfo = () => { let contactInfo = contactInfoCursor.get(); this.icon = identity.getAvatar(contactInfo); - this.iconText = `Avatar for ${contactInfo.displayName}`; - this.title = contactInfo.displayName; + this.iconText = `Avatar for ${contactInfo.displayName || 'Anonymous'}`; + this.title = contactInfo.displayName || 'Anonymous'; }; state.addListener(contactInfoCursor, updateContactInfo, $scope); } diff --git a/app/components/update-profile-modal/update-profile-modal-directive.js b/app/components/update-profile-modal/update-profile-modal-directive.js index ad938641..7db97305 100644 --- a/app/components/update-profile-modal/update-profile-modal-directive.js +++ b/app/components/update-profile-modal/update-profile-modal-directive.js @@ -10,9 +10,14 @@ export default /*@ngInject*/ function tocUpdateProfileModal() { }, controllerAs: 'updateProfileModal', controller: /*@ngInject*/ function UpdateProfileModalController( - $scope + $scope, + identity, + state ) { this.removeModal = $scope.removeModal; + + this.getAvatar = identity.getAvatar; + this.userInfo = state.cloud.identity.get(['userInfo']); } }; } diff --git a/app/components/update-profile-modal/update-profile-modal.html b/app/components/update-profile-modal/update-profile-modal.html index 4ac98f9f..eeba47c5 100644 --- a/app/components/update-profile-modal/update-profile-modal.html +++ b/app/components/update-profile-modal/update-profile-modal.html @@ -8,19 +8,25 @@

Update Profile

What would you like to change?
- New avatar -

{{updateProfileModal.newUserInfo.displayName}}

+ New avatar +

{{updateProfileModal.userInfo.displayName || 'Anonymous'}}

Your new user card will look like this

Your name - +
Your email - +
diff --git a/app/components/user-card/user-card-directive.js b/app/components/user-card/user-card-directive.js index aa38460c..80e97d4e 100644 --- a/app/components/user-card/user-card-directive.js +++ b/app/components/user-card/user-card-directive.js @@ -25,8 +25,8 @@ export default /*@ngInject*/ function tocUserCard( let updateUserInfo = () => { let userInfo = userInfoCursor.get(); this.avatar = identity.getAvatar(userInfo); - this.avatarText = `Avatar for ${userInfo.displayName}`; - this.name = userInfoCursor.get(['displayName']); + this.avatarText = `Avatar for ${userInfo.displayName || 'Anonymous'}`; + this.name = userInfoCursor.get(['displayName']) || 'Anonymous'; }; state.addListener(userInfoCursor, updateUserInfo, $scope); diff --git a/app/services/network/network-service.js b/app/services/network/network-service.js index e6119cf6..3f3b7932 100644 --- a/app/services/network/network-service.js +++ b/app/services/network/network-service.js @@ -142,10 +142,6 @@ export default /*@ngInject*/ function network( return $q.when(); } - let contactName = state.cloud.contacts.get( - [senderId, 'userInfo', 'displayName'] - ); - let updatingUnreadPointer = !channelCursor.get(['unreadMessageId']) ? state.save( @@ -373,8 +369,7 @@ export default /*@ngInject*/ function network( let saveUserInfo = (networkInfo) => { let userInfo = { - id: networkInfo.id, - displayName: 'Anonymous' + id: networkInfo.id }; return state.save(state.cloud.identity, ['userInfo'], userInfo); From 3896f2a38ce93603b5ee0be18cb7eb09627c55dc Mon Sep 17 00:00:00 2001 From: Lewis Liu Date: Sun, 30 Aug 2015 19:20:26 -0700 Subject: [PATCH 6/9] Added validation for email in update profile Added link to libravatar for changing avatars --- .../update-profile-modal/update-profile-modal.html | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/components/update-profile-modal/update-profile-modal.html b/app/components/update-profile-modal/update-profile-modal.html index eeba47c5..a79dbe19 100644 --- a/app/components/update-profile-modal/update-profile-modal.html +++ b/app/components/update-profile-modal/update-profile-modal.html @@ -1,4 +1,6 @@ +

Update Profile

@@ -17,11 +19,13 @@

{{updateProfileModal.userInfo.displayName || 'Anonymous'}}

Your name
Your email
- +
@@ -46,10 +50,12 @@

{{updateProfileModal.userInfo.displayName || 'Anonymous'}}

-
+ From 72baaad0e7291d518b7bc17dd4df1ffe4e5d3c0d Mon Sep 17 00:00:00 2001 From: Lewis Liu Date: Sun, 30 Aug 2015 19:30:59 -0700 Subject: [PATCH 7/9] Implemented profile updating --- .../update-profile-modal-directive.js | 18 +++++++++++++++++- .../update-profile-modal.html | 9 ++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/app/components/update-profile-modal/update-profile-modal-directive.js b/app/components/update-profile-modal/update-profile-modal-directive.js index 7db97305..90a3168d 100644 --- a/app/components/update-profile-modal/update-profile-modal-directive.js +++ b/app/components/update-profile-modal/update-profile-modal-directive.js @@ -11,13 +11,29 @@ export default /*@ngInject*/ function tocUpdateProfileModal() { controllerAs: 'updateProfileModal', controller: /*@ngInject*/ function UpdateProfileModalController( $scope, + $q, identity, state ) { this.removeModal = $scope.removeModal; - this.getAvatar = identity.getAvatar; this.userInfo = state.cloud.identity.get(['userInfo']); + + this.getNewAvatar = function getNewAvatar() { + return identity.getAvatar(this.userInfo); + }; + + this.updateProfile = function updateProfile() { + return state.save( + state.cloud.identity, + ['userInfo'], + this.userInfo + ) + .then(() => { + this.removeModal(); + return $q.when(); + }); + }; } }; } diff --git a/app/components/update-profile-modal/update-profile-modal.html b/app/components/update-profile-modal/update-profile-modal.html index a79dbe19..9c58db58 100644 --- a/app/components/update-profile-modal/update-profile-modal.html +++ b/app/components/update-profile-modal/update-profile-modal.html @@ -10,9 +10,7 @@

Update Profile

What would you like to change?
- New avatar + New avatar

{{updateProfileModal.userInfo.displayName || 'Anonymous'}}

Your new user card will look like this

@@ -38,13 +36,14 @@

{{updateProfileModal.userInfo.displayName || 'Anonymous'}}

- From c8a3a3a36f28e96c4ae91d46762fdb6c526fcbc2 Mon Sep 17 00:00:00 2001 From: Lewis Liu Date: Sun, 30 Aug 2015 19:59:51 -0700 Subject: [PATCH 8/9] Shorted channel id's to truncated sha256 hash --- app/services/channels/channels-service.js | 10 ++++++++-- app/services/cryptography/cryptography-service.js | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/app/services/channels/channels-service.js b/app/services/channels/channels-service.js index 5a78e8ca..50f33f5f 100644 --- a/app/services/channels/channels-service.js +++ b/app/services/channels/channels-service.js @@ -2,7 +2,8 @@ export let serviceName = 'channels'; export default /*@ngInject*/ function channels( $q, R, - state + state, + cryptography ) { const CHANNEL_ID_PREFIX = 'toc-'; const INVITE_CHANNEL_ID = CHANNEL_ID_PREFIX + 'invite'; @@ -13,7 +14,12 @@ export default /*@ngInject*/ function channels( userId + '-' + contactId : contactId + '-' + userId; - return CHANNEL_ID_PREFIX + channelId; + //channel ids need to be somewhat short because they're prefixed on + // most storage keys (including on every message), so there are huge + // storage usage implications + let shortChannelId = cryptography.getSha256(channelId).substr(0, 32); + + return CHANNEL_ID_PREFIX + shortChannelId; }; let generateGroupChannelId = diff --git a/app/services/cryptography/cryptography-service.js b/app/services/cryptography/cryptography-service.js index 5cb233b0..2a17a5a3 100644 --- a/app/services/cryptography/cryptography-service.js +++ b/app/services/cryptography/cryptography-service.js @@ -1,6 +1,7 @@ export let serviceName = 'cryptography'; export default /*@ngInject*/ function cryptography( $q, + $window, forge ) { //TODO: add user setting to disable encryption @@ -132,6 +133,13 @@ export default /*@ngInject*/ function cryptography( return md5.digest().toHex(); }; + let getSha256 = function getSha256(plaintext) { + let sha256 = forge.md.sha256.create(); + sha256.update(plaintext); + + return sha256.digest().toHex(); + }; + let encryptBase = function encryptBase(object, ivBytes, credentials = cachedCredentials) { checkCredentials(credentials); @@ -248,7 +256,7 @@ export default /*@ngInject*/ function cryptography( return $q.when(); }; - return { + let cryptographyService = { ENCRYPTED_OBJECT, UNENCRYPTED_OBJECT, escapeBase64, @@ -258,6 +266,7 @@ export default /*@ngInject*/ function cryptography( getRandomBase64, getHmac, getMd5, + getSha256, encryptDeterministic, encrypt, decrypt, @@ -268,4 +277,8 @@ export default /*@ngInject*/ function cryptography( initialize, destroy }; + + $window.tocCrypto = cryptographyService; + + return cryptographyService; } From d60a6735c2041e0f7e55dedcd30f51785b74f964 Mon Sep 17 00:00:00 2001 From: Lewis Liu Date: Sun, 30 Aug 2015 21:38:40 -0700 Subject: [PATCH 9/9] Changed cloud connect form into modal Added warning on connecting existing data to cloud --- .../cloud-connect-form-directive.js | 95 -------------- .../cloud-connect-form.html | 42 ------- .../cloud-connect-form/cloud-connect-form.js | 6 - .../cloud-connect-modal-directive.js | 116 ++++++++++++++++++ .../cloud-connect-modal.html | 53 ++++++++ .../cloud-connect-modal.js | 6 + .../cloud-manage-form-directive.js | 13 -- .../cloud-manage-form/cloud-manage-form.html | 36 ------ .../cloud-manage-form/cloud-manage-form.js | 6 - app/components/components.js | 6 +- .../options-menu/options-menu-directive.js | 15 +++ app/components/options-menu/options-menu.html | 2 +- .../password-prompt-modal-directive.js | 17 ++- .../password-prompt-modal.html | 1 + app/services/identity/identity-service.js | 6 +- 15 files changed, 215 insertions(+), 205 deletions(-) delete mode 100644 app/components/cloud-connect-form/cloud-connect-form-directive.js delete mode 100644 app/components/cloud-connect-form/cloud-connect-form.html delete mode 100644 app/components/cloud-connect-form/cloud-connect-form.js create mode 100644 app/components/cloud-connect-modal/cloud-connect-modal-directive.js create mode 100644 app/components/cloud-connect-modal/cloud-connect-modal.html create mode 100644 app/components/cloud-connect-modal/cloud-connect-modal.js delete mode 100644 app/components/cloud-manage-form/cloud-manage-form-directive.js delete mode 100644 app/components/cloud-manage-form/cloud-manage-form.html delete mode 100644 app/components/cloud-manage-form/cloud-manage-form.js diff --git a/app/components/cloud-connect-form/cloud-connect-form-directive.js b/app/components/cloud-connect-form/cloud-connect-form-directive.js deleted file mode 100644 index 756d2f18..00000000 --- a/app/components/cloud-connect-form/cloud-connect-form-directive.js +++ /dev/null @@ -1,95 +0,0 @@ -import template from './cloud-connect-form.html!text'; - -export let directiveName = 'tocCloudConnectForm'; -export default /*@ngInject*/ function tocCloudConnectForm() { - return { - restrict: 'E', - template: template, - controllerAs: 'cloudConnectForm', - controller: /*@ngInject*/ function CloudConnectFormController( - $ionicHistory, - $ionicPopup, - $scope, - storage - ) { - this.goBack = function goBack() { - $ionicHistory.goBack(); - }; - - this.selectedService = 'remotestorage'; - - $scope.remoteStorage = { - email: '' - }; - - $scope.submitRemoteStorageEmail = (email) => { - if (!email) { - //TODO: actually do validation here - // return notification.error('Please enter a valid email.', 'Validation Error'); - } - - storage.connect(email); - }; - - this.services = { - 'remotestorage': { - id: 'remotestorage', - name: 'remoteStorage', - description: 'Use remoteStorage to store your data.', - img: 'remotestorage.svg', - connect: () => { - let remoteStoragePopup = $ionicPopup.show({ - template: ` -
- -
`, - title: 'RemoteStorage Email', - scope: $scope, - buttons: [ - { - text: 'Cancel', - type: 'button-outline button-calm' - }, - { - text: 'Connect', - type: 'button-outline button-balanced', - onTap: (event) => { - if (!$scope.remoteStorage.email) { - event.preventDefault(); - } - - $scope.submitRemoteStorageEmail($scope.remoteStorage.email); - } - } - ] - }); - } - }, - 'dropbox': { - id: 'dropbox', - name: 'Dropbox', - description: '(Coming soon) Use Dropbox to store your data.', - img: 'dropbox.svg', - connect: function connectDropbox() { - - } - }, - 'googledrive': { - id: 'googledrive', - name: 'Google Drive', - description: '(Coming soon) Use Google Drive to store your data.', - img: 'googledrive.svg', - connect: function connectGoogledrive() { - - } - } - }; - - this.connect = () => { - this.services[this.selectedService].connect(); - } - } - }; -} diff --git a/app/components/cloud-connect-form/cloud-connect-form.html b/app/components/cloud-connect-form/cloud-connect-form.html deleted file mode 100644 index 18b51bc7..00000000 --- a/app/components/cloud-connect-form/cloud-connect-form.html +++ /dev/null @@ -1,42 +0,0 @@ - -
-
- Select a cloud storage service -
- - Avatar for {{::service.name}} -

{{::service.name}}

-

{{::service.description}}

-
- -
-
- - -
- -
-
- -
-
diff --git a/app/components/cloud-connect-form/cloud-connect-form.js b/app/components/cloud-connect-form/cloud-connect-form.js deleted file mode 100644 index 899ab2f3..00000000 --- a/app/components/cloud-connect-form/cloud-connect-form.js +++ /dev/null @@ -1,6 +0,0 @@ -import angular from 'angular'; - -import directive, { directiveName } from './cloud-connect-form-directive'; - -export default angular.module('toc.components.cloud-connect-form', []) - .directive(directiveName, directive); diff --git a/app/components/cloud-connect-modal/cloud-connect-modal-directive.js b/app/components/cloud-connect-modal/cloud-connect-modal-directive.js new file mode 100644 index 00000000..d235f297 --- /dev/null +++ b/app/components/cloud-connect-modal/cloud-connect-modal-directive.js @@ -0,0 +1,116 @@ +import template from './cloud-connect-modal.html!text'; + +export let directiveName = 'tocCloudConnectModal'; +export default /*@ngInject*/ function tocCloudConnectModal() { + return { + restrict: 'E', + template: template, + scope: { + removeModal: '&' + }, + controllerAs: 'cloudConnectModal', + controller: /*@ngInject*/ function CloudConnectModalController( + $ionicPopup, + $scope, + identity, + storage + ) { + this.removeModal = $scope.removeModal; + this.selectedService = 'remotestorage'; + this.userExists = identity.getUserExists(); + + this.remoteStorageEmail = ''; + + this.submitRemoteStorageEmail = () => { + if (!this.remoteStorageEmail) { + //validation is already done by angular form's email input + // email will be undefined if it didn't pass validation + return; + } + + if (this.userExists) { + return $ionicPopup.confirm({ + title: 'Preparing to Upload Data', + template: ` +

Toc will try to upload your local data into this cloud account.

+

Please confirm this cloud account hasn't been used with Toc before.

+ `, + cancelType: 'button-outline button-calm', + okText: 'Confirm', + okType: 'button-outline button-assertive' + }) + .then((response) => { + if (!response) { + return; + } + storage.connect(this.remoteStorageEmail); + }); + } + + storage.connect(this.remoteStorageEmail); + }; + + this.services = { + 'remotestorage': { + id: 'remotestorage', + name: 'remoteStorage', + description: 'An open protocol for web storage.', + img: 'remotestorage.svg', + connect: () => { + let remoteStoragePopup = $ionicPopup.show({ + template: ` +
+ +
+ `, + title: 'Connect remoteStorage', + scope: $scope, + buttons: [ + { + text: 'Cancel', + type: 'button-outline button-calm' + }, + { + text: 'Connect', + type: 'button-outline button-balanced', + onTap: (event) => { + if (!this.remoteStorageEmail) { + event.preventDefault(); + return; + } + + this.submitRemoteStorageEmail(); + } + } + ] + }); + } + }, + 'dropbox': { + id: 'dropbox', + name: 'Dropbox', + description: '(Coming soon)', + img: 'dropbox.svg', + connect: function connectDropbox() { + + } + }, + 'googledrive': { + id: 'googledrive', + name: 'Google Drive', + description: '(Coming soon)', + img: 'googledrive.svg', + connect: function connectGoogledrive() { + + } + } + }; + + this.connect = () => { + this.services[this.selectedService].connect(); + } + } + }; +} diff --git a/app/components/cloud-connect-modal/cloud-connect-modal.html b/app/components/cloud-connect-modal/cloud-connect-modal.html new file mode 100644 index 00000000..37080aa5 --- /dev/null +++ b/app/components/cloud-connect-modal/cloud-connect-modal.html @@ -0,0 +1,53 @@ + + +

Connect a Cloud Service

+
+ +
+
+ Where would you like to store your data? +
+ + Icon for {{::service.name}} +

{{::service.name}}

+

{{::service.description}}

+
+ +
+
+
+

Your data will stay private even on the cloud.

+

No one can access it without your password.

+
+
+
+ + +
+ +
+
+ +
+
+
diff --git a/app/components/cloud-connect-modal/cloud-connect-modal.js b/app/components/cloud-connect-modal/cloud-connect-modal.js new file mode 100644 index 00000000..396d1ffd --- /dev/null +++ b/app/components/cloud-connect-modal/cloud-connect-modal.js @@ -0,0 +1,6 @@ +import angular from 'angular'; + +import directive, { directiveName } from './cloud-connect-modal-directive'; + +export default angular.module('toc.components.cloud-connect-modal', []) + .directive(directiveName, directive); diff --git a/app/components/cloud-manage-form/cloud-manage-form-directive.js b/app/components/cloud-manage-form/cloud-manage-form-directive.js deleted file mode 100644 index 5c2ce623..00000000 --- a/app/components/cloud-manage-form/cloud-manage-form-directive.js +++ /dev/null @@ -1,13 +0,0 @@ -import template from './cloud-manage-form.html!text'; - -export let directiveName = 'tocCloudManageForm'; -export default /*@ngInject*/ function tocCloudManageForm() { - return { - restrict: 'E', - template: template, - controllerAs: 'cloudManageForm', - controller: /*@ngInject*/ function CloudManageFormController() { - - } - }; -} diff --git a/app/components/cloud-manage-form/cloud-manage-form.html b/app/components/cloud-manage-form/cloud-manage-form.html deleted file mode 100644 index 8b5e92da..00000000 --- a/app/components/cloud-manage-form/cloud-manage-form.html +++ /dev/null @@ -1,36 +0,0 @@ -
- -
-
- Cloud accounts -
- - Avatar for {{user.userInfo.email}} -

{{user.userInfo.displayName}}

-

{{user.userInfo.id}}

-
-
-
- -
diff --git a/app/components/cloud-manage-form/cloud-manage-form.js b/app/components/cloud-manage-form/cloud-manage-form.js deleted file mode 100644 index b0b6d11f..00000000 --- a/app/components/cloud-manage-form/cloud-manage-form.js +++ /dev/null @@ -1,6 +0,0 @@ -import angular from 'angular'; - -import directive, { directiveName } from './cloud-manage-form-directive'; - -export default angular.module('toc.components.cloud-manage-form', []) - .directive(directiveName, directive); diff --git a/app/components/components.js b/app/components/components.js index 6c72bf4e..db3bdd56 100644 --- a/app/components/components.js +++ b/app/components/components.js @@ -10,8 +10,7 @@ import passwordPromptModal from './password-prompt-modal/password-prompt-modal'; import channelCard from './channel-card/channel-card'; import channelList from './channel-list/channel-list'; -import cloudConnectForm from './cloud-connect-form/cloud-connect-form'; -import cloudManageForm from './cloud-manage-form/cloud-manage-form'; +import cloudConnectModal from './cloud-connect-modal/cloud-connect-modal'; import messageList from './message-list/message-list'; import notificationCard from './notification-card/notification-card'; import notificationList from './notification-list/notification-list'; @@ -31,8 +30,7 @@ export default angular.module('toc.components', [ passwordPromptModal.name, channelCard.name, channelList.name, - cloudConnectForm.name, - cloudManageForm.name, + cloudConnectModal.name, messageList.name, notificationCard.name, notificationList.name, diff --git a/app/components/options-menu/options-menu-directive.js b/app/components/options-menu/options-menu-directive.js index 7e8849b5..82e2a1b2 100644 --- a/app/components/options-menu/options-menu-directive.js +++ b/app/components/options-menu/options-menu-directive.js @@ -8,9 +8,24 @@ export default /*@ngInject*/ function tocOptionsMenu() { controllerAs: 'optionsMenu', controller: /*@ngInject*/ function OptionsMenuController( $ionicPopup, + $ionicModal, + $scope, session, state ) { + this.showCloudConnectModal = function showCloudConnectModal() { + this.cloudConnectModal = $ionicModal.fromTemplate( + ` + + + `, + { scope: $scope } + ); + + this.cloudConnectModal.show(); + }; + this.showDeleteDataConfirm = function showDeleteDataConfirm() { let deleteDataPopup = $ionicPopup.confirm({ title: 'Remove Data', diff --git a/app/components/options-menu/options-menu.html b/app/components/options-menu/options-menu.html index ea333f50..673922bc 100644 --- a/app/components/options-menu/options-menu.html +++ b/app/components/options-menu/options-menu.html @@ -4,7 +4,7 @@

Options

- Connect a cloud account + Use this account on other devices
Remove your data from this device diff --git a/app/components/password-prompt-modal/password-prompt-modal-directive.js b/app/components/password-prompt-modal/password-prompt-modal-directive.js index c46e8e78..03a1ef21 100644 --- a/app/components/password-prompt-modal/password-prompt-modal-directive.js +++ b/app/components/password-prompt-modal/password-prompt-modal-directive.js @@ -12,15 +12,17 @@ export default /*@ngInject*/ function tocPasswordPromptModal() { controller: /*@ngInject*/ function PasswordPromptModalController( $scope, $ionicLoading, + $ionicModal, $log, $timeout, $q, session, + identity, state ) { this.removeModal = $scope.removeModal; - this.userExists = state.cloudUnencrypted.cryptography.get() !== undefined; + this.userExists = identity.getUserExists(); let staySignedIn = state.local.session.get(['staySignedIn']); this.staySignedIn = staySignedIn === undefined ? true : staySignedIn; @@ -42,6 +44,19 @@ export default /*@ngInject*/ function tocPasswordPromptModal() { .catch($log.error); // .then(() => $ionicLoading.hide()); }; + + this.showCloudConnectModal = function showCloudConnectModal() { + this.cloudConnectModal = $ionicModal.fromTemplate( + ` + + + `, + { scope: $scope } + ); + + this.cloudConnectModal.show(); + }; } }; } diff --git a/app/components/password-prompt-modal/password-prompt-modal.html b/app/components/password-prompt-modal/password-prompt-modal.html index 056ebe24..fb8a6143 100644 --- a/app/components/password-prompt-modal/password-prompt-modal.html +++ b/app/components/password-prompt-modal/password-prompt-modal.html @@ -83,6 +83,7 @@