Skip to content
Permalink
Browse files

Merge pull request #31946 from julienw/1206727-dont-reload-thread-at-…

…change

Bug 1206727 - [Messages][Inbox] Don't reload the conversation node af…
  • Loading branch information
julienw committed Nov 25, 2015
2 parents 3ee7402 + a320c72 commit 4b595b02f0767ed86cb5c13d2c961fc84108579b
@@ -1019,6 +1019,7 @@
};

MockNavigatormozMobileMessage.send = function(number, text, success, error) {
var now = Date.now();
var sendId = messagesDb.id++;
var request = {
error: null
@@ -1116,7 +1117,7 @@
id: messagesDb.id++,
type: 'sms',
read: false,
timestamp: now,
timestamp: now + 1,
sentTimestamp: now - 100000,
threadId: thread.id
}
@@ -546,17 +546,17 @@ <h1 class="message-subject">
<span></span>
</label>
<a href="${hash}">
<aside role="note" data-l10n-id="${iconLabel}" class="icon icon-unread icon-draft"></aside>
<aside role="note" class="icon icon-unread icon-draft js-conversation-state"></aside>
<aside class="pack-end threadlist-item-picture"
role="img" aria-label="Contact photo"
data-l10n-id="contact-photo">
<span data-type="img"></span>
</aside>
<p class="threadlist-item-title"><bdi class="ellipsis-dir-fix">${number}</bdi></p>
<p class="threadlist-item-title"><bdi class="ellipsis-dir-fix"></bdi></p>
<p class="summary">
<time data-time-update="true" data-time-only="true" data-time="${timestamp}"></time>
<span class="mms-icon" data-l10n-id="mms-label">MMS</span>
<span dir="auto" class="body-text ellipsis-dir-fix">${bodyHTML}</span>
<span dir="auto" class="body-text js-conversation-body ellipsis-dir-fix"></span>
</p>
</a>
-->
@@ -168,7 +168,7 @@ <h1 id="threads-edit-mode" data-l10n-id="selectThreads-title"></h1>
data-l10n-id="contact-photo">
<span data-type="img"></span>
</aside>
<p class="threadlist-item-title"><bdi class="ellipsis-dir-fix">${number}</bdi></p>
<p class="threadlist-item-title"><bdi class="ellipsis-dir-fix"></bdi></p>
<p class="summary">
<time data-time-update="true" data-time-only="true" data-time="${timestamp}"></time>
<span class="mms-icon" data-l10n-id="mms-label">MMS</span>
@@ -251,6 +251,11 @@ var InboxView = {
titleContainer.replaceChild(groupTitle, title);
}

if (!title.textContent) {
// display something before waiting for findContact's result
title.textContent = threadNumbers[0];
}

if (threadNumbers.length === 1) {
return Utils.Promise.async(updateThreadNode)(threadNumbers[0]);
}
@@ -605,7 +610,9 @@ var InboxView = {
// Find draft-containing threads that have already been rendered
// and update them so they mark themselves appropriately
if (document.getElementById(`thread-${draft.threadId}`)) {
this.updateThread(Threads.get(draft.threadId));
this.updateThread(
Threads.get(draft.threadId), { conversationDraft: true }
);
}
} else {
// Safely assume there is a threadless draft
@@ -697,77 +704,96 @@ var InboxView = {
});
},

createThread: function inbox_createThread(record) {
// Create DOM element
var li = document.createElement('li');
var timestamp = +record.timestamp;
var type = record.lastMessageType;
var participants = record.participants;
var number = participants[0];
/**
* This method is responsible for adding or updating the data that could
* change in a node that's not moving in the same time.
*
* @param {Node} node The Node to update.
* @param {Object} record An object that holds the conversation informations.
*/
updateConversationContent(node, record) {
var id = record.id;
var bodyHTML = record.body;
var thread = Threads.get(id);
var iconLabel = '';

// A new conversation "is" a draft
var thread = Threads.get(id);
var isDraft = thread.isDraft;

// A an existing conversation has draft.
var draft = thread.getDraft();

if (!isDraft && draft) {
// If the draft is newer than the message, update
// the body with the draft content's first string.
if (draft.timestamp >= record.timestamp) {
bodyHTML = draft.content.find(function(content) {
if (typeof content === 'string') {
return true;
}
});
type = draft.type;
}
}
var body = record.body;
var type = record.lastMessageType;

bodyHTML = Template.escape(bodyHTML || '');
var iconLabel = '';

li.id = 'thread-' + id;
li.dataset.threadId = id;
li.dataset.time = timestamp;
li.dataset.lastMessageType = type;
li.classList.add('threadlist-item');
// If the draft is newer than the message, update
// the body with the draft content's first string.
if (draft && draft.timestamp >= record.timestamp) {
body = draft.content.find((content) => typeof content === 'string');
type = draft.type;
}

node.dataset.lastMessageType = type;

if (draft) {
// Set the "draft" visual indication
li.classList.add('draft');
node.classList.add('draft');

if (isDraft) {
li.dataset.draftId = draft.id;
li.classList.add('is-draft');
node.dataset.draftId = draft.id;
node.classList.add('is-draft');
iconLabel = 'is-draft';
} else {
li.classList.add('has-draft');
node.classList.add('has-draft');
iconLabel = 'has-draft';
}
} else {
// remove it
node.classList.remove('draft', 'has-draft', 'is-draft');
}

if (record.unreadCount > 0) {
li.classList.add('unread');
node.classList.add('unread');
iconLabel = 'unread-thread';
} else {
node.classList.remove('unread');
}

node.querySelector('.js-conversation-body').textContent = body || '';

var stateIndicator = node.querySelector('.js-conversation-state');
if (iconLabel) {
document.l10n.setAttributes(stateIndicator, iconLabel);
} else {
stateIndicator.removeAttribute('data-l10n-id');
}
},

createThread: function inbox_createThread(record) {
// Create DOM element
var li = document.createElement('li');
var timestamp = +record.timestamp;
var id = record.id;
var thread = Threads.get(id);
// A "new message" draft
var isDraft = thread.isDraft;
// An existing conversation's draft.
var draft = thread.getDraft();

li.id = 'thread-' + id;
li.dataset.threadId = id;
li.dataset.time = timestamp;
li.classList.add('threadlist-item');

// Render markup with thread data
li.innerHTML = this.tmpl.thread.interpolate({
hash: isDraft ? '#/composer' : '#/thread?id=' + id,
mode: isDraft ? 'drafts' : 'threads',
id: isDraft ? draft.id : id,
number: number,
bodyHTML: bodyHTML,
timestamp: String(timestamp),
iconLabel: iconLabel
timestamp: String(timestamp)
}, {
safe: ['id', 'bodyHTML']
safe: ['id']
});

this.updateConversationContent(li, record);

TimeHeaders.update(li.querySelector('time'));

return li;
@@ -803,7 +829,21 @@ var InboxView = {
}
},

updateThread: function inbox_updateThread(record, options) {
/**
* Update the DOM element for a conversation.
*
* @param {Record} record This contains the conversation informations.
* @param {Object} [options] Various options or hints to make the update more
* efficient.
* @param {Boolean} [options.conversationDraft] True if this update comes from
* a draft change for this thread. Will be false for "isDraft" conversation
* nodes.
* @param {Boolean} [options.deleted] True if this update comes from a message
* deletion.
* @param {Boolean} [options.unread] True if we have a new unread message in
* this conversation.
*/
updateThread(record, options = {}) {
var thread = Thread.create(record, options);
var threadUINode = document.getElementById('thread-' + thread.id);
var threadUITime = threadUINode ? +threadUINode.dataset.time : NaN;
@@ -812,23 +852,29 @@ var InboxView = {
Threads.set(thread.id, thread);

// Edge case: if we just received a message that is older than the latest
// one in the thread, we only need to update the 'unread' status.
var newMessageReceived = options && options.unread;
// one in the conversation, we only need to update the 'unread' status.
var newMessageReceived = options.unread;
if (newMessageReceived && threadUITime > recordTime) {
this.mark(thread.id, 'unread');
return;
}

// If we just deleted messages in a thread but kept the last message
// unchanged, we don't need to update the thread UI.
var messagesDeleted = options && options.deleted;
if (messagesDeleted && threadUITime === recordTime) {
// If we just deleted messages in a conversation but kept the last message
// unchanged, we don't need to update the conversation UI.
if (options.deleted && threadUITime === recordTime) {
return;
}

if (threadUINode && options.conversationDraft) {
// hasDraft drafts do not change the timestamps, so we can
// change the body and the type only.
this.updateConversationContent(threadUINode, record);
return;
}

// General case: update the thread UI.
// General case: update the conversation UI.
if (threadUINode) {
// remove the current thread node in order to place the new one properly
// remove the current node in order to place the new one properly.
this.removeConversationDOM(thread.id);
}

@@ -965,15 +1011,9 @@ var InboxView = {

mark: function inbox_mark(id, current) {
var li = document.getElementById('thread-' + id);
var remove = 'read';

if (current === 'read') {
remove = 'unread';
}

if (li) {
li.classList.remove(remove);
li.classList.add(current);
li.classList.toggle('unread', current === 'unread');
}
},

@@ -987,7 +1027,7 @@ var InboxView = {
if (thread.isDraft) {
this.deleteThread(thread.id);
} else {
this.updateThread(thread);
this.updateThread(thread, { conversationDraft: true });
}

// If the draft we scheduled notification for has been deleted, we shouldn't
@@ -998,8 +1038,13 @@ var InboxView = {
},

onDraftSaved: function inbox_onDraftSaved(draft) {
var threadToUpdate = draft.threadId ? Threads.get(draft.threadId) : draft;
this.updateThread(threadToUpdate);
if (draft.threadId) {
this.updateThread(
Threads.get(draft.threadId), { conversationDraft: true }
);
} else {
this.updateThread(draft);
}

// In case user saved draft when Inbox was not the active view, we want to
// notify that save operation successfully completed once user returns back

0 comments on commit 4b595b0

Please sign in to comment.
You can’t perform that action at this time.