From c3a774e414324746c484ad21d19c4be4e2167cd0 Mon Sep 17 00:00:00 2001 From: Emmanuel ROHEE Date: Fri, 29 Aug 2014 17:11:03 +0200 Subject: Show desktop notification state. Provide help if the user has previously denied permission to display them. --- webclient/app-controller.js | 7 ------- webclient/settings/settings-controller.js | 21 ++++++++++++++++++++- webclient/settings/settings.html | 25 +++++++++++++++++++------ 3 files changed, 39 insertions(+), 14 deletions(-) (limited to 'webclient') diff --git a/webclient/app-controller.js b/webclient/app-controller.js index 80474bb8df..775113bc87 100644 --- a/webclient/app-controller.js +++ b/webclient/app-controller.js @@ -69,13 +69,6 @@ angular.module('MatrixWebClientController', ['matrixService', 'mPresence', 'even $scope.logout(); }); - $scope.requestNotifications = function() { - if (window.Notification) { - console.log("Notification.permission: " + window.Notification.permission); - window.Notification.requestPermission(function(){}); - } - }; - }]); diff --git a/webclient/settings/settings-controller.js b/webclient/settings/settings-controller.js index f7d5e8eb75..3a9060ebae 100644 --- a/webclient/settings/settings-controller.js +++ b/webclient/settings/settings-controller.js @@ -25,7 +25,7 @@ angular.module('SettingsController', ['matrixService', 'mFileUpload', 'mFileInpu displayName: $scope.config.displayName, avatarUrl: $scope.config.avatarUrl }; - + $scope.$watch("profile.avatarFile", function(newValue, oldValue) { if ($scope.profile.avatarFile) { console.log("Uploading new avatar file..."); @@ -143,4 +143,23 @@ angular.module('SettingsController', ['matrixService', 'mFileUpload', 'mFileInpu } ); }; + + + /*** Desktop notifications section ***/ + $scope.settings = { + notifications: undefined + }; + + // If the browser supports it, check the desktop notification state + if ("Notification" in window) { + $scope.settings.notifications = window.Notification.permission; + } + + $scope.requestNotifications = function() { + console.log("requestNotifications"); + window.Notification.requestPermission(function (permission) { + console.log(" -> User decision: " + permission); + $scope.settings.notifications = permission; + }); + }; }]); \ No newline at end of file diff --git a/webclient/settings/settings.html b/webclient/settings/settings.html index 453a4fc35f..d06a0083fa 100644 --- a/webclient/settings/settings.html +++ b/webclient/settings/settings.html @@ -52,7 +52,25 @@
- + +

Desktop notifications

+
+
+ Notifications are enabled. +
+
+ You have denied permission for notifications.
+ To enable it, reset the notification setting for this web site into your browser settings. +
+
+ +
+
+ Sorry, your browser does not support notifications. +
+
+
+

Configuration

Home server: {{ config.homeserver }}
@@ -60,11 +78,6 @@
Access token: {{ config.access_token }}

- -
-
-
-
{{ feedback }} -- cgit 1.5.1 From b86d2a2d4fa6e9093bf08df88dce68e5f274c697 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 29 Aug 2014 17:21:57 +0100 Subject: update presence times in realtime through the magic of two-way binding --- webclient/room/room-controller.js | 48 ++++++++++++--------------------------- webclient/room/room.html | 2 +- 2 files changed, 15 insertions(+), 35 deletions(-) (limited to 'webclient') diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js index 09dac85d26..ed7de62c08 100644 --- a/webclient/room/room-controller.js +++ b/webclient/room/room-controller.js @@ -88,7 +88,7 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) call.onHangup = $scope.onCallHangup; $scope.currentCall = call; }); - + $scope.memberCount = function() { return Object.keys($scope.members).length; }; @@ -175,6 +175,8 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) // set target_user_id to keep things clear var target_user_id = chunk.state_key; + + var now = new Date().getTime(); var isNewMember = !(target_user_id in $scope.members); if (isNewMember) { @@ -185,44 +187,14 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) if ("mtime_age" in chunk.content) { chunk.mtime_age = chunk.content.mtime_age; } - // Once the HS reliably returns the displaynames & avatar_urls for both - // local and remote users, we should use this rather than the evalAsync block - // below if ("displayname" in chunk.content) { chunk.displayname = chunk.content.displayname; } if ("avatar_url" in chunk.content) { chunk.avatar_url = chunk.content.avatar_url; } - $scope.members[target_user_id] = chunk; - -/* - // Stale code for explicitly hammering the homeserver for every displayname & avatar_url - - // get their display name and profile picture and set it to their - // member entry in $scope.members. We HAVE to use $timeout with 0 delay - // to make this function run AFTER the current digest cycle, else the - // response may update a STALE VERSION of the member list (manifesting - // as no member names appearing, or appearing sporadically). - $scope.$evalAsync(function() { - matrixService.getDisplayName(chunk.target_user_id).then( - function(response) { - var member = $scope.members[chunk.target_user_id]; - if (member !== undefined) { - member.displayname = response.data.displayname; - } - } - ); - matrixService.getProfilePictureUrl(chunk.target_user_id).then( - function(response) { - var member = $scope.members[chunk.target_user_id]; - if (member !== undefined) { - member.avatar_url = response.data.avatar_url; - } - } - ); - }); -*/ + chunk.last_updated = now; + $scope.members[target_user_id] = chunk; if (target_user_id in $rootScope.presence) { updatePresence($rootScope.presence[target_user_id]); @@ -234,6 +206,12 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) member.content.membership = chunk.content.membership; } }; + + var updateMemberListPresenceAge = function() { + $scope.now = new Date().getTime(); + //console.log("updateMemberListPresenceAge() - now = " + $scope.now); + $timeout(updateMemberListPresenceAge, 5 * 1000); + }; var updatePresence = function(chunk) { if (!(chunk.content.user_id in $scope.members)) { @@ -395,8 +373,10 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) // Make recents highlight the current room $scope.recentsSelectedRoomID = $scope.room_id; - + paginate(MESSAGES_PER_PAGINATION); + + updateMemberListPresenceAge(); }; $scope.inviteUser = function(user_id) { diff --git a/webclient/room/room.html b/webclient/room/room.html index a3514c3a91..cb9239ed56 100644 --- a/webclient/room/room.html +++ b/webclient/room/room.html @@ -25,7 +25,7 @@
{{ member.displayname || member.id.substr(0, member.id.indexOf(':')) }}
{{ member.displayname ? "" : member.id.substr(member.id.indexOf(':')) }}
- {{ member.mtime_age | duration }}
{{ member.mtime_age ? "ago" : "" }} + {{ member.mtime_age + (now - member.last_updated) | duration }}
{{ member.mtime_age ? "ago" : "" }} -- cgit 1.5.1 From 67f42b2f26a6ea76ec480167c58e1fa115809e23 Mon Sep 17 00:00:00 2001 From: Emmanuel ROHEE Date: Fri, 29 Aug 2014 18:22:05 +0200 Subject: Get user display name and avatar from the server rather than storing them in the local storage --- webclient/home/home-controller.js | 27 +++++++++++++++++ webclient/home/home.html | 6 ++-- webclient/settings/settings-controller.js | 50 +++++++++++++++++++++---------- webclient/settings/settings.html | 6 ++-- 4 files changed, 68 insertions(+), 21 deletions(-) (limited to 'webclient') diff --git a/webclient/home/home-controller.js b/webclient/home/home-controller.js index 547a5c5603..7ae13f12e8 100644 --- a/webclient/home/home-controller.js +++ b/webclient/home/home-controller.js @@ -37,6 +37,11 @@ angular.module('HomeController', ['matrixService', 'eventHandlerService', 'Recen $scope.joinAlias = { room_alias: "" }; + + $scope.profile = { + displayName: "", + avatarUrl: "" + }; var refresh = function() { @@ -108,6 +113,28 @@ angular.module('HomeController', ['matrixService', 'eventHandlerService', 'Recen }; $scope.onInit = function() { + // Load profile data + // Display name + matrixService.getDisplayName($scope.config.user_id).then( + function(response) { + $scope.profile.displayName = response.data.displayname; + $scope.profileOnServer.displayName = response.data.displayname; + }, + function(error) { + $scope.feedback = "Can't load display name"; + } + ); + // Avatar + matrixService.getProfilePictureUrl($scope.config.user_id).then( + function(response) { + $scope.profile.avatarUrl = response.data.avatar_url; + $scope.profileOnServer.avatarUrl = response.data.avatar_url; + }, + function(error) { + $scope.feedback = "Can't load avatar URL"; + } + ); + refresh(); }; }]); diff --git a/webclient/home/home.html b/webclient/home/home.html index d38b843d83..1b1c21d9d2 100644 --- a/webclient/home/home.html +++ b/webclient/home/home.html @@ -9,13 +9,13 @@
- +
-
{{ config.displayName }}
-
{{ config.user_id }}
+
{{ profile.displayName }}
+
{{ config.user_id }}
diff --git a/webclient/settings/settings-controller.js b/webclient/settings/settings-controller.js index 3a9060ebae..dc680ef075 100644 --- a/webclient/settings/settings-controller.js +++ b/webclient/settings/settings-controller.js @@ -22,10 +22,40 @@ angular.module('SettingsController', ['matrixService', 'mFileUpload', 'mFileInpu $scope.config = matrixService.config(); $scope.profile = { - displayName: $scope.config.displayName, - avatarUrl: $scope.config.avatarUrl + displayName: "", + avatarUrl: "" }; - + + // The profile as stored on the server + $scope.profileOnServer = { + displayName: "", + avatarUrl: "" + }; + + $scope.onInit = function() { + // Load profile data + // Display name + matrixService.getDisplayName($scope.config.user_id).then( + function(response) { + $scope.profile.displayName = response.data.displayname; + $scope.profileOnServer.displayName = response.data.displayname; + }, + function(error) { + $scope.feedback = "Can't load display name"; + } + ); + // Avatar + matrixService.getProfilePictureUrl($scope.config.user_id).then( + function(response) { + $scope.profile.avatarUrl = response.data.avatar_url; + $scope.profileOnServer.avatarUrl = response.data.avatar_url; + }, + function(error) { + $scope.feedback = "Can't load avatar URL"; + } + ); + }; + $scope.$watch("profile.avatarFile", function(newValue, oldValue) { if ($scope.profile.avatarFile) { console.log("Uploading new avatar file..."); @@ -41,10 +71,10 @@ angular.module('SettingsController', ['matrixService', 'mFileUpload', 'mFileInpu }); $scope.saveProfile = function() { - if ($scope.profile.displayName !== $scope.config.displayName) { + if ($scope.profile.displayName !== $scope.profileOnServer.displayName) { setDisplayName($scope.profile.displayName); } - if ($scope.profile.avatarUrl !== $scope.config.avatarUrl) { + if ($scope.profile.avatarUrl !== $scope.profileOnServer.avatarUrl) { setAvatar($scope.profile.avatarUrl); } }; @@ -53,11 +83,6 @@ angular.module('SettingsController', ['matrixService', 'mFileUpload', 'mFileInpu matrixService.setDisplayName(displayName).then( function(response) { $scope.feedback = "Updated display name."; - - var config = matrixService.config(); - config.displayName = displayName; - matrixService.setConfig(config); - matrixService.saveConfig(); }, function(error) { $scope.feedback = "Can't update display name: " + error.data; @@ -71,11 +96,6 @@ angular.module('SettingsController', ['matrixService', 'mFileUpload', 'mFileInpu function(response) { console.log("Updated avatar"); $scope.feedback = "Updated avatar."; - - var config = matrixService.config(); - config.avatarUrl = avatarURL; - matrixService.setConfig(config); - matrixService.saveConfig(); }, function(error) { $scope.feedback = "Can't update avatar: " + error.data; diff --git a/webclient/settings/settings.html b/webclient/settings/settings.html index d06a0083fa..51884e7209 100644 --- a/webclient/settings/settings.html +++ b/webclient/settings/settings.html @@ -1,4 +1,4 @@ -
+
@@ -10,7 +10,7 @@
- +
@@ -19,7 +19,7 @@
- -- cgit 1.5.1 From e1f249ce20caebf3882278f657102efa05941373 Mon Sep 17 00:00:00 2001 From: Emmanuel ROHEE Date: Fri, 29 Aug 2014 18:24:13 +0200 Subject: Implemented /nick --- webclient/room/room-controller.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'webclient') diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js index ed7de62c08..23764fb725 100644 --- a/webclient/room/room-controller.js +++ b/webclient/room/room-controller.js @@ -253,6 +253,10 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) if ($scope.textInput.indexOf("/me") === 0) { promise = matrixService.sendEmoteMessage($scope.room_id, $scope.textInput.substr(4)); } + else if ($scope.textInput.indexOf("/nick ") === 0) { + // Change user display name + promise = matrixService.setDisplayName($scope.textInput.substr(6)); + } else { promise = matrixService.sendTextMessage($scope.room_id, $scope.textInput); } -- cgit 1.5.1 From 95cbd026ccb7c15daa17bd8eeb1a4551ea62d3fb Mon Sep 17 00:00:00 2001 From: Emmanuel ROHEE Date: Fri, 29 Aug 2014 18:29:04 +0200 Subject: oops. Should not have c+p all lines --- webclient/home/home-controller.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'webclient') diff --git a/webclient/home/home-controller.js b/webclient/home/home-controller.js index 7ae13f12e8..438ffe1b0e 100644 --- a/webclient/home/home-controller.js +++ b/webclient/home/home-controller.js @@ -118,7 +118,6 @@ angular.module('HomeController', ['matrixService', 'eventHandlerService', 'Recen matrixService.getDisplayName($scope.config.user_id).then( function(response) { $scope.profile.displayName = response.data.displayname; - $scope.profileOnServer.displayName = response.data.displayname; }, function(error) { $scope.feedback = "Can't load display name"; @@ -128,7 +127,6 @@ angular.module('HomeController', ['matrixService', 'eventHandlerService', 'Recen matrixService.getProfilePictureUrl($scope.config.user_id).then( function(response) { $scope.profile.avatarUrl = response.data.avatar_url; - $scope.profileOnServer.avatarUrl = response.data.avatar_url; }, function(error) { $scope.feedback = "Can't load avatar URL"; -- cgit 1.5.1 From e006f101c30136f4079f95c0e5c63469fe8887ff Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 29 Aug 2014 17:53:48 +0100 Subject: fix mobile skin by hiding recents LHS in /rooms --- webclient/app.css | 2 ++ 1 file changed, 2 insertions(+) (limited to 'webclient') diff --git a/webclient/app.css b/webclient/app.css index 16f9dd72b7..4e93bc9934 100644 --- a/webclient/app.css +++ b/webclient/app.css @@ -28,6 +28,7 @@ } #userIdCell, + #roomRecentsTableWrapper, #usersTableWrapper, #extraControls { display: none; @@ -353,6 +354,7 @@ h1 { } /*** Recents ***/ + .recentsTable { max-width: 480px; width: 100%; -- cgit 1.5.1 From 26766c22ebbd3fd267fef4f8b13e6e5c31d51d91 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 29 Aug 2014 17:54:11 +0100 Subject: todo --- webclient/room/room-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'webclient') diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js index 23764fb725..c745ce945b 100644 --- a/webclient/room/room-controller.js +++ b/webclient/room/room-controller.js @@ -209,7 +209,7 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) var updateMemberListPresenceAge = function() { $scope.now = new Date().getTime(); - //console.log("updateMemberListPresenceAge() - now = " + $scope.now); + // TODO: don't bother polling every 5s if we know none of our counters are younger than 1 minute $timeout(updateMemberListPresenceAge, 5 * 1000); }; -- cgit 1.5.1 From 490f142d739c7dd30c4ca8e262af5f84c577ebbe Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 29 Aug 2014 18:01:01 +0100 Subject: Give basic feedback on the state of VoIP calls in the UI. --- webclient/components/matrix/matrix-call.js | 3 ++- webclient/room/room-controller.js | 2 -- webclient/room/room.html | 4 ++++ 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'webclient') diff --git a/webclient/components/matrix/matrix-call.js b/webclient/components/matrix/matrix-call.js index c0a7735a7c..47b63d7f2f 100644 --- a/webclient/components/matrix/matrix-call.js +++ b/webclient/components/matrix/matrix-call.js @@ -36,7 +36,7 @@ var forAllTracksOnStream = function(s, f) { } angular.module('MatrixCall', []) -.factory('MatrixCall', ['matrixService', 'matrixPhoneService', function MatrixCallFactory(matrixService, matrixPhoneService) { +.factory('MatrixCall', ['matrixService', 'matrixPhoneService', '$rootScope', function MatrixCallFactory(matrixService, matrixPhoneService, $rootScope) { var MatrixCall = function(room_id) { this.room_id = room_id; this.call_id = "c" + new Date().getTime(); @@ -208,6 +208,7 @@ angular.module('MatrixCall', []) // ideally we'd consider the call to be connected when we get media but chrome doesn't implement nay of the 'onstarted' events yet if (this.peerConn.iceConnectionState == 'completed' || this.peerConn.iceConnectionState == 'connected') { this.state = 'connected'; + $rootScope.$apply(); } }; diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js index c745ce945b..75adf259cf 100644 --- a/webclient/room/room-controller.js +++ b/webclient/room/room-controller.js @@ -471,7 +471,5 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) } $scope.onCallHangup = function() { - $scope.feedback = "Call ended"; - $scope.currentCall = undefined; } }]); diff --git a/webclient/room/room.html b/webclient/room/room.html index cb9239ed56..aa7879ea8f 100644 --- a/webclient/room/room.html +++ b/webclient/room/room.html @@ -105,6 +105,10 @@
+ Calling... + Call Connecting... + Call Connected + Call Ended {{ currentCall.state }}
-- cgit 1.5.1 From c715660cb8acd5333ee3202e2d06bebe6867e47f Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sat, 30 Aug 2014 00:41:36 +0100 Subject: shrink text bubble font a bit; make image thumbnails always fit in their bubbles --- webclient/app.css | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'webclient') diff --git a/webclient/app.css b/webclient/app.css index 4e93bc9934..9ba0aa997c 100644 --- a/webclient/app.css +++ b/webclient/app.css @@ -301,7 +301,7 @@ h1 { display: inline-block; margin-bottom: -1px; max-width: 90%; - font-size: 16px; + font-size: 14px; word-wrap: break-word; padding-top: 7px; padding-bottom: 5px; @@ -311,6 +311,11 @@ h1 { -webkit-text-size-adjust:100% } +.bubble img { + max-width: 100%; + max-height: auto; +} + .differentUser td { padding-bottom: 5px ! important; } -- cgit 1.5.1 From f64ce52305d1486dfcb1ce9f880be97578bbeeec Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sat, 30 Aug 2014 00:44:56 +0100 Subject: actually add a 'home' button --- webclient/index.html | 1 + 1 file changed, 1 insertion(+) (limited to 'webclient') diff --git a/webclient/index.html b/webclient/index.html index 5faf165626..fdc50a5212 100644 --- a/webclient/index.html +++ b/webclient/index.html @@ -41,6 +41,7 @@
-- cgit 1.5.1 From b040bd61572704df800440f42bcf28c48ba939cc Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 31 Aug 2014 00:38:45 +0100 Subject: factor out mobile css into its own file --- webclient/mobile.css | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 webclient/mobile.css (limited to 'webclient') diff --git a/webclient/mobile.css b/webclient/mobile.css new file mode 100644 index 0000000000..7c62a072d5 --- /dev/null +++ b/webclient/mobile.css @@ -0,0 +1,92 @@ +/*** Mobile voodoo ***/ +@media all and (max-device-width: 640px) { + + #messageTableWrapper { + margin-right: 0px ! important; + } + + .leftBlock { + width: 8em ! important; + font-size: 8px ! important; + } + + .rightBlock { + width: 0px ! important; + display: none ! important; + } + + .avatar { + width: 36px ! important; + } + + #header { + background-color: transparent; + } + + #headerContent { + padding-right: 5px; + } + + #headerContent button { + font-size: 8px; + } + + #messageTable, + #wrapper, + #controls { + max-width: 640px ! important; + } + + #headerUserId, + #roomHeader img, + #userIdCell, + #roomRecentsTableWrapper, + #usersTableWrapper, + .extraControls { + display: none; + } + + #buttonsCell { + width: 60px ! important; + padding-left: 20px ! important; + } + + #roomLogo { + display: none; + } + + .bubble { + font-size: 12px ! important; + min-height: 20px ! important; + } + + #roomHeader { + padding-top: 10px; + } + + #roomName { + float: left; + font-size: 14px ! important; + margin-top: 0px ! important; + } + + #roomPage { + top: 35px ! important; + left: 5px ! important; + right: 5px ! important; + bottom: 70px ! important; + } + + #controlPanel { + height: 70px; + } + + /* stop zoom on select */ + select:focus, + textarea, + input + { + font-size: 16px ! important; + } + +} -- cgit 1.5.1 From 1bc036a12d6877f78f1f5033603d803ac01a13d2 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 31 Aug 2014 00:40:42 +0100 Subject: nasty big monolithic commit of a whole bunch of UI/UX improvements: - add a simple CSS template across the app for navigation & cosmetics - split login into login & register, and totally reskin it - restructure room CSS to play nicely with it - implement basis 1:1 chat from user pages - disable autofocus on iOS to improve UX --- webclient/app-controller.js | 12 ++ webclient/app-directive.js | 7 +- webclient/app.css | 296 ++++++++++++++------------ webclient/app.js | 10 +- webclient/components/matrix/matrix-service.js | 14 +- webclient/home/home-controller.js | 4 +- webclient/home/home.html | 40 ++-- webclient/index.html | 18 +- webclient/login/login-controller.js | 59 +---- webclient/login/login.html | 88 ++++---- webclient/room/room-controller.js | 7 +- webclient/room/room.html | 30 +-- webclient/settings/settings.html | 17 +- webclient/user/user-controller.js | 28 +++ webclient/user/user.html | 36 ++-- 15 files changed, 356 insertions(+), 310 deletions(-) (limited to 'webclient') diff --git a/webclient/app-controller.js b/webclient/app-controller.js index 775113bc87..77a7ad03a5 100644 --- a/webclient/app-controller.js +++ b/webclient/app-controller.js @@ -37,6 +37,8 @@ angular.module('MatrixWebClientController', ['matrixService', 'mPresence', 'even mPresence.start(); } + $scope.user_id = matrixService.config().user_id; + /** * Open a given page. * @param {String} url url of the page @@ -45,6 +47,16 @@ angular.module('MatrixWebClientController', ['matrixService', 'mPresence', 'even $location.url(url); }; + // Open the given user profile page + $scope.goToUserPage = function(user_id) { + if (user_id === $scope.user_id) { + $location.url("/settings"); + } + else { + $location.url("/user/" + user_id); + } + }; + // Logs the user out $scope.logout = function() { diff --git a/webclient/app-directive.js b/webclient/app-directive.js index 01f60fdadf..eee0d3842f 100644 --- a/webclient/app-directive.js +++ b/webclient/app-directive.js @@ -32,7 +32,12 @@ angular.module('matrixWebClient') .directive('ngFocus', ['$timeout', function($timeout) { return { link: function(scope, element, attr) { - $timeout(function() { element[0].focus(); }, 0); + // XXX: slightly evil hack to disable autofocus on iOS, as in general + // it causes more problems than it fixes, by bouncing the page + // around + if (!/(iPad|iPhone|iPod)/g.test(navigator.userAgent)) { + $timeout(function() { element[0].focus(); }, 0); + } } }; }]); \ No newline at end of file diff --git a/webclient/app.css b/webclient/app.css index a5d0199bab..142e764ef1 100644 --- a/webclient/app.css +++ b/webclient/app.css @@ -1,122 +1,195 @@ -/*** Mobile voodoo ***/ -@media all and (max-device-width: 640px) { - - #messageTableWrapper { - margin-right: 0px ! important; - } - - .leftBlock { - width: 8em ! important; - font-size: 8px ! important; - } - - .rightBlock { - width: 0px ! important; - display: none ! important; - } - - .avatar { - width: 36px ! important; - } - - #header, - #messageTable, - #wrapper, - #roomName, - #controls { - max-width: 640px ! important; - } - - #userIdCell, - #roomRecentsTableWrapper, - #usersTableWrapper, - #extraControls { - display: none; - } - - #buttonsCell { - width: 60px ! important; - padding-left: 20px ! important; - } - - #roomLogo { - display: none; - } - - #roomName { - text-align: left ! important; - top: -35px ! important; - } - - .bubble { - font-size: 12px ! important; - min-height: 20px ! important; - } - - #page { - top: 35px ! important; - bottom: 70px ! important; - } - - #header, - #page { - margin: 5px ! important; - } - - #header { - padding: 5px ! important; - } - - /* stop zoom on select */ - select:focus, - textarea, - input - { - font-size: 16px ! important; - } - +/** Common layout **/ + +html { + height: 100%; } body { + height: 100%; font-family: "Myriad Pro", "Myriad", Helvetica, Arial, sans-serif; font-size: 12pt; margin: 0px; } h1 { - font-family: Helvetica, Arial, sans-serif; + font-size: 20pt; } -/*** Overall page layout ***/ +a:link { color: #666; } +a:visited { color: #666; } +a:hover { color: #000; } +a:active { color: #000; } #page { - position: absolute; - top: 80px; - bottom: 100px; - left: 0px; - right: 0px; - margin: 20px; + min-height: 100%; + margin-bottom: -32px; /* to make room for the footer */ } #wrapper { margin: auto; max-width: 1280px; height: 100%; + padding-top: 40px; + padding-bottom: 40px; + padding-left: 20px; + padding-right: 20px; } -#roomName { +#header +{ + position: absolute; + top: 0px; + width: 100%; + background-color: #333; + height: 32px; +} + +#headerContent { + color: #ccc; max-width: 1280px; + margin: auto; + text-align: right; + height: 32px; + line-height: 32px; +} + +#headerContent a:link, +#headerContent a:visited, +#headerContent a:hover, +#headerContent a:active { + color: #fff; +} + +#footer +{ width: 100%; + border-top: #666 1px solid; + background-color: #aaa; + height: 32px; +} + +#footerContent +{ + font-size: 8pt; + color: #fff; + max-width: 1280px; + margin: auto; + text-align: center; + height: 32px; + line-height: 32px; +} + +#genericHeading +{ + margin-top: 13px; +} + +#feedback { + color: #800; +} + +.mouse-pointer { + cursor: pointer; +} + +.invited { + opacity: 0.2; +} + +/*** Login Pages ***/ + +.loginWrapper { + text-align: center; +} + +#loginForm { + text-align: left; + padding: 1em; + margin-bottom: 40px; + display: inline-block; + + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; + + -webkit-box-shadow: 0px 0px 20px 0px rgba(0,0,0,0.15); + -moz-box-shadow: 0px 0px 20px 0px rgba(0,0,0,0.15); + box-shadow: 0px 0px 20px 0px rgba(0,0,0,0.15); + + background-color: #f8f8f8; + border: 1px #ccc solid; +} + +#loginForm input[type='radio'] { + margin-right: 1em; +} + +#serverConfig { + text-align: center; +} + +#serverConfig, +#serverConfig input, +#serverConfig button +{ + font-size: 10pt ! important; +} + +.smallPrint { + color: #888; + font-size: 9pt ! important; + font-style: italic ! important; +} + +#serverConfig label { + display: inline-block; text-align: right; - top: -40px; + margin-right: 0.5em; + width: 7em; +} + +#loginForm, +#loginForm input, +#loginForm button, +#loginForm select { + font-size: 18px; +} + +/*** Room page ***/ + +#roomPage { position: absolute; + top: 120px; + bottom: 120px; + left: 20px; + right: 20px; +} + +#roomWrapper { + margin: auto; + max-width: 1280px; + height: 100%; +} + +#roomName { + float: right; font-size: 16px; + margin-top: 15px; +} + +#roomHeader { + margin: auto; + padding-left: 20px; + padding-right: 20px; + padding-top: 53px; + max-width: 1280px; } #controlPanel { position: absolute; bottom: 0px; width: 100%; + height: 100px; background-color: #f8f8f8; border-top: #aaa 1px solid; } @@ -147,10 +220,6 @@ h1 { background-color: #faa; } -.mouse-pointer { - cursor: pointer; -} - /*** Participant list ***/ #usersTableWrapper { @@ -409,11 +478,14 @@ h1 { } /*** Recents in the room page ***/ + #roomRecentsTableWrapper { float: left; max-width: 320px; - margin-right: 20px; + padding-right: 10px; + margin-right: 10px; height: 100%; + border-right: 1px solid #ddd; overflow-y: auto; } @@ -434,46 +506,8 @@ h1 { } /*** User profile page ***/ + #user-displayname { font-size: 24px; } -/******************************/ - -#header -{ - padding: 20px; - max-width: 1280px; - margin: auto; -} - -#logo, -#roomLogo { - max-width: 1280px; - margin: auto; -} - -#header-buttons { - float: right; -} - -.text_entry_section { - position: fixed; - bottom: 0; - z-index: 100; - left: 0; - right: 10em; - width: 100%; - background: #e0e0e0; -} - -.member_invited { - color: blue; -} -.member_joined { - -} - -.member_left { - color: gray; -} diff --git a/webclient/app.js b/webclient/app.js index 02695c3ae6..9663ddf967 100644 --- a/webclient/app.js +++ b/webclient/app.js @@ -18,6 +18,7 @@ var matrixWebClient = angular.module('matrixWebClient', [ 'ngRoute', 'MatrixWebClientController', 'LoginController', + 'RegisterController', 'RoomController', 'HomeController', 'RecentsController', @@ -38,6 +39,10 @@ matrixWebClient.config(['$routeProvider', '$provide', '$httpProvider', templateUrl: 'login/login.html', controller: 'LoginController' }). + when('/register', { + templateUrl: 'login/register.html', + controller: 'RegisterController' + }). when('/room/:room_id_or_alias', { templateUrl: 'room/room.html', controller: 'RoomController' @@ -84,7 +89,10 @@ matrixWebClient.config(['$routeProvider', '$provide', '$httpProvider', matrixWebClient.run(['$location', 'matrixService', function($location, matrixService) { // If user auth details are not in cache, go to the login page - if (!matrixService.isUserLoggedIn()) { + if (!matrixService.isUserLoggedIn() && + $location.path() !== "/login" && + $location.path() !== "/register") + { $location.path("login"); } diff --git a/webclient/components/matrix/matrix-service.js b/webclient/components/matrix/matrix-service.js index 8543491dca..746442c280 100644 --- a/webclient/components/matrix/matrix-service.js +++ b/webclient/components/matrix/matrix-service.js @@ -95,14 +95,18 @@ angular.module('matrixService', []) }, // Create a room - create: function(room_id, visibility) { + create: function(room_alias, visibility) { // The REST path spec var path = "/createRoom"; - return doRequest("POST", path, undefined, { - visibility: visibility, - room_alias_name: room_id - }); + var req = { + "visibility": visibility + }; + if (room_alias) { + req.room_alias_name = room_alias; + } + + return doRequest("POST", path, undefined, req); }, // List all rooms joined or been invited to diff --git a/webclient/home/home-controller.js b/webclient/home/home-controller.js index 438ffe1b0e..847918d5dc 100644 --- a/webclient/home/home-controller.js +++ b/webclient/home/home-controller.js @@ -58,14 +58,14 @@ angular.module('HomeController', ['matrixService', 'eventHandlerService', 'Recen ); }; - $scope.createNewRoom = function(room_id, isPrivate) { + $scope.createNewRoom = function(room_alias, isPrivate) { var visibility = "public"; if (isPrivate) { visibility = "private"; } - matrixService.create(room_id, visibility).then( + matrixService.create(room_alias, visibility).then( function(response) { // This room has been created. Refresh the rooms list console.log("Created room " + response.data.room_alias + " with id: "+ diff --git a/webclient/home/home.html b/webclient/home/home.html index 1b1c21d9d2..8d35eb5157 100644 --- a/webclient/home/home.html +++ b/webclient/home/home.html @@ -1,29 +1,24 @@
-
- + +
+ [matrix] +
+ +

Welcome to homeserver {{ config.homeserver }}

+
-
- - - - - -
-
- -
-
-
-
{{ profile.displayName }}
-
{{ config.user_id }}
-
-
-
+
+ +
+
+
{{ profile.displayName }}
+
{{ config.user_id }}
+
-

Recents

+

Recent conversations


@@ -38,9 +33,9 @@
- + private - +
@@ -54,5 +49,4 @@ {{ feedback }}
-
diff --git a/webclient/index.html b/webclient/index.html index fdc50a5212..3c31a8a051 100644 --- a/webclient/index.html +++ b/webclient/index.html @@ -4,6 +4,8 @@ [matrix] + + @@ -19,6 +21,7 @@ + @@ -38,16 +41,23 @@ - +
-
+
+ diff --git a/webclient/login/login-controller.js b/webclient/login/login-controller.js index 51f9a3bdf4..2b91926954 100644 --- a/webclient/login/login-controller.js +++ b/webclient/login/login-controller.js @@ -10,63 +10,26 @@ angular.module('LoginController', ['matrixService']) if ($location.port()) { hs_url += ":" + $location.port(); } + var example_domain = $location.host(); $scope.account = { homeserver: hs_url, + example_domain: example_domain, desired_user_name: "", user_id: "", password: "", - identityServer: "", + identityServer: "http://matrix.org:8090", pwd1: "", - pwd2: "" + pwd2: "", }; - - $scope.register = function() { - - // Set the urls - matrixService.setConfig({ - homeserver: $scope.account.homeserver, - identityServer: $scope.account.identityServer - }); - - if ($scope.account.pwd1 !== $scope.account.pwd2) { - $scope.feedback = "Passwords don't match."; - return; - } - else if ($scope.account.pwd1.length < 6) { - $scope.feedback = "Password must be at least 6 characters."; - return; - } - - matrixService.register($scope.account.desired_user_name, $scope.account.pwd1).then( - function(response) { - $scope.feedback = "Success"; - // Update the current config - var config = matrixService.config(); - angular.extend(config, { - access_token: response.data.access_token, - user_id: response.data.user_id - }); - matrixService.setConfig(config); - - // And permanently save it - matrixService.saveConfig(); - eventStreamService.resume(); - // Go to the user's rooms list page - $location.url("home"); - }, - function(error) { - if (error.data) { - if (error.data.errcode === "M_USER_IN_USE") { - $scope.feedback = "Username already taken."; - } - } - else if (error.status === 0) { - $scope.feedback = "Unable to talk to the server."; - } - }); + + $scope.login_types = [ "email", "mxid" ]; + $scope.login_type_label = { + "email": "Email address", + "mxid": "Matrix ID (e.g. @bob:matrix.org or bob)", }; - + $scope.login_type = 'mxid'; // TODO: remember the user's preferred login_type + $scope.login = function() { matrixService.setConfig({ homeserver: $scope.account.homeserver, diff --git a/webclient/login/login.html b/webclient/login/login.html index 4b2ea60928..8d5a53ebbc 100644 --- a/webclient/login/login.html +++ b/webclient/login/login.html @@ -1,55 +1,49 @@