diff options
Diffstat (limited to 'webclient')
-rw-r--r-- | webclient/app.css | 10 | ||||
-rw-r--r-- | webclient/app.js | 13 | ||||
-rw-r--r-- | webclient/components/fileInput/file-input-directive.js | 5 | ||||
-rw-r--r-- | webclient/components/fileUpload/file-upload-service.js | 30 | ||||
-rw-r--r-- | webclient/components/matrix/matrix-service.js | 28 | ||||
-rw-r--r-- | webclient/index.html | 1 | ||||
-rw-r--r-- | webclient/room/room-controller.js | 64 | ||||
-rw-r--r-- | webclient/room/room.html | 10 | ||||
-rw-r--r-- | webclient/rooms/rooms-controller.js | 8 | ||||
-rw-r--r-- | webclient/rooms/rooms.html | 4 | ||||
-rw-r--r-- | webclient/user/user-controller.js | 38 | ||||
-rw-r--r-- | webclient/user/user.html | 30 |
12 files changed, 207 insertions, 34 deletions
diff --git a/webclient/app.css b/webclient/app.css index b9e7771ca8..869db69cd6 100644 --- a/webclient/app.css +++ b/webclient/app.css @@ -89,6 +89,7 @@ h1 { height: 100px; position: relative; background-color: #000; + cursor: pointer; } .userAvatar .userAvatarImage { @@ -251,6 +252,7 @@ h1 { height: 160px; display:table-cell; vertical-align: middle; + text-align: center; } .profile-avatar img { @@ -258,6 +260,14 @@ h1 { max-height: 100%; } +/*** User profile page ***/ +#user-ids { + padding-left: 1em; +} + +#user-displayname { + font-size: 16pt; +} /******************************/ #header { diff --git a/webclient/app.js b/webclient/app.js index 8d64db92d3..576912be46 100644 --- a/webclient/app.js +++ b/webclient/app.js @@ -20,6 +20,7 @@ var matrixWebClient = angular.module('matrixWebClient', [ 'LoginController', 'RoomController', 'RoomsController', + 'UserController', 'matrixService', 'eventStreamService', 'eventHandlerService', @@ -33,7 +34,13 @@ matrixWebClient.config(['$routeProvider', '$provide', '$httpProvider', templateUrl: 'login/login.html', controller: 'LoginController' }). - when('/room/:room_id', { + when('/room/:room_id_or_alias', { + templateUrl: 'room/room.html', + controller: 'RoomController' + }). + when('/room/', { // room URL with room alias in it (ex: http://127.0.0.1:8000/#/room/#public:localhost:8080) will come here. + // The reason is that 2nd hash key breaks routeProvider parameters cutting so that the URL will not match with + // the previous '/room/:room_id_or_alias' URL rule templateUrl: 'room/room.html', controller: 'RoomController' }). @@ -41,6 +48,10 @@ matrixWebClient.config(['$routeProvider', '$provide', '$httpProvider', templateUrl: 'rooms/rooms.html', controller: 'RoomsController' }). + when('/user/:user_matrix_id', { + templateUrl: 'user/user.html', + controller: 'UserController' + }). otherwise({ redirectTo: '/rooms' }); diff --git a/webclient/components/fileInput/file-input-directive.js b/webclient/components/fileInput/file-input-directive.js index 9b73f877e9..c5e4ae07a8 100644 --- a/webclient/components/fileInput/file-input-directive.js +++ b/webclient/components/fileInput/file-input-directive.js @@ -29,7 +29,7 @@ angular.module('mFileInput', []) scope: { selectedFile: '=mFileInput' }, - + link: function(scope, element, attrs, ctrl) { element.bind("click", function() { element.find("input")[0].click(); @@ -38,6 +38,9 @@ angular.module('mFileInput', []) scope.$apply(); }); }); + + // Change the mouse icon on mouseover on this element + element.css("cursor", "pointer"); } }; }); \ No newline at end of file diff --git a/webclient/components/fileUpload/file-upload-service.js b/webclient/components/fileUpload/file-upload-service.js index 5729d5da48..d620e6a4d0 100644 --- a/webclient/components/fileUpload/file-upload-service.js +++ b/webclient/components/fileUpload/file-upload-service.js @@ -16,11 +16,12 @@ 'use strict'; +// TODO determine if this is really required as a separate service to matrixService. /* * Upload an HTML5 file to a server */ angular.module('mFileUpload', []) -.service('mFileUpload', ['$http', '$q', function ($http, $q) { +.service('mFileUpload', ['matrixService', '$q', function (matrixService, $q) { /* * Upload an HTML5 file to a server and returned a promise @@ -28,20 +29,19 @@ angular.module('mFileUpload', []) */ this.uploadFile = function(file) { var deferred = $q.defer(); - - // @TODO: This service runs with the do_POST hacky implementation of /synapse/demos/webserver.py. - // This is temporary until we have a true file upload service - console.log("Uploading " + file.name + "..."); - $http.post(file.name, file) - .success(function(data, status, headers, config) { - deferred.resolve(location.origin + data.url); - console.log(" -> Successfully uploaded! Available at " + location.origin + data.url); - }). - error(function(data, status, headers, config) { - console.log(" -> Failed to upload" + file.name); - deferred.reject(); - }); + console.log("Uploading " + file.name + "... to /matrix/content"); + matrixService.uploadContent(file).then( + function(response) { + var content_url = location.origin + "/matrix/content/" + response.data.content_token; + console.log(" -> Successfully uploaded! Available at " + content_url); + deferred.resolve(content_url); + }, + function(error) { + console.log(" -> Failed to upload " + file.name); + deferred.reject(error); + } + ); return deferred.promise; }; -}]); \ No newline at end of file +}]); diff --git a/webclient/components/matrix/matrix-service.js b/webclient/components/matrix/matrix-service.js index 3cd0aa674b..828396c866 100644 --- a/webclient/components/matrix/matrix-service.js +++ b/webclient/components/matrix/matrix-service.js @@ -54,13 +54,14 @@ angular.module('matrixService', []) params.access_token = config.access_token; + if (path.indexOf(prefixPath) !== 0) { + path = prefixPath + path; + } + return doBaseRequest(config.homeserver, method, path, params, data, undefined); }; var doBaseRequest = function(baseUrl, method, path, params, data, headers) { - if (path.indexOf(prefixPath) !== 0) { - path = prefixPath + path; - } return $http({ method: method, url: baseUrl + path, @@ -165,6 +166,16 @@ angular.module('matrixService', []) return doRequest("DELETE", path, undefined, undefined); }, + // Retrieves the room ID corresponding to a room alias + resolveRoomAlias:function(room_alias) { + var path = "/matrix/client/api/v1/ds/room/$room_alias"; + room_alias = encodeURIComponent(room_alias); + + path = path.replace("$room_alias", room_alias); + + return doRequest("GET", path, undefined, {}); + }, + sendMessage: function(room_id, msg_id, content) { // The REST path spec var path = "/rooms/$room_id/messages/$from/$msg_id"; @@ -309,6 +320,17 @@ angular.module('matrixService', []) return doBaseRequest(config.identityServer, "POST", path, {}, data, headers); }, + uploadContent: function(file) { + var path = "/matrix/content"; + var headers = { + "Content-Type": undefined // undefined means angular will figure it out + }; + var params = { + access_token: config.access_token + }; + return doBaseRequest(config.homeserver, "POST", path, params, file, headers); + }, + // start listening on /events getEventStream: function(from, timeout) { var path = "/events"; diff --git a/webclient/index.html b/webclient/index.html index 455eff4a13..51f6ff1f4d 100644 --- a/webclient/index.html +++ b/webclient/index.html @@ -16,6 +16,7 @@ <script src="login/login-controller.js"></script> <script src="room/room-controller.js"></script> <script src="rooms/rooms-controller.js"></script> + <script src="user/user-controller.js"></script> <script src="components/matrix/matrix-service.js"></script> <script src="components/matrix/event-stream-service.js"></script> <script src="components/matrix/event-handler-service.js"></script> diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js index b859f3d7e8..b585e338ed 100644 --- a/webclient/room/room-controller.js +++ b/webclient/room/room-controller.js @@ -108,8 +108,11 @@ angular.module('RoomController', ['ngSanitize']) function($scope, $http, $timeout, $routeParams, $location, matrixService, eventStreamService, eventHandlerService) { 'use strict'; var MESSAGES_PER_PAGINATION = 30; - $scope.room_id = $routeParams.room_id; - $scope.room_alias = matrixService.getRoomIdToAliasMapping($scope.room_id); + + // Room ids. Computed and resolved in onInit + $scope.room_id = undefined; + $scope.room_alias = undefined; + $scope.state = { user_id: matrixService.config().user_id, events_from: "END", // when to start the event stream from. @@ -144,7 +147,7 @@ angular.module('RoomController', ['ngSanitize']) if (document.hidden) { var notification = new window.Notification( ($scope.members[event.user_id].displayname || event.user_id) + - " (" + $scope.room_alias + ")", + " (" + ($scope.room_alias || $scope.room_id) + ")", // FIXME: don't leak room_ids here { "body": event.content.body, "icon": $scope.members[event.user_id].avatar_url, @@ -342,7 +345,57 @@ angular.module('RoomController', ['ngSanitize']) $scope.onInit = function() { // $timeout(function() { document.getElementById('textInput').focus() }, 0); console.log("onInit"); + + // Does the room ID provided in the URL? + var room_id_or_alias; + if ($routeParams.room_id_or_alias) { + room_id_or_alias = decodeURIComponent($routeParams.room_id_or_alias); + } + + if (room_id_or_alias && '!' === room_id_or_alias[0]) { + // Yes. We can start right now + $scope.room_id = room_id_or_alias; + $scope.room_alias = matrixService.getRoomIdToAliasMapping($scope.room_id); + onInit2(); + } + else { + // No. The URL contains the room alias. Get this alias. + if (room_id_or_alias) { + // The room alias was passed urlencoded, use it as is + $scope.room_alias = room_id_or_alias; + } + else { + // Else get the room alias by hand from the URL + // ie: extract #public:localhost:8080 from http://127.0.0.1:8000/#/room/#public:localhost:8080 + if (3 === location.hash.split("#").length) { + $scope.room_alias = "#" + location.hash.split("#")[2]; + } + else { + // In case of issue, go to the default page + console.log("Error: cannot extract room alias"); + $location.path("/"); + return; + } + } + + // Need a room ID required in Matrix API requests + console.log("Resolving alias: " + $scope.room_alias); + matrixService.resolveRoomAlias($scope.room_alias).then(function(response) { + $scope.room_id = response.data.room_id; + console.log(" -> Room ID: " + $scope.room_id); + + // Now, we can start + onInit2(); + }, + function () { + // In case of issue, go to the default page + console.log("Error: cannot resolve room alias"); + $location.path("/"); + }); + } + }; + var onInit2 = function() { // Join the room matrixService.join($scope.room_id).then( function() { @@ -380,6 +433,11 @@ angular.module('RoomController', ['ngSanitize']) }); }; + // Open the user profile page + $scope.goToUserPage = function(user_id) { + $location.url("/user/" + user_id); + }; + $scope.leaveRoom = function() { matrixService.leave($scope.room_id).then( diff --git a/webclient/room/room.html b/webclient/room/room.html index 106a9dfd15..36bd95c1bb 100644 --- a/webclient/room/room.html +++ b/webclient/room/room.html @@ -10,9 +10,13 @@ <div id="usersTableWrapper"> <table id="usersTable"> <tr ng-repeat="member in members | orderMembersList"> - <td class="userAvatar"> - <img class="userAvatarImage" ng-src="{{member.avatar_url || 'img/default-profile.jpg'}}" width="80" height="80"/> - <img class="userAvatarGradient" src="img/gradient.png" width="80" height="24"/> + <td class="userAvatar" ng-click="goToUserPage(member.id)"> + <img class="userAvatarImage" + ng-src="{{member.avatar_url || 'img/default-profile.jpg'}}" + alt="{{ member.displayname || member.id.substr(0, member.id.indexOf(':')) }}" + title="{{ member.id }}" + width="80" height="80"/> + <img class="userAvatarGradient" src="img/gradient.png" title="{{ member.id }}" width="80" height="24"/> <div class="userName">{{ member.displayname || member.id.substr(0, member.id.indexOf(':')) }}<br/>{{ member.displayname ? "" : member.id.substr(member.id.indexOf(':')) }}</div> </td> <td class="userPresence" ng-class="member.presenceState === 'online' ? 'online' : (member.presenceState === 'unavailable' ? 'unavailable' : '')"> diff --git a/webclient/rooms/rooms-controller.js b/webclient/rooms/rooms-controller.js index da79c23d55..a237b59b4e 100644 --- a/webclient/rooms/rooms-controller.js +++ b/webclient/rooms/rooms-controller.js @@ -149,12 +149,8 @@ angular.module('RoomsController', ['matrixService', 'mFileInput', 'mFileUpload', $scope.joinAlias = function(room_alias) { matrixService.joinAlias(room_alias).then( function(response) { - if (response.data.hasOwnProperty("room_id")) { - $location.path("room/" + response.data.room_id); - return; - } else { - // TODO (erikj): Do something here? - } + // Go to this room + $location.path("room/" + room_alias); }, function(error) { $scope.feedback = "Can't join room: " + error.data; diff --git a/webclient/rooms/rooms.html b/webclient/rooms/rooms.html index 007ad29999..2602209bd3 100644 --- a/webclient/rooms/rooms.html +++ b/webclient/rooms/rooms.html @@ -65,7 +65,7 @@ <div class="rooms" ng-repeat="(rm_id, room) in rooms"> <div> - <a href="#/room/{{ rm_id }}" >{{ room.room_alias }}</a> {{room.membership === 'invite' ? ' (invited)' : ''}} + <a href="#/room/{{ room.room_alias ? room.room_alias : rm_id }}" >{{ room.room_alias }}</a> {{room.membership === 'invite' ? ' (invited)' : ''}} </div> </div> <br/> @@ -74,7 +74,7 @@ <div class="public_rooms" ng-repeat="room in public_rooms"> <div> - <a href="#/room/{{ room.room_id }}" >{{ room.room_alias }}</a> + <a href="#/room/{{ room.room_alias ? room.room_alias : room.room_id }}" >{{ room.room_alias }}</a> </div> </div> <br/> diff --git a/webclient/user/user-controller.js b/webclient/user/user-controller.js new file mode 100644 index 0000000000..620230561c --- /dev/null +++ b/webclient/user/user-controller.js @@ -0,0 +1,38 @@ +/* +Copyright 2014 matrix.org + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +'use strict'; + +angular.module('UserController', ['matrixService']) +.controller('UserController', ['$scope', '$routeParams', 'matrixService', + function($scope, $routeParams, matrixService) { + $scope.user = { + id: $routeParams.user_matrix_id, + displayname: "", + avatar_url: undefined + }; + + matrixService.getDisplayName($scope.user.id).then( + function(response) { + $scope.user.displayname = response.data.displayname; + } + ); + matrixService.getProfilePictureUrl($scope.user.id).then( + function(response) { + $scope.user.avatar_url = response.data.avatar_url; + } + ); +}]); \ No newline at end of file diff --git a/webclient/user/user.html b/webclient/user/user.html new file mode 100644 index 0000000000..47db09d1ee --- /dev/null +++ b/webclient/user/user.html @@ -0,0 +1,30 @@ +<div ng-controller="UserController" class="user"> + + <div id="page"> + <div id="wrapper"> + + <div> + <form> + <table> + <tr> + <td> + <div class="profile-avatar"> + <img ng-src="{{ user.avatar_url || 'img/default-profile.jpg' }}"/> + </div> + </td> + <td> + <div id="user-ids"> + <div id="user-displayname">{{ user.displayname }}</div> + <div>{{ user.id }}</div> + </div> + </td> + </tr> + </table> + </form> + </div> + + {{ feedback }} + + </div> + </div> +</div> |