merge small fixes
[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                 }
160                 this.last_update = (new Date()) - 0;
161                 dl.html(out);
162                 if (clb) clb(data);
163         }.bind(this));
164         
165 };
166
167 Compose.prototype.send = function(clb){
168         
169         var screen_name = $(".message_to").val().trim();
170         var replyto = $(".message_reply").val();
171         var text = $(".message_body").val();
172         if (text=="")
173                 text = $(".message_text").val();
174
175         if (text=="") {
176                 alert("Please enter the message body");
177                 return;
178         }
179         if (screen_name=="" || this.friends[screen_name]==undefined){
180                 alert("Please enter a valid recipient");
181                 return;
182         }
183         
184         /**
185                 WARNING: HACK AHEAD!
186
187                 Friendica doesn't set CORS headers (it should.. open a feature request!)
188                 We can't send post requests via ajax on different domains without it 
189                 (we can get with jsonp, wich is another hack, but standard...)
190                 We create an iframe, append it to body and create a form wich post data to
191                 remote server.
192                 We listen for 'load' event to know when the request returned data, so we
193                 can update the message list.
194                 We sould remove it when finished.
195                 We could read the content of the iframe before removeit as it would be json
196                 reply from API...
197         **/
198
199
200         var f = $("<iframe>").appendTo($("body")).hide();
201         
202         f.on('load', function() {
203                 if (clb){
204                         clb({
205                                 screen_name:screen_name,
206                                 replyto:replyto,
207                                 text:text
208                         });
209                 }
210         });
211         // we need a small timeout before we can write to iframe content
212         setTimeout( function() {
213                 var doc = f[0].contentWindow.document;
214                 // build the form
215                 var form = $("<form>").attr('action', url("direct_messages/new")).attr('method','POST').append(
216                                 $("<input>").attr('name','screen_name').val(screen_name)
217                         ).append(
218                                 $("<input>").attr('name','text').val(text)
219                         );
220                 if (replyto!=="") form.append(
221                         $("<input>").attr('name','replyto').val(replyto)        
222                 );
223                 $('body',doc).append(form);
224                 // send the form!
225                 form.submit();
226         }, 1 );
227 };
228
229 /**
230  * App settings
231  */
232 function Settings(sel_elm) {
233         this.elm = $(sel_elm);
234         this.update();
235         
236         
237         this.elm.find(".autoupdate").on("blur", function(e,b){ 
238                 this.set(e.target.id, $(e.target).val());
239         }.bind(this));
240 }
241         
242 Settings.prototype.update = function(clb) {
243         this.opts = JSON.parse( window.localStorage.getItem("opts") );
244         if (this.opts === null) this.opts={};
245
246         for (k in this.opts) {
247                 this.elm.find("#"+k).val(this.opts[k]);
248         }
249         if(clb) clb();
250 };
251         
252 Settings.prototype.is_valid = function() {
253         return this.opts !== null && 
254               this.opts.host !== undefined && this.opts.host !== "" && 
255               this.opts.user !== undefined && this.opts.user !== "" && 
256               this.opts.pass !== undefined && this.opts.pass !=="";
257 };
258         
259 Settings.prototype.set = function(name, value) {
260         this.opts[name] = value;
261         window.localStorage.setItem("opts", JSON.stringify(this.opts));
262 };
263
264
265
266 /**
267  * App Object
268  */
269 var app = {
270     // Application Constructor
271     initialize: function() {
272                 app.settings = new Settings("#settingsPage");
273                 app.messagelist = new MessageList("#messageList");
274                 app.messages    = new Messages("#messages");
275                 app.compose             = new Compose("#newMessagePage");
276                 
277                 routie({
278                         '': app.page_messageList,
279                         'settings' : app.page_settings,
280                         'compose'  : app.page_compose,
281                         'message/:user': app.page_messageUser
282                 });
283                 
284                 
285         this.bindEvents();
286     },
287         
288         page_messageList : function(){
289                 if (!app.settings.is_valid()) {
290                         /* alert("Please fill required settings"); */
291                         routie("settings");
292                         return;
293                 }
294                 app.messagelist.update(function(){
295                         if ($("body > .current").length>0) { 
296                                 $("body > .current").removeClass("current").addClass("right");
297                                 $("#inboxPage").addClass("current");
298                         }
299                 });
300         },
301         
302         page_messageUser : function(user) {
303
304                 app.messages.update(user, function(){
305                         
306                         var ofs = $("#messages li:last-of-type").offset();
307                         if (ofs !== null)
308                                 $("#messagePage .scrollable").scrollTop(ofs.top);
309                         
310                         $("#inboxPage").removeClass("current").addClass("left");
311                         $("#messagePage").removeClass("right").addClass("current");
312                 });
313         },
314         
315         page_settings : function() {
316                 app.settings.update(function(){
317                         $("#inboxPage").removeClass("current").addClass("left");
318                         $("#settingsPage").removeClass("right").addClass("current");
319                 });             
320         },
321         
322         page_compose : function() {
323                 $(".message_body").val("");
324                 $(".message_to").val("");
325                 $(".message_reply").val("");
326                 app.compose.contact_photo.attr("src", app.compose.contact_photo_empty);
327                 
328                 app.compose.update(function(){
329                         $("#inboxPage").removeClass("current").addClass("left");
330                         $("#newMessagePage").removeClass("right").addClass("current");
331                 });
332         },
333         
334     bindEvents: function() {
335         
336                 
337                 /* send reply */
338                 $("#reply_send").on("click", function(e){
339                         e.preventDefault();
340                         app.compose.send(function(){
341                                 app.messages.update();
342                         });
343                 });
344                 
345                 /* send new message */
346                 $("#message_send").on("click", function(e){
347                         e.preventDefault();
348                         app.compose.send(function(data){
349                                 // dovrebbe andare a message/data.screen_name
350                                 // ma per come รจ fatto al momento non funziona...
351                                 // torniamo alla lista messaggi
352                                 routie("");
353                         });
354                 });
355                 
356                 
357     }
358 };
359
360 $("progress").hide();
361 $.ajaxSettings.beforeSend = function() { $("progress").show(); }
362 $.ajaxSettings.complete = function() { $("progress").hide(); }
363
364
365 app.initialize();