... | ... |
@@ -143,6 +143,9 @@ this.App = |
143 | 143 |
setHistory: (me, chatId, attendant, state, onSuccess) -> |
144 | 144 |
App.Com.trigger(event: 'app.chat.setHistorySaving', data: {me: me, chatId: chatId, attendant: attendant, enable: state}, success: onSuccess) |
145 | 145 |
|
146 |
+ loadHistory: (me, chatId, attendant, step, onSuccess) -> |
|
147 |
+ App.Com.trigger(event: 'app.chat.loadHistory', data: {me: me, chatId: chatId, attendant: attendant, step: step}, success: onSuccess) |
|
148 |
+ |
|
146 | 149 |
_setupBackboneComponents: -> |
147 | 150 |
App.Collections.contacts = new Xmpp.Collections.ContactsCollection() |
148 | 151 |
App.Collections.chats = new Xmpp.Collections.ChatsCollection() |
... | ... |
@@ -100,6 +100,5 @@ class Xmpp.Collections.ChatsCollection extends Backbone.Collection |
100 | 100 |
@activeChat = null |
101 | 101 |
@models = _.without(@openedChats, chat) |
102 | 102 |
|
103 |
- createTempContact: (jid) -> |
|
104 |
- newTempContact = new Xmpp.Models.Contact(jid: jid, belongsTo: [App.Models.me]) |
|
105 |
- newTempContact |
|
106 | 103 |
\ No newline at end of file |
104 |
+ @createTempContact: (jid) -> |
|
105 |
+ new Xmpp.Models.Contact(id: jid, jid: jid, belongsTo: [App.Models.me]) |
|
107 | 106 |
\ No newline at end of file |
... | ... |
@@ -1,6 +1,6 @@ |
1 | 1 |
.conversation.clear.border |
2 | 2 |
.history-settings |
3 |
- %a.left{href: '#'} #{I18n.t('chat.history.load')} |
|
3 |
+ %a.left.load-history{href: '#'} #{I18n.t('chat.history.load')} |
|
4 | 4 |
|
5 | 5 |
%input.hidden{ type: 'checkbox', name: 'enable-history', value: '1', id: 'ihistory', checked: 'checked'} |
6 | 6 |
%label.right.action.enabled{ for: 'ihistory' } #{I18n.t('chat.history.disable')} |
... | ... |
@@ -7,10 +7,12 @@ class Xmpp.Views.Chat.WindowView extends Backbone.View |
7 | 7 |
|
8 | 8 |
maxHistoryLength: 20 |
9 | 9 |
savingHistory: true |
10 |
+ historyStep: 0 |
|
10 | 11 |
|
11 | 12 |
events: |
12 | 13 |
'submit #msg-writer': (e) -> @sendMessage(e) |
13 | 14 |
'change .history-settings input': 'changeHistorySettings' |
15 |
+ 'click .history-settings .load-history': 'loadHistory' |
|
14 | 16 |
|
15 | 17 |
initialize: (options) -> |
16 | 18 |
_.bindAll(this) |
... | ... |
@@ -18,12 +20,15 @@ class Xmpp.Views.Chat.WindowView extends Backbone.View |
18 | 18 |
@tab = options.tab |
19 | 19 |
|
20 | 20 |
chatId = @tab.getChatId() |
21 |
- attendant = if not chatId then @tab.getAttendant().getPreferredResource() else null |
|
21 |
+ attendant = if not chatId then @tab.getAttendant().get('jid') else null |
|
22 |
+ |
|
22 | 23 |
App.Com.checkSavingHistory(App.Models.me.get('jid'), chatId, attendant, (canSave) => |
23 | 24 |
@savingHistory = canSave |
24 | 25 |
@_changeHistoryVisibly(@savingHistory) |
25 | 26 |
) |
26 | 27 |
|
28 |
+ @loadHistory() |
|
29 |
+ |
|
27 | 30 |
render: -> |
28 | 31 |
historyStackHtml = _.map(@historyStack, (view) -> |
29 | 32 |
view.render().el.outerHTML |
... | ... |
@@ -87,11 +92,14 @@ class Xmpp.Views.Chat.WindowView extends Backbone.View |
87 | 87 |
@log(messageView) |
88 | 88 |
Backbone.Events.trigger('resizeWorkspace') |
89 | 89 |
|
90 |
- log: (view) -> |
|
90 |
+ log: (view, isHistoryMessage) -> |
|
91 | 91 |
if (@historyStack.length + 1 >= @maxHistoryLength) |
92 | 92 |
@historyStack = @historyStack.slice(@historyStack.length - @maxHistoryLength + 1) |
93 | 93 |
|
94 |
- @historyStack.push(view) |
|
94 |
+ if not isHistoryMessage? || isHistoryMessage == false |
|
95 |
+ @historyStack.push(view) |
|
96 |
+ else |
|
97 |
+ @historyStack.unshift(view) |
|
95 | 98 |
|
96 | 99 |
changeHistorySettings: (e) -> |
97 | 100 |
$input = $(e.currentTarget) |
... | ... |
@@ -113,4 +121,29 @@ class Xmpp.Views.Chat.WindowView extends Backbone.View |
113 | 113 |
toDisable = '.enabled' |
114 | 114 |
|
115 | 115 |
$(@el).find(".action#{toEnable}, .current#{toEnable}").show() |
116 |
- $(@el).find(".action#{toDisable}, .current#{toDisable}").hide() |
|
117 | 116 |
\ No newline at end of file |
117 |
+ $(@el).find(".action#{toDisable}, .current#{toDisable}").hide() |
|
118 |
+ |
|
119 |
+ prependHistoryMessage: (user, date, msg) -> |
|
120 |
+ messageView = new Xmpp.Views.Chat.MessageView(user: user, date: date, message: msg, fromMe: user.get('jid') == App.Models.me.get('jid')) |
|
121 |
+ $(@el).find('.messages').prepend(messageView.render().el) |
|
122 |
+ @log(messageView, true) |
|
123 |
+ |
|
124 |
+ loadHistory: -> |
|
125 |
+ chatId = @tab.getChatId() |
|
126 |
+ attendant = if not chatId then @tab.getAttendant().get('jid') else null |
|
127 |
+ |
|
128 |
+ App.Com.loadHistory(App.Models.me.get('jid'), chatId, attendant, @historyStep, (result) => |
|
129 |
+ App.debug result |
|
130 |
+ |
|
131 |
+ _.each(result.history.reverse(), (message) => |
|
132 |
+ jid = App.stripJid(message.from) |
|
133 |
+ if App.Models.me.get('jid') == jid |
|
134 |
+ contact = App.Models.me |
|
135 |
+ else |
|
136 |
+ contact = App.Collections.contacts.findByJid(jid) || Xmpp.Collections.ChatsCollection.createTempContact(jid) |
|
137 |
+ |
|
138 |
+ @prependHistoryMessage(contact, new Date(message.created_at), message.message) |
|
139 |
+ ) |
|
140 |
+ |
|
141 |
+ @historyStep++ unless _.isEmpty(result.history) |
|
142 |
+ ) |
... | ... |
@@ -1,5 +1,7 @@ |
1 | 1 |
class WsChatController < WsController |
2 | 2 |
|
3 |
+ require 'message_builder' |
|
4 |
+ |
|
3 | 5 |
def start_polling_messages |
4 | 6 |
connection_store[:clients].each do |client| |
5 | 7 |
client.add_message_callback do |message| |
... | ... |
@@ -228,6 +230,19 @@ class WsChatController < WsController |
228 | 228 |
User.set_history_saving(save, me, attendant, chat_id) && trigger_success |
229 | 229 |
end |
230 | 230 |
|
231 |
+ def load_history |
|
232 |
+ me = message[:me] |
|
233 |
+ attendant = message[:attendant] |
|
234 |
+ chat_id = message[:chatId] |
|
235 |
+ page = message[:step] |
|
236 |
+ per_page = 10 |
|
237 |
+ |
|
238 |
+ trigger_failure unless find_client(me) |
|
239 |
+ |
|
240 |
+ history = History.page_history(me, attendant || chat_id, page, per_page) |
|
241 |
+ trigger_success history: history |
|
242 |
+ end |
|
243 |
+ |
|
231 | 244 |
private |
232 | 245 |
|
233 | 246 |
def process_incoming_message(from, me, body, chat_id = nil) |
... | ... |
@@ -24,4 +24,19 @@ class History |
24 | 24 |
|
25 | 25 |
history.save |
26 | 26 |
end |
27 |
+ |
|
28 |
+ def self.page_history(me, with, page, per_page) |
|
29 |
+ # Aggregation DSL: WIP (https://github.com/mongoid/origin/pull/59) |
|
30 |
+ History.collection.aggregate([ |
|
31 |
+ {'$match' => {me: me, _with: with}}, |
|
32 |
+ {'$limit' => 1}, |
|
33 |
+ {'$project' => {:messages => 1}}, |
|
34 |
+ {'$unwind' => '$messages'}, |
|
35 |
+ {'$sort' => {'messages.created_at' => -1}}, |
|
36 |
+ {'$skip' => page * per_page}, |
|
37 |
+ {'$limit' => per_page}, |
|
38 |
+ {'$sort' => {'messages.created_at' => 1}}, |
|
39 |
+ {'$project' => {message: '$messages.message', from: '$messages.from', created_at: '$messages.created_at'}} |
|
40 |
+ ]) |
|
41 |
+ end |
|
27 | 42 |
end |
... | ... |
@@ -72,6 +72,7 @@ WebsocketRails::EventMap.describe do |
72 | 72 |
subscribe :switchOwnership, to: WsChatController, with_method: :switch_ownership |
73 | 73 |
subscribe :canSaveHistory, to: WsChatController, with_method: :can_save_conversation? |
74 | 74 |
subscribe :setHistorySaving, to: WsChatController, with_method: :set_history_saving |
75 |
+ subscribe :loadHistory, to: WsChatController, with_method: :load_history |
|
75 | 76 |
end |
76 | 77 |
end |
77 | 78 |
end |