Special run, just for Lisa.
[webos-internals:skurriers-modifications.git] / messaging / messaging-poor-mans-twitter-client.patch
1 diff --git a/usr/palm/applications/com.palm.app.messaging/app/controllers/chatview-assistant.js b/usr/palm/applications/com.palm.app.messaging/app/controllers/chatview-assistant.js
2 index 71c2226..eeb4aec 100644
3 --- a/usr/palm/applications/com.palm.app.messaging/app/controllers/chatview-assistant.js
4 +++ b/usr/palm/applications/com.palm.app.messaging/app/controllers/chatview-assistant.js
5 @@ -2390,6 +2390,29 @@ var ChatviewAssistant = Class.create({
6                         this.addTextToClipboard(text);
7                 } else if (value === 'delete-cmd') {
8                         this.handleMessageDeleteFromContextMenu(messageId);
9 +               } else if (value === "twitter-retweet-cmd") {
10 +                       Mojo.Log.info("twitter-retweet-cmd");
11 +                       this.twitterRetweet(text);
12 +               } else if (value === "twitter-reply-cmd") {
13 +                       Mojo.Log.info("twitter-reply-cmd");
14 +                       this.twitterReply(text);
15 +               } else if (value === "twitter-direct-reply-cmd") {
16 +                       Mojo.Log.info("twitter-direct-reply-cmd");
17 +                       this.twitterDirectReply(text);
18 +               } else if (value === "twitter-leave-user-cmd") {
19 +                       Mojo.Log.info("twitter-leave-user-cmd");
20 +                       this.twitterLeaveUser(text);
21 +               } else if (/^twitter-user:/.test(value)) {
22 +                       var username = RegExp.rightContext;
23 +                       var url = "http://twitter.com/" + username;
24 +                       var params = {
25 +                               scene: "page",
26 +                               target: url
27 +                       };
28 +                       var request = new Mojo.Service.Request("palm://com.palm.applicationManager", {
29 +                               method: 'launch',
30 +                               parameters: {'id': "com.palm.app.browser", 'params': params}
31 +                       });
32                 } else if (value === 'view-error') {
33                         var future = MessagingDB.Messages.get(messageId);
34                         future.then(this, function() {
35 @@ -2400,6 +2423,230 @@ var ChatviewAssistant = Class.create({
36                         });
37                 }
38         },
39 +
40 +
41 +       twitterSkipChain: function (body) {
42 +               var originally_from, chainlink, result;
43 +               var modified = false;
44 +               Mojo.Log.info("twitterSkipChain(%j)", body);
45 +               while (true) {
46 +                       // skip past any RT/via chains.
47 +                       if (/^\s*rt(?:\s*@\s*|\s+)([_A-Za-z0-9]+)(?:\s*:\s*|\s+)/i.test(body)) {
48 +                               // RT@user:... (space optional before or after @ and :)
49 +                               // RT user ...
50 +                               chainlink       = RegExp.match;
51 +                               originally_from = RegExp.$1;
52 +                               body            = RegExp.rightContext;
53 +                               Mojo.Log.info("twitterSkipChain: skipping 'RT' chain link: %j", chainlink);
54 +                               modified = true;
55 +                       }
56 +                       else if (/^\s*(?:[\(\[\{]\s*)?via(?:\s*@\s*|\s+)[_A-Za-z0-9]+(?:\s*[\)\]\}])?(?:\s*:\s*|\s+)/i.test(body)) {
57 +                               // (via@user):...
58 +                               //  via user  ...
59 +                               chainlink = RegExp.match;
60 +                               body      = RegExp.rightContext;
61 +                               Mojo.Log.info("twitterSkipChain: skipping 'via' chain link: %j", chainlink);
62 +                               modified = true;
63 +                       }
64 +                       else {
65 +                               break;
66 +                       }
67 +               }
68 +               if (modified) {
69 +                       result = {
70 +                               body: body,
71 +                               originally_from: originally_from
72 +                       };
73 +               }
74 +               Mojo.Log.info("twitterSkipChain: returning %j", result);
75 +               return result;
76 +       },
77 +
78 +       twitterParseMessage: function (text) {
79 +               var from, originally_from, body, chain, result, match;
80 +               var mentioned = {};
81 +               var theMentioned = [];
82 +               var addMention = function (username) {
83 +                       Mojo.Log.info("ADDMENTION: %s", username);
84 +                       var usernameLower = username.toLowerCase();
85 +                       Mojo.Log.info("ADDMENTION: %s", usernameLower);
86 +                       if (!(usernameLower in mentioned)) {
87 +                               Mojo.Log.info(":)");
88 +                               mentioned[usernameLower] = true;
89 +                               theMentioned.push(username);
90 +                       }
91 +               };
92 +               Mojo.Log.info("twitterParseMessage(%j)", text);
93 +               if (/^Direct from (\S+):\s*(.*)/i.test(text)) {
94 +                       from = RegExp.$1;
95 +                       body = RegExp.$2;
96 +                       result = {
97 +                               direct: true,
98 +                               from: from,
99 +                               body: body,
100 +                               mentioned: theMentioned
101 +                       };
102 +                       addMention(from);
103 +               }
104 +               else if (/^(\S+):\s*(.*)/.test(text)) {
105 +                       from = RegExp.$1;
106 +                       originally_from = from;
107 +                       body = RegExp.$2;
108 +                       chain = this.twitterSkipChain(body);
109 +                       if (chain) {
110 +                               if ("originally_from" in chain) {
111 +                                       originally_from = chain.originally_from;
112 +                               }
113 +                               body = chain.body;
114 +                       }
115 +                       result = {
116 +                               direct: false, 
117 +                               from: from,
118 +                               originally_from: originally_from,
119 +                               body: body,
120 +                               mentioned: theMentioned
121 +                       };
122 +                       addMention(from);
123 +                       addMention(originally_from);
124 +               }
125 +
126 +               var match;
127 +               var rx_user = /\@([_A-Za-z0-9]+)/g;
128 +               while ((match = rx_user.exec(text)) !== null) {
129 +                       addMention(match[1]);
130 +               }
131 +
132 +               Mojo.Log.info("twitterParseMessage: returning %j", result);
133 +               return result;
134 +       },
135 +
136 +       twitterRetweet: function (text) {
137 +               Mojo.Log.info("twitterRetweet(%j)", text);
138 +               var tweet = this.twitterParseMessage(text);
139 +               if (tweet) {
140 +                       Mojo.Log.info("twitterRetweet: is an actionable tweet.");
141 +                       if (tweet.direct) {
142 +                               this.twitterErrorDialog("You cannot retweet a direct message.");
143 +                       }
144 +                       else {
145 +                               if (tweet.originally_from === tweet.from) {
146 +                                       this.twitterSetTextFieldValue(
147 +                                               "RT @" + tweet.originally_from + ": " + tweet.body
148 +                                       );
149 +                               }
150 +                               else {
151 +                                       this.twitterSetTextFieldValue(
152 +                                               "RT @" + tweet.originally_from +
153 +                                                       " via @" + tweet.from + ": " + tweet.body
154 +                                       );
155 +                               }
156 +                       }
157 +               }
158 +               else {
159 +                       Mojo.Log.info("twitterRetweet: is not an actionable tweet.");
160 +               }
161 +       },
162 +
163 +       twitterErrorDialog: function (error) {
164 +               this.controller.showAlertDialog({
165 +                       onChoose: function () { },
166 +                       title: $L("Error"),
167 +                       message: $L(error),
168 +                       preventCancel: false,
169 +                       choices: [{ label: $L('Dismiss'), value: 'Dismiss' }]
170 +               });
171 +       },
172 +       
173 +       twitterWarningDialog: function (warning) {
174 +               this.controller.showAlertDialog({
175 +                       onChoose: function () { },
176 +                       title: $L("Warning"),
177 +                       message: $L(warning),
178 +                       preventCancel: false,
179 +                       choices: [{ label: $L('OK'), value: 'OK' }]
180 +               });
181 +       },
182 +
183 +       twitterSetTextFieldValue: function (text) {
184 +               var self = this;
185 +               var value = this.messageTextElement.value;
186 +               if (/\S/.test(value)) {
187 +                       this.controller.showAlertDialog({
188 +                               onChoose: function (choice) {
189 +                                       if (choice) {
190 +                                               self.twitterSetTextFieldValueRaw(text);
191 +                                       }
192 +                               },
193 +                               title: "Erase existing message?",
194 +                               message: "Your current message:\n" + value,
195 +                               preventCancel: false,
196 +                               choices: [{ label: $L('Yes'), value: true },
197 +                                         { label: $L('No'),  value: false }]
198 +                       });
199 +               }
200 +               else {
201 +                       this.twitterSetTextFieldValueRaw(text);
202 +               }
203 +       },
204 +
205 +       twitterSetTextFieldValueRaw: function (text) {
206 +               this.setTextFieldValue(text);
207 +               this.moveCursorToEndOfTextField();
208 +               if (text.length > 140) {
209 +                       this.twitterWarningDialog("Your submission is longer than 140 characters. " + 
210 +                                                 "Please shorten before sending.");
211 +               }
212 +       },
213 +
214 +       twitterReply: function (text) {
215 +               Mojo.Log.info("twitterReply(%j)", text);
216 +               var tweet = this.twitterParseMessage(text);
217 +               if (tweet) {
218 +                       Mojo.Log.info("twitterReply: is an actionable tweet.");
219 +                       this.twitterSetTextFieldValue("@" + tweet.from + " ");
220 +               }
221 +               else {
222 +                       Mojo.Log.info("twitterReply: is not an actionable tweet.");
223 +               }
224 +       },
225 +       
226 +       twitterDirectReply: function (text) {
227 +               Mojo.Log.info("twitterDirectReply(%j)", text);
228 +               var tweet = this.twitterParseMessage(text);
229 +               if (tweet) {
230 +                       Mojo.Log.info("twitterReply: is an actionable tweet.");
231 +                       this.twitterSetTextFieldValue("D " + tweet.from + " ");
232 +               }
233 +               else {
234 +                       Mojo.Log.info("twitterReply: is not an actionable tweet.");
235 +               }
236 +       },
237 +       
238 +       twitterLeaveUser: function (text) {
239 +               Mojo.Log.info("twitterLeaveUser(%j)", text);
240 +               var tweet = this.twitterParseMessage(text);
241 +               if (tweet) {
242 +                       Mojo.Log.info("twitterLeaveUser: is an actionable tweet.");
243 +                       if (tweet.direct) {
244 +                               this.twitterSetTextFieldValue("leave " + tweet.from);
245 +                       }
246 +                       else {
247 +                               this.twitterSetTextFieldValue("leave " + tweet.from);
248 +                       }
249 +               }
250 +               else {
251 +                       Mojo.Log.info("twitterLeaveUser: is not an actionable tweet.");
252 +               }
253 +       },
254 +
255 +       moveCursorToEndOfTextField: function () {
256 +               var widget = this.controller.get('messageTextWidget');
257 +               if (widget) {
258 +                       widget = widget.mojo;
259 +               }
260 +               var len = widget.getValue().length;
261 +               widget.setCursorPosition(len, len);
262 +       },
263         
264         /**
265          * context menu handler for tap on MMS in chat list
266 @@ -2518,6 +2765,41 @@ var ChatviewAssistant = Class.create({
267                                 if(deliveryReceiptMsg !== undefined) {
268                                         popupItems = [{label: $L(deliveryReceiptMsg), command: '', disabled: true}];
269                                 }
270 +                               var menuItems = [
271 +                                       {label: $L('Forward'), command: 'forward-cmd'},
272 +                                       {label: $L('Forward Via Email'), command: 'forward-as-email-cmd'},
273 +                                       {label: $L('Copy Text'), command: 'copy-cmd'},
274 +                                       {label: $L('Delete'), command: 'delete-cmd'}
275 +                               ];
276 +                               var lcDisplayName = this.chatDisplayName.toLowerCase();
277 +                               if (lcDisplayName === "twitter" ||
278 +                                   lcDisplayName === "40404") {
279 +                                       var text = event.item.textForCopying;
280 +                                       Mojo.Log.info("MOO");
281 +                                       var tweet = this.twitterParseMessage(text);
282 +                                       if (tweet) {
283 +                                               if (tweet.direct) {
284 +                                                       menuItems.push({ label: $L('DM Reply'),
285 +                                                                        command: 'twitter-direct-reply-cmd' });
286 +                                               }
287 +                                               else {
288 +                                                       menuItems.push({ label: $L('Retweet'),
289 +                                                                        command: 'twitter-retweet-cmd' });
290 +                                                       menuItems.push({ label: $L('Tweet Reply'),
291 +                                                                        command: 'twitter-reply-cmd' });
292 +                                                       menuItems.push({ label: $L('DM Reply'),
293 +                                                                        command: 'twitter-direct-reply-cmd' });
294 +                                               }
295 +                                               menuItems.push({ label: $L('Leave User'),
296 +                                                                command: 'twitter-leave-user-cmd' });
297 +                                               tweet.mentioned.forEach(function (username) {
298 +                                                       menuItems.push({
299 +                                                               label: "@" + username,
300 +                                                               command: 'twitter-user:' + username
301 +                                                       });
302 +                                               });
303 +                                       }
304 +                               }
305                                 popupItems = popupItems.concat([
306                                         {label: $L('Forward'), command: 'forward-cmd'},
307                                         {label: $L('Forward Via Email'), command: 'forward-as-email-cmd'},
308 @@ -2530,7 +2812,7 @@ var ChatviewAssistant = Class.create({
309                                 this.controller.popupSubmenu({
310                                         onChoose: this.handleContextMenuSelectSmsIm.bind(this, event.item.textForCopying, messageId, event.index),
311                                         placeNear: eventTarget.target,
312 -                                       items: popupItems
313 +                                       items: menuItems
314                                 });
315                         }
316                 }