Skip to content

Commit

Permalink
Merge pull request #4775 from wireapp/staging
Browse files Browse the repository at this point in the history
release 2018-10-02
  • Loading branch information
Gregor Herdmann authored Oct 2, 2018
2 parents eba198f + a8b8e34 commit b6eb7f9
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 111 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ deploy:
after_deploy:
- |
if [ "${TRAVIS_BRANCH}" == "staging" ] && [ "${TRAVIS_PULL_REQUEST}" == "false" ] && [ "${TRAVIS_EVENT_TYPE}" == "push" ]; then
yarn global add @wireapp/changelog-bot@0.4.25
yarn global add @wireapp/changelog-bot@1.0.24
wire-changelog-bot -e "${WIRE_WEBAPP_BOT_EMAIL}" -p "${WIRE_WEBAPP_BOT_PASSWORD}" -c "a720ce02-c44c-4981-936c-609380884231"
wire-changelog-bot -e "${WIRE_WEBAPP_BOT_EMAIL}" -p "${WIRE_WEBAPP_BOT_PASSWORD}" -c "4223f57f-0c8d-42fe-bf8a-908d680788ab" -m "Staging bump done! 🏁"
fi
4 changes: 2 additions & 2 deletions app/page/template/content/conversation/input-bar.htm
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
</div>

<!-- ko if: !conversationEntity().removed_from_conversation() -->
<div class="controls-center">
<div class="controls-center" data-bind="template: {afterRender: setElements}">
<textarea id="conversation-input-bar-text"
class="conversation-input-bar-text border-theme"
data-bind="event: {'keydown': onInputKeyDown, 'keyup': onInputKeyUp, 'select click': handleMentionFlow, 'input': updateMentions},
focus_on_keydown: true,
enter: onInputEnter,
hasFocus: hasFocus,
textInput: input,
resize: {triggerValue: input(), callback: scrollMessageList, syncElement: '.shadow-input'},
resize: {triggerValue: input, callback: scrollMessageList, syncElement: '.shadow-input', delayedResize: true},
click: onInputClick,
attr: {'placeholder': inputPlaceholder},
css: {'conversation-input-bar-text--accent': hasLocalEphemeralTimer()},
Expand Down
21 changes: 15 additions & 6 deletions app/script/components/mentionSuggestions.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,22 +79,25 @@ z.components.MentionSuggestions = class MentionSuggestions {
const actions = {
[z.util.KeyboardUtil.KEY.ARROW_UP]: this.moveSelection.bind(this, 1),
[z.util.KeyboardUtil.KEY.ARROW_DOWN]: this.moveSelection.bind(this, -1),
[z.util.KeyboardUtil.KEY.ENTER]: this.validateSelection.bind(this),
[z.util.KeyboardUtil.KEY.TAB]: this.validateSelection.bind(this),
[z.util.KeyboardUtil.KEY.ENTER]: this.validateSelection.bind(this, keyboardEvent),
[z.util.KeyboardUtil.KEY.TAB]: this.validateSelection.bind(this, keyboardEvent),
};

const action = actions[keyboardEvent.key];
if (action) {
action();
keyboardEvent.preventDefault();
keyboardEvent.stopPropagation();
const wasHandled = action();
if (wasHandled) {
keyboardEvent.preventDefault();
keyboardEvent.stopPropagation();
}
}
}

moveSelection(delta) {
const currentIndex = this.selectedSuggestionIndex();
const newIndex = z.util.NumberUtil.clamp(currentIndex + delta, 0, this.suggestions().length - 1);
this.selectedSuggestionIndex(newIndex);
return true;
}

onSuggestionClick(data, event) {
Expand All @@ -103,8 +106,14 @@ z.components.MentionSuggestions = class MentionSuggestions {
this.onSelectionValidated(data, this.targetInput);
}

validateSelection() {
validateSelection(keyboardEvent) {
const isShiftEnter = z.util.KeyboardUtil.isEnterKey(keyboardEvent) && keyboardEvent.shiftKey;
if (isShiftEnter) {
return false;
}

this.onSelectionValidated(this.selectedSuggestion(), this.targetInput);
return true;
}

updateScrollPosition(selectedNumber) {
Expand Down
11 changes: 6 additions & 5 deletions app/script/components/participantAvatar.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,16 @@ z.components.ParticipantAvatar = class ParticipantAvatar {
_loadAvatarPicture();
};

z.ui.ViewportObserver.addElement(componentInfo.element, _onInViewport);

this.pictureSubscription = this.participant().mediumPictureResource.subscribe(() => {
const _loadAvatarPictureIfVisible = () => {
if (this.avatarEnteredViewport) {
_loadAvatarPicture();
}
});
};

z.ui.ViewportObserver.addElement(componentInfo.element, _onInViewport);

this.participantSubscription = this.participant.subscribe(() => _loadAvatarPicture());
this.pictureSubscription = this.participant().mediumPictureResource.subscribe(_loadAvatarPictureIfVisible);
this.participantSubscription = this.participant.subscribe(_loadAvatarPictureIfVisible);
}

dispose() {
Expand Down
10 changes: 2 additions & 8 deletions app/script/conversation/EventMapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ z.conversation.EventMapper = class EventMapper {
try {
return this._mapJsonEvent(event, conversationEntity, createDummyImage);
} catch (error) {
const {conversation, from, type} = event;
const errorMessage =
'Failure while mapping event.' +
` Affected '${type}' event in '${conversation}' from '${from}': ${error.message}`;
const errorMessage = `Failure while mapping events. Affected '${event.type}' event: ${error.message}`;
this.logger.error(errorMessage, {error, event});

const customData = {eventTime: new Date(event.time).toISOString(), eventType: event.type};
Expand All @@ -78,10 +75,7 @@ z.conversation.EventMapper = class EventMapper {
if (isMessageNotFound) {
throw error;
}
const {conversation, from, type} = event;
const errorMessage =
'Failure while mapping event.' +
` Affected '${type}' event in '${conversation}' from '${from}': ${error.message}`;
const errorMessage = `Failure while mapping events. Affected '${event.type}' event: ${error.message}`;
this.logger.error(errorMessage, {error, event});

const customData = {eventTime: new Date(event.time).toISOString(), eventType: event.type};
Expand Down
2 changes: 1 addition & 1 deletion app/script/ui/ContextMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ z.ui.Context = (() => {
return _rotateItem(keyboardEvent.key);
}

if (z.util.KeyboardUtil.isEnterKey(z.util.KeyboardUtil.KEY.ENTER)) {
if (z.util.KeyboardUtil.isEnterKey(keyboardEvent)) {
_triggerItem();
}
};
Expand Down
8 changes: 6 additions & 2 deletions app/script/view_model/MainViewModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,9 @@ z.viewModel.MainViewModel = class MainViewModel {
const centerWidthOpen = centerWidthClose - MainViewModel.CONFIG.PANEL.WIDTH;

return new Promise(resolve => {
panel.addEventListener('transitionend', event => {
const transitionEndHandler = event => {
if (event.target === panel) {
panel.removeEventListener('transitionend', transitionEndHandler);
this._clearStyles(panel, ['width', 'transform', 'position', 'right', 'transition']);
this._clearStyles(titleBar, ['width', 'transition']);
this._clearStyles(input, ['width', 'transition']);
Expand All @@ -149,6 +150,7 @@ z.viewModel.MainViewModel = class MainViewModel {
overlay.addEventListener('click', this.closePanelOnClick);
}
window.dispatchEvent(new Event('resize'));

z.util.afterRender(() => {
const scrollToBottom = !isNarrowScreen && this.content.messageList.should_scroll_to_bottom;
if (scrollToBottom) {
Expand All @@ -157,7 +159,9 @@ z.viewModel.MainViewModel = class MainViewModel {
});
resolve();
}
});
};

panel.addEventListener('transitionend', transitionEndHandler);

if (isPanelOpen) {
this._applyStyle(panel, MainViewModel.PANEL_STYLE.OPEN);
Expand Down
111 changes: 49 additions & 62 deletions app/script/view_model/bindings/CommonBindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,76 +126,63 @@ ko.virtualElements.allowedBindings.stopBinding = true;
/**
* Resize textarea according to the containing text.
*/
ko.bindingHandlers.resize = (function() {
let lastHeight = null;
let triggerValue = null;
let callback = null;
let syncElement = null;

const resizeTextarea = _.throttle(element => {
element.style.height = 0;
const newStyleHeight = `${element.scrollHeight}px`;
element.style.height = newStyleHeight;

if (syncElement) {
syncElement.style.height = newStyleHeight;
}
ko.bindingHandlers.resize = {
init(element, valueAccessor, allBindings, data, context) {
const params = ko.unwrap(valueAccessor()) || {};

const currentHeight = element.clientHeight;
const callback = params.callback;
const syncElement = document.querySelector(params.syncElement);
const triggerValue = params.triggerValue;

if (lastHeight !== currentHeight) {
if (typeof callback === 'function') {
callback(currentHeight, lastHeight);
}
lastHeight = currentHeight;
const maxHeight = window.parseInt(getComputedStyle(element).maxHeight, 10);
let lastHeight = element.scrollHeight;

const isMaximumHeight = currentHeight >= maxHeight;
const newStyleOverflowY = isMaximumHeight ? 'scroll' : 'hidden';
element.style.overflowY = newStyleOverflowY;
const resizeTextarea = (textareaElement => {
textareaElement.style.height = 0;
const newStyleHeight = `${textareaElement.scrollHeight}px`;
textareaElement.style.height = newStyleHeight;

if (syncElement) {
syncElement.style.overflowY = newStyleOverflowY;
syncElement.style.height = newStyleHeight;
}
$(element).scroll();
}
}, 100);

return {
init(element, valueAccessor, allBindings, data, context) {
lastHeight = element.scrollHeight;
const params = ko.unwrap(valueAccessor()) || {};
triggerValue = params.triggerValue;
syncElement = document.querySelector(params.syncElement);
callback = params.callback;

if (triggerValue === undefined) {
return ko.applyBindingsToNode(
element,
{
event: {
focus() {
resizeTextarea(element);
},
input() {
resizeTextarea(element);
},
},
},
context
);
}
},
const currentHeight = textareaElement.clientHeight;

update(element, valueAccessor) {
const params = ko.unwrap(valueAccessor()) || {};
triggerValue = params.triggerValue;
syncElement = document.querySelector(params.syncElement);
callback = params.callback;
resizeTextarea(element);
},
};
})();
if (lastHeight !== currentHeight) {
if (typeof callback === 'function') {
callback(currentHeight, lastHeight);
}
lastHeight = currentHeight;
const maxHeight = window.parseInt(getComputedStyle(textareaElement).maxHeight, 10);

const isMaximumHeight = currentHeight >= maxHeight;
const newStyleOverflowY = isMaximumHeight ? 'scroll' : 'hidden';
textareaElement.style.overflowY = newStyleOverflowY;

if (syncElement) {
syncElement.style.overflowY = newStyleOverflowY;
}
$(textareaElement).scroll();
}
}).bind(null, element);
const throttledResizeTextarea = _.throttle(resizeTextarea, 100, {leading: !params.delayedResize});

throttledResizeTextarea();
if (triggerValue === undefined) {
return ko.applyBindingsToNode(
element,
{
event: {
focus: throttledResizeTextarea,
input: throttledResizeTextarea,
},
},
context
);
}
const valueSubscription = params.triggerValue.subscribe(throttledResizeTextarea);
ko.utils.domNodeDisposal.addDisposeCallback(element, () => valueSubscription.dispose());
},
};

/**
* Syncs scrolling to another element.
Expand Down
39 changes: 20 additions & 19 deletions app/script/view_model/content/InputBarViewModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,12 @@ z.viewModel.content.InputBarViewModel = class InputBarViewModel {
this.onDropFiles = this.onDropFiles.bind(this);
this.onPasteFiles = this.onPasteFiles.bind(this);
this.onWindowClick = this.onWindowClick.bind(this);
this.setElements = this.setElements.bind(this);
this.updateSelectionState = this.updateSelectionState.bind(this);

this.shadowInput = null;
this.textarea = null;

this.selectionStart = ko.observable(0);
this.selectionEnd = ko.observable(0);

Expand Down Expand Up @@ -137,12 +141,10 @@ z.viewModel.content.InputBarViewModel = class InputBarViewModel {
});

this.richTextInput.subscribe(() => {
const textarea = this.getTextArea();
const shadowInput = document.querySelector('.shadow-input');
if (textarea && shadowInput) {
if (this.textarea && this.shadowInput) {
z.util.afterRender(() => {
if (shadowInput.scrollTop !== textarea.scrollTop) {
shadowInput.scrollTop = textarea.scrollTop;
if (this.shadowInput.scrollTop !== this.textarea.scrollTop) {
this.shadowInput.scrollTop = this.textarea.scrollTop;
}
});
}
Expand Down Expand Up @@ -233,6 +235,11 @@ z.viewModel.content.InputBarViewModel = class InputBarViewModel {
});
}

setElements(nodes) {
this.textarea = nodes.find(node => node.id === 'conversation-input-bar-text');
this.shadowInput = nodes.find(node => node.classList && node.classList.contains('shadow-input'));
}

loadInitialStateForConversation(conversationEntity) {
this.conversationHasFocus(true);
this.pastedFile(null);
Expand Down Expand Up @@ -285,10 +292,6 @@ z.viewModel.content.InputBarViewModel = class InputBarViewModel {
return new z.message.MentionEntity(this.editedMention().startIndex, mentionLength, userEntity.id);
}

getTextArea() {
return document.querySelector('#conversation-input-bar-text');
}

addMention(userEntity, inputElement) {
const mentionEntity = this._createMentionEntity(userEntity);

Expand Down Expand Up @@ -357,9 +360,8 @@ z.viewModel.content.InputBarViewModel = class InputBarViewModel {
.mentions()
.slice();
this.currentMentions(newMentions);
const inputElement = this.getTextArea();
if (inputElement) {
this._moveCursorToEnd(inputElement);
if (this.textarea) {
this._moveCursorToEnd(this.textarea);
}
}
}
Expand Down Expand Up @@ -507,18 +509,17 @@ z.viewModel.content.InputBarViewModel = class InputBarViewModel {
}

handleMentionFlow() {
const {selectionStart, selectionEnd, value} = this.getTextArea();
const {selectionStart, selectionEnd, value} = this.textarea;
const mentionCandidate = this.getMentionCandidate(selectionStart, selectionEnd, value);
this.editedMention(mentionCandidate);
this.updateSelectionState();
}

updateSelectionState() {
const textarea = this.getTextArea();
if (!textarea) {
if (!this.textarea) {
return;
}
const {selectionStart, selectionEnd} = textarea;
const {selectionStart, selectionEnd} = this.textarea;
const defaultRange = {endIndex: 0, startIndex: Infinity};

const firstMention = this.findMentionAtPosition(selectionStart, this.currentMentions()) || defaultRange;
Expand All @@ -529,9 +530,9 @@ z.viewModel.content.InputBarViewModel = class InputBarViewModel {

const newStart = Math.min(mentionStart, selectionStart);
const newEnd = Math.max(mentionEnd, selectionEnd);
if (newStart !== textarea.selectionStart || newEnd !== textarea.selectionEnd) {
textarea.selectionStart = newStart;
textarea.selectionEnd = newEnd;
if (newStart !== selectionStart || newEnd !== selectionEnd) {
this.textarea.selectionStart = newStart;
this.textarea.selectionEnd = newEnd;
}
this.selectionStart(newStart);
this.selectionEnd(newEnd);
Expand Down
6 changes: 4 additions & 2 deletions app/script/view_model/content/MessageListViewModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -613,9 +613,11 @@ z.viewModel.content.MessageListViewModel = class MessageListViewModel {
handleClickOnMessage(messageEntity, event) {
const hasMentions = messageEntity.mentions().length;
const mentionElement = hasMentions && event.target.closest('.message-mention');
if (mentionElement) {
const userId = mentionElement && mentionElement.dataset.userId;

if (userId) {
this.userRepository
.get_user_by_id(mentionElement.dataset.userId)
.get_user_by_id(userId)
.then(userEntity => this.showUserDetails(userEntity))
.catch(error => {
if (error.type !== z.user.UserError.TYPE.USER_NOT_FOUND) {
Expand Down
Loading

0 comments on commit b6eb7f9

Please sign in to comment.