fix message list height, add contact list dialog in new message page
[progetti-gl-como:friendica-messenger.git] / www / js / index.js
1
2
3 function url(endpoint){
4         return "https://" + app.settings.opts.user + ":" + app.settings.opts.pass + "@" + app.settings. opts.host + "/api/" + endpoint + "?callback=?"; 
5 }
6
7 /**
8  * Message List Object
9  */
10 function MessageList(sel_elm){
11         this.elm = $(sel_elm);
12 }
13
14
15 MessageList.prototype.update = function(clb){
16         $.getJSON(url("direct_messages"), {getText:"plain"}, function(data, status){
17                 //console.log(status);
18                 var senders = [];
19                 var out="";
20                 for (k in data) {
21                         var msg = data[k];
22                         if (senders.indexOf(msg.sender_screen_name)<0){
23                                 senders.push(msg.sender_screen_name);
24                                 out += "<li>";
25                                 out += "<aside class='pack'><img src='"+ msg.sender.profile_image_url + "'></aside>";
26                                 out += "<a href='#message/"+msg.sender_screen_name+"'>";
27                                 out += "<p>" + msg.text + "</p>";
28                                 out += "<p>" + msg.sender_screen_name + " - " + msg.created_at + "</p>";
29                                 out += "</a>";
30                                 out += "</li>";
31                         }
32                 }
33                 
34                 this.elm.html(out);
35                 
36                 if(clb) clb(data);
37                 
38         }.bind(this));
39 }
40
41
42 /**
43  * Conversation with a user
44  */
45 function Messages(sel_elm){
46         this.elm = $(sel_elm);
47         this.username = null;
48 }
49
50 Messages.prototype.update = function(username, clb) {
51         if (username) {
52                 this.username = username;
53         } else {
54                 username = this.username;
55         }
56         
57         if (!username) return;
58         
59         $("#contact_screen_name").html(username);
60         
61         $.getJSON(url("direct_messages/all"), {getText:"html", screen_name: username}, function(data, status){
62                 //console.log(data, status);
63                 data.reverse();
64                 var out="";
65                 var pack="";
66                 var reply_id; // id of the message to reply to. should be the last.
67                 for (k in data) {
68                         var msg = data[k];
69                         out += "<li>";
70                         pack = (msg.sender_screen_name==username ? "pack": "pack-end"); 
71                         out += "<aside class='"+pack+"'><img src='"+ msg.sender.profile_image_url + "'></aside>";
72                         //out += "<a href='#message/"+msg.sender_screen_name+"'>";
73                         out += "<p>" + msg.text + "</p>";
74                         out += "<p>" + msg.sender_screen_name + " - " + msg.created_at + "</p>";
75                         //out += "</a>";
76                         out += "</li>";
77                         reply_id = msg.id;
78                 }
79                 
80                 /* reply form */
81                 $(".message_text").val("");
82                 $(".message_to").val(username);
83                 $(".message_reply").val(reply_id);
84                 
85                 this.elm.html(out);
86                 if(clb) clb(data);
87         }.bind(this));
88         
89 }
90
91 /**
92  * Send Message
93  */
94 function Compose(sel_elm){
95         this.elm = $(sel_elm);
96         this.dialog = this.elm.find("#select_contact");
97         
98         this.contact_photo = this.elm.find(".contact_photo");
99         this.contact_photo_empty = this.contact_photo.attr("src");
100         
101         
102         this.friends = {};
103         this.last_update = 0;
104
105         
106         /* contact list dialog */
107         this.dialog.hide();
108         
109         this.contact_photo.on("click",function(e){
110                 var out="";
111                 for (k in this.friends) {
112                         var f = this.friends[k];
113                         out += "<button type='button' value='"+k+"' class='contact_item'><img src='"+f.profile_image_url+"'>"+f.name+" ("+f.screen_name+")</button>"
114                 }
115                 out += '<button type="button" class="cancel">Cancel</button>';
116                 
117                 this.dialog.find("menu").html(out);
118                 this.dialog.show();
119
120                 this.dialog.find(".contact_item").on("click", function(e){
121                         $(".message_to").val( $(e.target).val() );
122                         $(".message_to").trigger("input");
123                         this.dialog.hide();
124                 }.bind(this));
125                 
126                 this.dialog.find(".cancel").on("click", function(){
127                         this.dialog.hide();
128                 }.bind(this));
129                 
130         }.bind(this));
131         /* /contact list dialog */
132         
133         this.elm.find(".message_to").on('input', function(e){
134                 var f=$(e.target).val().trim();
135                 if (this.friends[f] !== undefined) {
136                         this.contact_photo.attr("src",this.friends[f].profile_image_url);
137                 } else {
138                         this.contact_photo.attr("src", this.contact_photo_empty);
139                 }
140         }.bind(this));
141 }
142
143 Compose.prototype.update = function(clb){
144         if (this.last_update > (new Date())-60000) {
145                 if (clb) clb(this.friends)
146                 return;
147         }
148         var dl = this.elm.find("#contacts");
149         
150         $.getJSON(url("statuses/friends"), {}, function(data, status) {
151                 var out="";
152                 this.friends = {};
153                 for (k in data){
154                         var friend = data[k];
155                         if (friend.network == "dfrn")
156                                 this.friends[friend.screen_name] = friend;
157                                 out += "<option value='"+friend.screen_name+"'>"+friend.name+" ("+friend.screen_name+")</option>";
158                 }
159                 this.last_update = (new Date()) - 0;
160                 dl.html(out);
161                 if (clb) clb(data);
162         }.bind(this));
163         
164 }
165
166 Compose.prototype.send = function(clb){
167         
168         var screen_name = $(".message_to").val().trim();
169         var replyto = $(".message_reply").val();
170         var text = $(".message_body").val();
171         if (text=="")
172                 text = $(".message_text").val();
173
174         if (text=="") {
175                 alert("Please enter the message body");
176                 return;
177         }
178         if (screen_name=="" || this.friends[screen_name]==undefined){
179                 alert("Please enter a valid recipient");
180                 return;
181         }
182         
183         /**
184                 WARNING: HACK AHEAD!
185
186                 Friendica doesn't set CORS headers (it should.. open a feature request!)
187                 We can't send post requests via ajax on different domains without it 
188                 (we can get with jsonp, wich is another hack, but standard...)
189                 We create an iframe, append it to body and create a form wich post data to
190                 remote server.
191                 We listen for 'load' event to know when the request returned data, so we
192                 can update the message list.
193                 We sould remove it when finished.
194                 We could read the content of the iframe before removeit as it would be json
195                 reply from API...
196         **/
197
198
199         var f = $("<iframe>").appendTo($("body")).hide();
200         
201         f.on('load', function() {
202                 if (clb){
203                         clb({
204                                 screen_name:screen_name,
205                                 replyto:replyto,
206                                 text:text
207                         });
208                 }
209         });
210         // we need a small timeout before we can write to iframe content
211         setTimeout( function() {
212                 var doc = f[0].contentWindow.document;
213                 // build the form
214                 var form = $("<form>").attr('action', url("direct_messages/new")).attr('method','POST').append(
215                                 $("<input>").attr('name','screen_name').val(screen_name)
216                         ).append(
217                                 $("<input>").attr('name','text').val(text)
218                         );
219                 if (replyto!=="") form.append(
220                         $("<input>").attr('name','replyto').val(replyto)        
221                 );
222                 $('body',doc).append(form);
223                 // send the form!
224                 form.submit();
225         }, 1 );
226 }
227
228 /**
229  * App settings
230  */
231 function Settings(sel_elm) {
232         this.elm = $(sel_elm);
233         this.update();
234         
235         
236         this.elm.find(".autoupdate").on("blur", function(e,b){ 
237                 this.set(e.target.id, $(e.target).val());
238         }.bind(this));
239 }
240         
241 Settings.prototype.update = function(clb) {
242         this.opts = JSON.parse( window.localStorage.getItem("opts") );
243         if (this.opts === null) this.opts={};
244
245         for (k in this.opts) {
246                 this.elm.find("#"+k).val(this.opts[k]);
247         }
248         if(clb) clb();
249 }
250         
251 Settings.prototype.is_valid = function() {
252         return this.opts !== null && 
253               this.opts.host !== undefined && this.opts.host !== "" && 
254               this.opts.user !== undefined && this.opts.user !== "" && 
255               this.opts.pass !== undefined && this.opts.pass !=="";
256 }
257         
258 Settings.prototype.set = function(name, value) {
259         this.opts[name] = value;
260         window.localStorage.setItem("opts", JSON.stringify(this.opts));
261 }
262
263
264
265 /**
266  * App Object
267  */
268 var app = {
269     // Application Constructor
270     initialize: function() {
271                 app.settings = new Settings("#settingsPage");
272                 app.messagelist = new MessageList("#messageList");
273                 app.messages    = new Messages("#messages");
274                 app.compose             = new Compose("#newMessagePage");
275                 
276                 routie({
277                         '': app.page_messageList,
278                         'settings' : app.page_settings,
279                         'compose'  : app.page_compose,
280                         'message/:user': app.page_messageUser
281                 });
282                 
283                 
284         this.bindEvents();
285     },
286         
287         page_messageList : function(){
288                 if (!app.settings.is_valid()) {
289                         /* alert("Please fill required settings"); */
290                         routie("settings");
291                         return;
292                 }
293                 app.messagelist.update(function(){
294                         if ($("body > .current").length>0) { 
295                                 $("body > .current").removeClass("current").addClass("right");
296                                 $("#inboxPage").addClass("current");
297                         }
298                 });
299         },
300         
301         page_messageUser : function(user) {
302
303                 app.messages.update(user, function(){
304                         
305                         var ofs = $("#messages li:last-of-type").offset()
306                         if (ofs !== null)
307                                 $("#messagePage .scrollable").scrollTop(ofs.top);
308                         
309                         $("#inboxPage").removeClass("current").addClass("left");
310                         $("#messagePage").removeClass("right").addClass("current");
311                 });
312         },
313         
314         page_settings : function() {
315                 app.settings.update(function(){
316                         $("#inboxPage").removeClass("current").addClass("left");
317                         $("#settingsPage").removeClass("right").addClass("current");
318                 });             
319         },
320         
321         page_compose : function() {
322                 $(".message_body").val("");
323                 $(".message_to").val("");
324                 $(".message_reply").val("");
325                 app.compose.contact_photo.attr("src", app.compose.contact_photo_empty);
326                 
327                 app.compose.update(function(){
328                         $("#inboxPage").removeClass("current").addClass("left");
329                         $("#newMessagePage").removeClass("right").addClass("current");
330                 });
331         },
332         
333     bindEvents: function() {
334         
335                 
336                 /* send reply */
337                 $("#reply_send").on("click", function(e){
338                         e.preventDefault();
339                         app.compose.send(function(){
340                                 app.messages.update();
341                         });
342                 });
343                 
344                 /* send new message */
345                 $("#message_send").on("click", function(e){
346                         e.preventDefault();
347                         app.compose.send(function(data){
348                                 // dovrebbe andare a message/data.screen_name
349                                 // ma per come รจ fatto al momento non funziona...
350                                 // torniamo alla lista messaggi
351                                 routie("");
352                         });
353                 });
354                 
355                 
356     }
357 };
358
359 $("progress").hide();
360 $.ajaxSettings.beforeSend = function() { $("progress").show(); }
361 $.ajaxSettings.complete = function() { $("progress").hide(); }
362
363
364 app.initialize();