SYWEB-152: Move up/down history fully to a directive.

Previously, there was some of it in a lovely generic directive, but the
core of it was hard coded id attributes in RoomController. It's now all
generic in a directive: the room history you get when you up/down arrow
is determined by the value of the attribute e.g. command-history="!foo:bar"
would present the history for !foo:bar. In practice, this is {{room_id}}
in the html.
This commit is contained in:
Kegan Dougal 2014-11-13 16:09:44 +00:00
parent 8d8a133c89
commit afd2e214bc
3 changed files with 101 additions and 94 deletions

View File

@ -414,7 +414,8 @@ angular.module('RoomController', ['ngSanitize', 'matrixFilter', 'mFileInput', 'a
scrollToBottom(true); scrollToBottom(true);
// Store the command in the history // Store the command in the history
history.push(input); $rootScope.$broadcast("commandHistory:BROADCAST_NEW_HISTORY_ITEM(item)",
input);
var isEmote = input.indexOf("/me ") === 0; var isEmote = input.indexOf("/me ") === 0;
var promise; var promise;
@ -625,9 +626,6 @@ angular.module('RoomController', ['ngSanitize', 'matrixFilter', 'mFileInput', 'a
// Make recents highlight the current room // Make recents highlight the current room
recentsService.setSelectedRoomId($scope.room_id); recentsService.setSelectedRoomId($scope.room_id);
// Init the history for this room
history.init();
// Get the up-to-date the current member list // Get the up-to-date the current member list
matrixService.getMemberList($scope.room_id).then( matrixService.getMemberList($scope.room_id).then(
function(response) { function(response) {
@ -746,84 +744,6 @@ angular.module('RoomController', ['ngSanitize', 'matrixFilter', 'mFileInput', 'a
$rootScope.currentCall = call; $rootScope.currentCall = call;
}; };
// Manage history of typed messages
// History is saved in sessionStoratge so that it survives when the user
// navigates through the rooms and when it refreshes the page
var history = {
// The list of typed messages. Index 0 is the more recents
data: [],
// The position in the history currently displayed
position: -1,
// The message the user has started to type before going into the history
typingMessage: undefined,
// Init/load data for the current room
init: function() {
var data = sessionStorage.getItem("history_" + $scope.room_id);
if (data) {
this.data = JSON.parse(data);
}
},
// Store a message in the history
push: function(message) {
this.data.unshift(message);
// Update the session storage
sessionStorage.setItem("history_" + $scope.room_id, JSON.stringify(this.data));
// Reset history position
this.position = -1;
this.typingMessage = undefined;
},
// Move in the history
go: function(offset) {
if (-1 === this.position) {
// User starts to go to into the history, save the current line
this.typingMessage = $('#mainInput').val();
}
else {
// If the user modified this line in history, keep the change
this.data[this.position] = $('#mainInput').val();
}
// Bounds the new position to valid data
var newPosition = this.position + offset;
newPosition = Math.max(-1, newPosition);
newPosition = Math.min(newPosition, this.data.length - 1);
this.position = newPosition;
if (-1 !== this.position) {
// Show the message from the history
$('#mainInput').val(this.data[this.position]);
}
else if (undefined !== this.typingMessage) {
// Go back to the message the user started to type
$('#mainInput').val(this.typingMessage);
}
}
};
// Make history singleton methods available from HTML
$scope.history = {
goUp: function($event) {
if ($scope.room_id) {
history.go(1);
}
$event.preventDefault();
},
goDown: function($event) {
if ($scope.room_id) {
history.go(-1);
}
$event.preventDefault();
}
};
$scope.openJson = function(content) { $scope.openJson = function(content) {
$scope.event_selected = angular.copy(content); $scope.event_selected = angular.copy(content);

View File

@ -144,19 +144,106 @@ angular.module('RoomController')
}); });
}; };
}]) }])
// A directive which stores text sent into it and restores it via up/down arrows
.directive('commandHistory', [ function() { .directive('commandHistory', [ function() {
return function (scope, element, attrs) { var BROADCAST_NEW_HISTORY_ITEM = "commandHistory:BROADCAST_NEW_HISTORY_ITEM(item)";
// Manage history of typed messages
// History is saved in sessionStorage so that it survives when the user
// navigates through the rooms and when it refreshes the page
var history = {
// The list of typed messages. Index 0 is the more recents
data: [],
// The position in the history currently displayed
position: -1,
element: undefined,
roomId: undefined,
// The message the user has started to type before going into the history
typingMessage: undefined,
// Init/load data for the current room
init: function(element, roomId) {
this.roomId = roomId;
this.element = element;
var data = sessionStorage.getItem("history_" + this.roomId);
if (data) {
this.data = JSON.parse(data);
}
},
// Store a message in the history
push: function(message) {
this.data.unshift(message);
// Update the session storage
sessionStorage.setItem("history_" + this.roomId, JSON.stringify(this.data));
// Reset history position
this.position = -1;
this.typingMessage = undefined;
},
// Move in the history
go: function(offset) {
if (-1 === this.position) {
// User starts to go to into the history, save the current line
this.typingMessage = this.element.val();
}
else {
// If the user modified this line in history, keep the change
this.data[this.position] = this.element.val();
}
// Bounds the new position to valid data
var newPosition = this.position + offset;
newPosition = Math.max(-1, newPosition);
newPosition = Math.min(newPosition, this.data.length - 1);
this.position = newPosition;
if (-1 !== this.position) {
// Show the message from the history
this.element.val(this.data[this.position]);
}
else if (undefined !== this.typingMessage) {
// Go back to the message the user started to type
this.element.val(this.typingMessage);
}
}
};
return {
restrict: "AE",
scope: {
roomId: "=commandHistory"
},
link: function (scope, element, attrs) {
element.bind("keydown", function (event) { element.bind("keydown", function (event) {
var keycodePressed = event.which; var keycodePressed = event.which;
var UP_ARROW = 38; var UP_ARROW = 38;
var DOWN_ARROW = 40; var DOWN_ARROW = 40;
if (scope.roomId) {
if (keycodePressed === UP_ARROW) { if (keycodePressed === UP_ARROW) {
scope.history.goUp(event); history.go(1);
event.preventDefault();
} }
else if (keycodePressed === DOWN_ARROW) { else if (keycodePressed === DOWN_ARROW) {
scope.history.goDown(event); history.go(-1);
event.preventDefault();
}
} }
}); });
scope.$on(BROADCAST_NEW_HISTORY_ITEM, function(ngEvent, item) {
history.push(item);
});
history.init(element, scope.roomId);
},
} }
}]) }])

View File

@ -251,7 +251,7 @@
<button id="attachButton" m-file-input="imageFileToSend" class="extraControls" ng-disabled="state.permission_denied"></button> <button id="attachButton" m-file-input="imageFileToSend" class="extraControls" ng-disabled="state.permission_denied"></button>
<textarea id="mainInput" rows="1" ng-enter="send()" <textarea id="mainInput" rows="1" ng-enter="send()"
ng-disabled="state.permission_denied" ng-disabled="state.permission_denied"
ng-focus="true" autocomplete="off" tab-complete command-history/> ng-focus="true" autocomplete="off" tab-complete command-history="room_id"/>
{{ feedback }} {{ feedback }}
<div ng-show="state.stream_failure"> <div ng-show="state.stream_failure">
{{ state.stream_failure.data.error || "Connection failure" }} {{ state.stream_failure.data.error || "Connection failure" }}