Updates for all of my patches
[webos-internals:modifications.git] / advanced / advanced-system-prefs-msg-prefs-vzw.patch
1 --- .orig/usr/palm/applications/com.palm.app.messaging/app/models/MojoDbInterfaces.js
2 +++ /usr/palm/applications/com.palm.app.messaging/app/models/MojoDbInterfaces.js
3 @@ -958,29 +958,55 @@
4  //                     return isValid;
5  //             },
6                 
7 -               setCustomMessage: function(customMessage) {
8 +               setCustomMessage: function(customMessage, objectId) {
9                         Mojo.Log.info("Setting customMessage to %s", customMessage);
10 -                       var mergeObject = {
11 -                               props: {
12 -                                       customMessage: customMessage
13 -                               },
14 -                               query: {
15 -                                       from: MessagingDB.IMLoginState.id
16 -                               }
17 -                       };
18 +                       if(objectId) {
19 +                               var mergeObject = {
20 +                                       props: {
21 +                                               customMessage: customMessage
22 +                                       },
23 +                                       query: {
24 +                                               from: MessagingDB.IMLoginState.id,
25 +                                               where: [{ prop: "_id", op: "=", val: objectId }]
26 +                                       }
27 +                               };
28 +                       }
29 +                       else {
30 +                               var mergeObject = {
31 +                                       props: {
32 +                                               customMessage: customMessage
33 +                                       },
34 +                                       query: {
35 +                                               from: MessagingDB.IMLoginState.id
36 +                                       }
37 +                               };
38 +                       }
39                         return MojoDB.execute("merge", mergeObject);
40                 },
41  
42 -               setAvailability: function(availability) {
43 +               setAvailability: function(availability, objectId) {
44                         Mojo.Log.info("Setting availability to %s", availability);
45 -                       var mergeObject = {
46 -                               props: {
47 -                                       availability: availability
48 -                               },
49 -                               query: {
50 -                                       from: MessagingDB.IMLoginState.id
51 -                               }
52 -                       };
53 +                       if(objectId) {
54 +                               var mergeObject = {
55 +                                       props: {
56 +                                               availability: availability
57 +                                       },
58 +                                       query: {
59 +                                               from: MessagingDB.IMLoginState.id,
60 +                                               where: [{ prop: "_id", op: "=", val: objectId }]
61 +                                       }
62 +                               };
63 +                       }
64 +                       else {                  
65 +                               var mergeObject = {
66 +                                       props: {
67 +                                               availability: availability
68 +                                       },
69 +                                       query: {
70 +                                               from: MessagingDB.IMLoginState.id
71 +                                       }
72 +                               };
73 +                       }
74                         return MojoDB.execute("merge", mergeObject);
75                 },
76  
77 --- .orig/usr/palm/applications/com.palm.app.messaging/app/controllers/app-assistant.js
78 +++ /usr/palm/applications/com.palm.app.messaging/app/controllers/app-assistant.js
79 @@ -52,6 +52,8 @@
80                 }
81  
82                 var stageController = this.controller.getStageController(MainStageName);
83 +
84 +               this.appController.notificationAssistant.removePlayNotificationSoundTasks();
85                 
86                 if (launchParams.clearBanner) {
87                         PalmSystem.clearBannerMessages();
88 @@ -99,10 +101,20 @@
89                  */     
90                 } else if (launchParams.target !== undefined) {
91                         this.handleTargetParam(launchParams.target, stageController);
92 +               } else if (launchParams.playNotificationSound) {
93 +                       // Delay playing to go around WebOS bug (sound not playing).
94 +
95 +                       setTimeout(this.playNotificationSound.bind(this, launchParams.serviceName), 1000);
96                 } else {
97                         this.launchMessaging(stageController);
98                 }               
99         },
100 +
101 +       playNotificationSound: function(serviceName) {
102 +               this.appController.notificationAssistant.playNotificationSound(serviceName);
103 +                       
104 +               this.appController.notificationAssistant.schedulePlayNotificationSoundTasks(serviceName);
105 +       },
106         
107         launchChatWithId: function(stageController, chatThreadId) {
108                 if (stageController) {                  
109 --- .orig/usr/palm/applications/com.palm.app.messaging/app/views/listview/buddyList-row.html
110 +++ /usr/palm/applications/com.palm.app.messaging/app/views/listview/buddyList-row.html
111 @@ -7,7 +7,7 @@
112        <div class="unread-count-container">
113          <div class="unread-count-wrapper">#{unreadCount}</div>
114        </div>
115 -      <div class="truncating-text custom-message">#{-customMessage}</div>
116 +      <div class="custom-message">#{-customMessage}</div>
117      </div>
118    </div>
119  </div>
120 \ No newline at end of file
121 --- .orig/usr/palm/applications/com.palm.app.messaging/app/controllers/chatview-assistant.js
122 +++ /usr/palm/applications/com.palm.app.messaging/app/controllers/chatview-assistant.js
123 @@ -270,6 +270,16 @@
124                 this.newMessageFieldLoseFocus = function(event) {
125                         if (this.messageTextElement !== undefined) {
126                                 this.messageTextElement.focus();
127 +                               
128 +                               var msg = this.Messaging.messagingPrefs.getMessageGreeting() + " " + 
129 +                                       this.Messaging.messagingPrefs.getMessageSignature();
130 +
131 +                               if((msg.length > 1) && (this.messageTextWidgetModel.value == msg))
132 +                               {
133 +                                       var curPos = this.Messaging.messagingPrefs.getMessageGreeting().length;
134 +                                       this.setTextFieldValue(msg);
135 +                                       this.controller.get("messageTextWidget").mojo.setCursorPosition(curPos, curPos);
136 +                               }
137                         }
138                 }.bind(this);
139                 
140 @@ -394,7 +404,9 @@
141                                 labelCallback: this.chatListDividerFunction.bind(this),
142                                 template: 'chatview/separator'
143                         },
144 -                       swipeDelete: true,
145 +                       swipeDelete: {
146 +                               autoConfirm: !this.Messaging.messagingPrefs.getUseDeleteConfirmation()
147 +                       },
148                         uniquenessProperty: '_id',
149                         initialScrollingDirection: 'up',
150                         revisionProperty: '_rev',
151 @@ -1370,6 +1382,8 @@
152                         return;
153                 }
154                 
155 +               this.messageTextElement.focus();
156 +
157                 if (tapTarget && tapTarget.id.startsWith(ChatviewAssistant.quickDialIdPrefix)) {
158                         try {
159                                 // The phone number is the substring after the quick dial prefix.
160 @@ -1445,6 +1459,30 @@
161                                 this.resetTextBox(false);
162                         }
163                 }
164 +               
165 +               var msg = this.Messaging.messagingPrefs.getMessageGreeting() + " " + 
166 +                       this.Messaging.messagingPrefs.getMessageSignature();
167 +
168 +           // Hide the attach button if there is an IM contact
169 +           if(selectedTransport.serviceName != "sms") {  
170 +                       if((msg.length > 1) && 
171 +                               (this.messageTextWidgetModel.value != undefined) &&
172 +                               (this.messageTextWidgetModel.value == msg))
173 +                       {
174 +                               this.setTextFieldValue("");
175 +                       }
176 +           } else {                  
177 +                       if((msg.length > 1) && 
178 +                               ((this.messageTextWidgetModel.value == undefined) || 
179 +                               (this.messageTextWidgetModel.value == "") ||
180 +                               (this.messageTextWidgetModel.value == msg)))
181 +                       {
182 +                               var curPos = this.Messaging.messagingPrefs.getMessageGreeting().length;
183 +                               this.setTextFieldValue(msg);
184 +                               this.controller.get("messageTextWidget").mojo.setCursorPosition(curPos, curPos);
185 +                       }
186 +               }
187 +
188                 this.setCharacterCounterMaxLength();
189         },
190  
191 @@ -2437,6 +2475,9 @@
192                 Mojo.Log.info("value " + value);
193                 
194                 if (value === 'forward-cmd') {
195 +                       if(this.Messaging.messagingPrefs.getPrependForward())
196 +                               text = "Fwd: " + text;
197 +               
198                         var composeParams = {
199                                 messageText: text,
200                                 focusWindow: true,
201 @@ -3104,8 +3145,26 @@
202         
203         _getMessageFromDraft: function() {
204                 MessagingDB.Messages.getMessageFromDraft(this.chatThreadId, function(result) {
205 -                       // Fill in text fields
206 -                       this.setTextFieldValue(result.messageText);
207 +                       if(this.Messaging.messagingPrefs.getUseAutomaticMsgDrafts()) {
208 +                               // Fill in text fields
209 +                               this.setTextFieldValue(result.messageText);
210 +                       }
211 +
212 +                       if(this.Messaging.messagingPrefs.getUseClipboardMsgDrafts())
213 +                               this.controller.stageController.setClipboard(result.messageText);
214 +
215 +                       if((result.serviceName == undefined) || (result.serviceName == "sms")) {
216 +                               var msg = this.Messaging.messagingPrefs.getMessageGreeting() + " " + 
217 +                                       this.Messaging.messagingPrefs.getMessageSignature();
218 +
219 +                               if((msg.length > 1) && ((this.messageTextElement.value == undefined) ||
220 +                                       (this.messageTextElement.value == "") || (this.messageTextElement.value == msg)))
221 +                               {
222 +                                       var curPos = this.Messaging.messagingPrefs.getMessageGreeting().length;
223 +                                       this.setTextFieldValue(msg);
224 +                                       this.controller.get("messageTextWidget").mojo.setCursorPosition(curPos, curPos);
225 +                               }
226 +                       }
227                 }.bind(this));
228         },
229  
230 --- .orig/usr/palm/applications/com.palm.app.messaging/app/controllers/compose-assistant.js
231 +++ /usr/palm/applications/com.palm.app.messaging/app/controllers/compose-assistant.js
232 @@ -132,10 +132,6 @@
233         },
234  
235         setup: function() {
236 -               if (!this.launchedWithParams){
237 -                       this.restoreFromDraft();
238 -               }
239 -
240                 this.controller.setupWidget(Mojo.Menu.appMenu, this.appMenuAttrs, this.appMenuModel);
241  
242                 this.searchList = {
243 @@ -230,6 +226,10 @@
244                 if (this.passedAttachment) {
245                         this.attachFile(this.passedAttachment, this.passedAttachmentIconPath, this.deleteAttachmentWhenDone, this.passedAttachmentType, this.passedTranscodeParams);
246                 }
247 +
248 +               if (!this.launchedWithParams){
249 +                       this.restoreFromDraft();
250 +               }
251         },
252  
253         pushReminder: function(recipient){
254 @@ -784,10 +784,30 @@
255                                 }
256                         }
257                 }
258 +
259 +               var msg = this.Messaging.messagingPrefs.getMessageGreeting() + " " + 
260 +                       this.Messaging.messagingPrefs.getMessageSignature();
261 +
262             // Hide the attach button if there is an IM contact
263 -           if(hasIM === true) {         
264 +           if(hasIM === true) {  
265 +                       if((msg.length > 1) && 
266 +                               (this.messageTextWidgetModel.value != undefined) &&
267 +                               (this.messageTextWidgetModel.value == msg))
268 +                       {
269 +                               this.setTextFieldValue("");
270 +                       }
271 +                  
272               this.hideAttachButton();
273             } else {                  
274 +                       if((msg.length > 1) && 
275 +                               ((this.messageTextWidgetModel.value == undefined) || 
276 +                               (this.messageTextWidgetModel.value == "")))
277 +                       {
278 +                               var curPos = this.Messaging.messagingPrefs.getMessageGreeting().length;
279 +                               this.setTextFieldValue(msg);
280 +                               this.controller.get("messageTextWidget").mojo.setCursorPosition(curPos, curPos);
281 +                       }
282 +
283               this.showAttachButton();
284             }
285                 this.setCharacterCounterMaxLength();
286 @@ -921,13 +941,29 @@
287                 if (this.launchedAsForward === undefined && 
288                         (this.messageText === undefined || this.messageText.length === 0) &&
289                         this.prePopulatedRecipients.length === 0) {
290 +                               var msg = this.Messaging.messagingPrefs.getMessageGreeting() + " " + 
291 +                                       this.Messaging.messagingPrefs.getMessageSignature();
292 +
293 +                               if((msg.length > 1) && 
294 +                                       ((this.messageTextWidgetModel.value == undefined) || 
295 +                                       (this.messageTextWidgetModel.value == "")))
296 +                               {
297 +                                       var curPos = this.Messaging.messagingPrefs.getMessageGreeting().length;
298 +                                       this.setTextFieldValue(msg);
299 +                                       this.controller.get("messageTextWidget").mojo.setCursorPosition(curPos, curPos);
300 +                               }
301                                 
302                                 MessagingDB.Messages.getMessageFromDraft("_compose",function(result) {
303 -                                       this.controller.get('searchList').mojo.updateRecipients(result.to);
304 -                                       this.setTextFieldValue(result.messageText);
305 -                                       if (result.attachment !== undefined) {
306 -                                               this.attachFile(result.attachment);
307 +                                       if(this.Messaging.messagingPrefs.getUseAutomaticMsgDrafts()) {
308 +                                               this.controller.get('searchList').mojo.updateRecipients(result.to);
309 +                                               this.setTextFieldValue(result.messageText);
310 +                                               if (result.attachment !== undefined) {
311 +                                                       this.attachFile(result.attachment);
312 +                                               }                                       
313                                         }                                       
314 +
315 +                                       if(this.Messaging.messagingPrefs.getUseClipboardMsgDrafts())
316 +                                               this.controller.stageController.setClipboard(result.messageText);
317                                 }.bind(this));
318                 }
319         },
320 --- .orig/usr/palm/applications/com.palm.app.messaging/app/controllers/dashboardMessage-assistant.js
321 +++ /usr/palm/applications/com.palm.app.messaging/app/controllers/dashboardMessage-assistant.js
322 @@ -2,7 +2,7 @@
323  /*jslint white: false, onevar: false, nomen:false, plusplus: false*/
324  /* Copyright 2009 Palm, Inc.  All rights reserved. */
325  
326 -function DashboardMessageAssistant(dashboardData) {
327 +function DashboardMessageAssistant(dashboardData, blinkNotify) {
328         this.dashboardData = dashboardData; // hold onto a reference to the dashboardData
329         if(this.dashboardData.newest && this.dashboardData[this.dashboardData.newest].list && this.dashboardData[this.dashboardData.newest].list.length>0){
330                 this.isInvite = (this.dashboardData[this.dashboardData.newest].list[0].imType === "invite"? true:false);
331 @@ -11,10 +11,11 @@
332         this.Messaging = this.appController.Messaging;
333         this.tapHandler = this.tapHandler.bindAsEventListener(this);
334         this.oldPresenceClass = "";
335 +       this.blinkNotify = blinkNotify;
336  }
337  
338  DashboardMessageAssistant.prototype.setup = function() {
339 -       this.update(true);
340 +       this.update(this.blinkNotify);
341         this.messageInfoElement = this.controller.get('message_info');
342         this.messageInfoElement.addEventListener(Mojo.Event.tap, this.tapHandler);
343  };
344 --- .orig/usr/palm/applications/com.palm.app.messaging/app/controllers/listview-assistant.js
345 +++ /usr/palm/applications/com.palm.app.messaging/app/controllers/listview-assistant.js
346 @@ -32,6 +32,8 @@
347                 this.historyListReset = false;
348                 this.delayUpdateCount = 0;
349                 this.delayExecuteCount = 0;
350 +               this.accountsData = {};
351 +               this.availabilityData = {};
352         
353                 this.COMMAND_MENU = {
354                         loadComposeView: {command:'cmdLoadComposeView',target: this.loadComposeView.bind(this)},
355 @@ -67,7 +69,7 @@
356                         {label: $L('Available'), command:this.Messaging.Availability.getAvailabilityAsConstText(this.Messaging.Availability.AVAILABLE), secondaryIcon:'status-available'},
357                         {label: $L('Busy'),      command:this.Messaging.Availability.getAvailabilityAsConstText(this.Messaging.Availability.BUSY),      secondaryIcon:'status-away'},
358                         // libpurple doesn't support invisible status for gtalk so commenting this out for now.
359 -                       //{label: $L('Invisible'), command:this.Messaging.Availability.getAvailabilityAsConstText(this.Messaging.Availability.INVISIBLE),  secondaryIcon:'status-invisible'},
360 +                       {label: $L('Invisible'), command:this.Messaging.Availability.getAvailabilityAsConstText(this.Messaging.Availability.INVISIBLE),  secondaryIcon:'status-invisible'},
361                         {label: $L('Sign off'),  command:this.Messaging.Availability.getAvailabilityAsConstText(this.Messaging.Availability.OFFLINE),   secondaryIcon:'status-offline'}
362                 ];
363                 
364 @@ -91,6 +93,29 @@
365         
366                 //To update the addBuddy menu item
367                 this.handleIMAccountsChange = function(results) {
368 +                       this.accountsData = {};
369 +                                       
370 +                       if(results && results.length > 1) {
371 +                               for(var i = 0; i < results.length; i++) {                                               
372 +                                       if(results[i].alias) {
373 +                                               var cp = results[i].capabilityProviders;
374 +
375 +                                               for (j = 0; j < cp.length; j++) {
376 +                                                       if (cp[j].capability === 'MESSAGING') {
377 +                                                               if (cp[j].capabilitySubtype === 'IM') {
378 +                                                                       if(!this.accountsData[results[i].alias])
379 +                                                                               this.accountsData[results[i].alias] = [];
380 +       
381 +                                                                       this.accountsData[results[i].alias].push({
382 +                                                                               accountId: results[i]._id, 
383 +                                                                               username: results[i].username});
384 +                                                               }
385 +                                                       }
386 +                                               }
387 +                                       }
388 +                               }
389 +                       }
390 +
391                         //Assume we only have SMS and IM for Messaging, only have one SMS
392                         if (results && results.length > 1) {
393                                 this.toEnableAddBuddyMenuItem = true;
394 @@ -136,6 +161,8 @@
395                 }.bind(this);
396                 
397                 this.updateAvailability = function(results) {
398 +                       this.availabilityData = {};
399 +                                       
400                         //Mojo.Log.info("this.updateAvailability: %j",results);
401                         Mojo.Log.info("Number of IM transports: "+results.length);
402                         if( results && results.length > 0 ) {
403 @@ -156,6 +183,13 @@
404                                 var isPending = false;
405                                 for (var i = 0; i < results.length && !isPending; i++) {
406                                         var account = results[i];
407 +                                       
408 +                                       this.availabilityData[account.accountId] = {
409 +                                               objectId: account._id,
410 +                                               availability: account.availability,
411 +                                               customMessage: account.customMessage
412 +                                       };
413 +                                       
414                                         Mojo.Log.info("username=%s, availability=%d, state=%s", account.username, account.availability, account.state);
415                                         // If an account is not offline, then we can clear out any notifications
416                                         // that may have been queued from losing wifi connectivity when the screen turned off
417 @@ -216,7 +250,11 @@
418                 this.handleHistoryListDelete = this.handleHistoryListDelete.bindAsEventListener(this);
419                 this.handleBuddyListTap = this.handleBuddyListTap.bindAsEventListener(this);
420                 this.handleAvailabilityPickerTap = this.handleAvailabilityPickerTap.bindAsEventListener(this);
421 -               this.customMessageUpdate = this.customMessageUpdate.bind(this);
422 +               this.handleAvailabilityPickerHold = this.handleAvailabilityPickerHold.bindAsEventListener(this);
423 +               this.customMessageSelect = this.customMessageSelect.bindAsEventListener(this);
424 +               this.customMessageCancel = this.customMessageCancel.bindAsEventListener(this);
425 +               this.customMessageUpdateTap = this.customMessageUpdate.bindAsEventListener(this, true);
426 +               this.customMessageUpdateHold = this.customMessageUpdate.bindAsEventListener(this, false);
427                 this.handleScreenStateChange = this.handleScreenStateChange.bind(this);
428                 this.handleFocus = this.handleFocus.bind(this);
429                 this.handleLoseFocus = this.handleLoseFocus.bind(this);
430 @@ -418,7 +456,9 @@
431                                 }.bind(this),
432                                 template: 'listview/historyList-divider'
433                         },
434 -                       swipeDelete: true,
435 +                       swipeDelete: {
436 +                               autoConfirm: !this.Messaging.messagingPrefs.getUseDeleteConfirmation()
437 +                       },
438                         uniquenessProperty: '_id',
439                         revisionProperty: '_rev',
440                         delay: 500
441 @@ -650,6 +690,54 @@
442         },
443         
444         handleAvailabilityPickerTap: function(event) {
445 +               var accountsList = [];
446 +               var accountNames = {};
447 +
448 +               for(var alias in this.accountsData) {
449 +                       accountsList.push({label: alias});
450 +                       
451 +                       var listLength = accountsList.length;
452 +                       
453 +                       for(var i = 0; i < this.accountsData[alias].length; i++) {
454 +                               if(this.availabilityData[this.accountsData[alias][i].accountId]) {
455 +                                       var availability = this.availabilityData[this.accountsData[alias][i].accountId].availability;
456 +                       
457 +                                       if(availability == this.Messaging.Availability.AVAILABLE)
458 +                                               var icon = 'status-available';
459 +                                       else if(availability == this.Messaging.Availability.BUSY)
460 +                                               var icon = 'status-away';
461 +                                       else if(availability == this.Messaging.Availability.INVISIBLE)
462 +                                               var icon = 'status-invisible';
463 +                                       else
464 +                                               var icon = 'status-offline';
465 +                       
466 +                                       accountNames[this.accountsData[alias][i].accountId] = alias + " - " + this.accountsData[alias][i].username;
467 +                       
468 +                                       accountsList.push({
469 +                                               label: this.accountsData[alias][i].username, 
470 +                                               command: this.accountsData[alias][i].accountId, 
471 +                                               secondaryIcon: icon});
472 +                               }
473 +                       }
474 +                       
475 +                       if(listLength == accountsList.length)
476 +                               accountsList.splice(listLength - 1, 1);
477 +               }
478 +               
479 +               if(accountsList.length <= 2)
480 +                       this.handleAvailabilityPickerHold(event);
481 +               else {
482 +                       this.controller.popupSubmenu({
483 +                               onChoose: this.handleAccountSelection.bind(this, event.target, accountNames),
484 +                               placeNear: event.target,
485 +                               items: accountsList
486 +                       });
487 +               }
488 +       },
489 +
490 +       handleAvailabilityPickerHold: function(event) {
491 +               event.stop();
492 +               
493                 this.controller.popupSubmenu({
494                         onChoose: this.handleAvailabilitySelection.bind(this),
495                         toggleCmd: this.Messaging.Availability.getAvailabilityAsConstText(this.currentAvailability),
496 @@ -667,10 +755,12 @@
497                         this.customMessageTextWidgetModel.value = "";
498                         this.customMessageTextWidgetModel.disabled = true;
499                 } else {
500 +                       this.customMessageTextWidgetModel.value = "";
501                         this.customMessageTextWidgetModel.disabled = false;
502 -                       if (this.customMessage) {
503 +/*                     if (this.customMessage) {
504                                 this.customMessageTextWidgetModel.value = this.customMessage;
505                         }
506 +*/
507                 }
508                 
509                 if (update) {
510 @@ -701,10 +791,13 @@
511                 // the checkmark image to commit changes
512                 this.customMessageField = this.controller.get('customMessageTextWidget').querySelector('[name=customMessageTextElement]');
513                 //this.customMessage = this.customMessageField.value;
514 -               this.customMessageField.observe('blur', this.customMessageUpdate);
515 +               this.customMessageField.observe('focus', this.customMessageSelect);
516 +               this.customMessageField.observe('blur', this.customMessageCancel);
517                 this.customMessageField.observe('keyup', this.handleCustomMessageFieldKeyUp);
518 -               this.commitCustomMessageElement.observe(Mojo.Event.tap, this.customMessageUpdate);
519 +               this.commitCustomMessageElement.observe(Mojo.Event.tap, this.customMessageUpdateTap);
520 +               this.commitCustomMessageElement.observe(Mojo.Event.hold, this.customMessageUpdateHold);
521                 this.availabilityPickerElement.observe(Mojo.Event.tap, this.handleAvailabilityPickerTap);
522 +               this.availabilityPickerElement.observe(Mojo.Event.hold, this.handleAvailabilityPickerHold);
523  
524                 this.controller.document.addEventListener(Mojo.Event.stageActivate, this.handleFocus, false);
525                 this.controller.document.addEventListener(Mojo.Event.stageDeactivate, this.handleLoseFocus, false);
526 @@ -1752,10 +1845,13 @@
527                 this.historyIndexedList.stopObserving(Mojo.Event.listTap, this.handleHistoryListTap);
528                 this.historyIndexedList.stopObserving(Mojo.Event.listDelete, this.handleHistoryListDelete);
529                 this.buddyIndexedList.stopObserving(Mojo.Event.listTap, this.handleBuddyListTap);
530 -               this.customMessageField.stopObserving('blur', this.customMessageUpdate);
531 +               this.customMessageField.stopObserving('focus', this.customMessageSelect);
532 +               this.customMessageField.stopObserving('blur', this.customMessageCancel);
533                 this.customMessageField.stopObserving('keyup', this.handleCustomMessageFieldKeyUp);
534 -               this.commitCustomMessageElement.stopObserving(Mojo.Event.tap, this.customMessageUpdate);
535 +               this.commitCustomMessageElement.stopObserving(Mojo.Event.tap, this.customMessageUpdateTap);
536 +               this.commitCustomMessageElement.stopObserving(Mojo.Event.hold, this.customMessageUpdateHold);
537                 this.availabilityPickerElement.stopObserving(Mojo.Event.tap, this.handleAvailabilityPickerTap);
538 +               this.availabilityPickerElement.stopObserving(Mojo.Event.hold, this.handleAvailabilityPickerHold);
539                 this.Messaging.DisplayState.stopObserving(this.handleScreenStateChange);
540                 this.controller.document.removeEventListener(Mojo.Event.stageActivate, this.handleFocus, false);
541                 this.controller.document.removeEventListener(Mojo.Event.stageDeactivate, this.handleLoseFocus, false);
542 @@ -1763,6 +1859,50 @@
543                 this.Messaging.listviewSceneAssistant = null; // null out the reference to the listview so that it can get garbage collected
544         },
545  
546 +       handleAccountSelection: function(target, accountNames, accountId) {
547 +               if(accountId) {
548 +                       var availabilityList = [{label: accountNames[accountId]}];
549 +                       
550 +                       availabilityList = availabilityList.concat(this.availabilities);
551 +               
552 +                       var currentAvailability = this.Messaging.Availability.getAvailabilityAsConstText(this.Messaging.Availability.OFFLINE);
553 +
554 +                       if(this.availabilityData[accountId]) {
555 +                               var availability = this.availabilityData[accountId].availability;
556 +                               
557 +                               currentAvailability = this.Messaging.Availability.getAvailabilityAsConstText(availability);
558 +                       }
559 +       
560 +                       this.controller.popupSubmenu({
561 +                               onChoose: this.handleAccountAvailabilitySelection.bind(this, accountId),
562 +                               toggleCmd: currentAvailability,
563 +                               placeNear: target,
564 +                               items: availabilityList
565 +                       });
566 +               }
567 +       },
568 +       
569 +       handleAccountAvailabilitySelection: function(accountId, availabilityString) {
570 +               if((availabilityString) && (this.availabilityData[accountId])) {
571 +                       var availabilityInteger = this.Messaging.Availability.getAvailabilityAsInteger(availabilityString);
572 +
573 +                       MessagingDB.IMLoginState.setAvailability(availabilityInteger, this.availabilityData[accountId].objectId);
574 +
575 +                       if(availabilityInteger < 4) {
576 +                               for(var i = 0; i < this.appController.Messaging.IMAccounts.data.length; i++) {
577 +                                        var capability = this.appController.Messaging.IMAccounts.data[i].capabilityProviders;
578 +
579 +                                        for (var j = 0; j< capability.length; j++) {
580 +                                               if(capability[j].capability === "MESSAGING" && capability[j].wanOnly === true){
581 +                                                       this.checkWANConnection(capability[j]);
582 +                                                       break;
583 +                                               }
584 +                                       }
585 +                               }
586 +                       }
587 +               }
588 +       },
589 +       
590         handleAvailabilitySelection: function(availabilityString) {
591                 var availabilityInteger;
592                 
593 @@ -1879,15 +2019,133 @@
594                         this.appController.notificationAssistant.clearMessageDashboard();
595                 }
596         },
597 -       
598 -       customMessageUpdate: function(e) {
599 +
600 +       customMessageUpdate: function(e, select, accountId) {
601 +               e.stop();
602 +               
603 +               if(select) {
604 +                       var count = 0;
605 +                       var accountsList = [];
606 +
607 +                       for(var alias in this.accountsData) {
608 +                               accountsList.push({label: alias});
609 +
610 +                               var listLength = accountsList.length;
611 +
612 +                               for(var i = 0; i < this.accountsData[alias].length; i++) {
613 +                                       if(this.availabilityData[this.accountsData[alias][i].accountId]) {
614 +                                               count++;
615 +                                       
616 +                                               var availability = this.availabilityData[this.accountsData[alias][i].accountId].availability;
617 +                                       
618 +                                               if((availability != this.Messaging.Availability.OFFLINE) && 
619 +                                                       (availability != this.Messaging.Availability.PENDING))
620 +                                               {
621 +                                                       accountsList.push({
622 +                                                               label: this.accountsData[alias][i].username, 
623 +                                                               command: this.accountsData[alias][i].accountId});
624 +                                               }
625 +                                       }
626 +                               }
627 +                               
628 +                               if(listLength == accountsList.length)
629 +                                       accountsList.splice(listLength - 1, 1);
630 +                       }
631 +               
632 +                       if(count > 1) {
633 +                               this.controller.popupSubmenu({
634 +                                       onChoose: this.customMessageUpdate.bind(this, e, false),
635 +                                       placeNear: e.target,
636 +                                       items: accountsList
637 +                               });
638 +
639 +                               return;
640 +                       }
641 +               }
642 +
643 +               var objectId = null;
644 +
645 +               if((accountId) && (this.availabilityData[accountId]))
646 +                       objectId = this.availabilityData[accountId].objectId;
647 +
648                 var newMessage = this.customMessageField.value;
649                 // Set the new custom message if it has changed or if it has been cleared
650 -               if ((newMessage.length > 0 && newMessage !== this.customMessage) ||
651 -               (newMessage.length === 0 && this.customMessage.length > 0)) {
652 +//             if ((newMessage.length > 0 && newMessage !== this.customMessage) ||
653 +//             (newMessage.length === 0 && this.customMessage.length > 0)) {
654                         this.customMessage = newMessage;
655 -                       MessagingDB.IMLoginState.setCustomMessage(this.customMessage);
656 +                       MessagingDB.IMLoginState.setCustomMessage(this.customMessage, objectId);
657                         this.updateCustomMessageCommitIcon();
658 +//             }
659 +
660 +               this.controller.get('customMessageTextWidget').mojo.blur();
661 +       },
662 +       
663 +       customMessageSelect: function(event) {
664 +               var messagesList = [];
665 +               this.customMessage = null;                      
666 +
667 +               this.customMessageTextWidgetModel.value = "";
668 +               this.controller.modelChanged(this.customMessageTextWidgetModel);
669 +
670 +               messagesList.push({label: $L("New custom message..."), command: "empty"});
671 +
672 +               for(var alias in this.accountsData) {
673 +                       for(var i = 0; i < this.accountsData[alias].length; i++) {
674 +                               if(this.availabilityData[this.accountsData[alias][i].accountId]) {
675 +                                       if((this.availabilityData[this.accountsData[alias][i].accountId].customMessage) &&
676 +                                               (this.availabilityData[this.accountsData[alias][i].accountId].customMessage.length > 0))
677 +                                       {
678 +                                               messagesList.push({label: alias + " - " + this.accountsData[alias][i].username});
679 +
680 +                                               messagesList.push({
681 +                                                       label: this.availabilityData[this.accountsData[alias][i].accountId].customMessage, 
682 +                                                       command: this.accountsData[alias][i].accountId});
683 +                                       }
684 +                               }
685 +                       }
686 +               }
687 +       
688 +               if(messagesList.length > 2) {
689 +                       this.controller.popupSubmenu({
690 +                               onChoose: this.customMessageFill.bind(this),
691 +                               placeNear: event.target,
692 +                               items: messagesList
693 +                       });
694 +               }
695 +               else
696 +                       this.controller.get('commitCustomMessage').show();
697 +       },
698 +       
699 +       customMessageCancel: function(event) {
700 +               this.customMessage = '';
701 +       
702 +               this.customMessageTextWidgetModel.value = '';
703 +               this.controller.modelChanged(this.customMessageTextWidgetModel);
704 +
705 +               this.updateCustomMessageCommitIcon();
706 +       },
707 +       
708 +       customMessageFill: function(accountId) {
709 +               if(accountId) {
710 +                       if(accountId == "empty") {
711 +                               this.controller.get('commitCustomMessage').show();
712 +                       }
713 +                       else {
714 +                               if((this.availabilityData[accountId]) && 
715 +                                       (this.availabilityData[accountId].customMessage) &&
716 +                                       (this.availabilityData[accountId].customMessage.length > 0))
717 +                               {
718 +                                       var msg = this.availabilityData[accountId].customMessage;
719 +               
720 +                                       this.customMessageTextWidgetModel.value = msg;
721 +                                       this.controller.modelChanged(this.customMessageTextWidgetModel);
722 +
723 +                                       this.updateCustomMessageCommitIcon();
724 +                               }
725 +                       }
726 +               }
727 +               else {
728 +                       this.customMessageCancel();
729                 }
730         },
731         
732 --- .orig/usr/palm/applications/com.palm.app.messaging/app/controllers/notification-assistant.js
733 +++ /usr/palm/applications/com.palm.app.messaging/app/controllers/notification-assistant.js
734 @@ -9,6 +9,7 @@
735         // a reference to this is passed to the dashboard assistant
736         this.messageDashboardData = {};
737         this.inviteDashboardData = {};
738 +       this.notificationsData = {};
739         this.class0AlertData = {
740                 list: []
741         };
742 @@ -230,20 +231,20 @@
743   */
744  
745  NotificationAssistant.prototype.considerForNotification = function(notificationData){
746 -       if (!this.Messaging.messagingPrefs.getNotificationsEnabled()) {
747 +       if (!this.Messaging.messagingPrefs.getNotificationsEnabled(notificationData.message.serviceName)) {
748                 Mojo.Log.info("Notification Assistant - Consider for Notification - Notifications are disabled");       
749                 return;
750         }
751         
752         // check if we should only play a sound (when you are already in a chat & a new message comes in)
753 -       if(notificationData.playSoundOnly && this.Messaging.messagingPrefs.getNotificationSound()) {
754 +       if(notificationData.playSoundOnly && this.Messaging.messagingPrefs.getNotificationSound(notificationData.message.serviceName)) {
755                 var notifParams = {};
756 -               this.setNotificationSound(notifParams);
757 +               this.setNotificationSound(notifParams, notificationData);
758                 this.controller.playSoundNotification(notifParams.soundClass, notifParams.soundFile);
759                 return; // don't display any visual notification
760         }       
761         //TODO: does sendFailure and connectionFailure need displayName?
762 -       if (Object.keys(notificationData).length > 0 && this.Messaging.messagingPrefs.getNotificationsEnabled()) {
763 +       if (Object.keys(notificationData).length > 0 && this.Messaging.messagingPrefs.getNotificationsEnabled(notificationData.message.serviceName)) {
764                 var notificationType = notificationData.notificationType;
765                 if (notificationType === this.Messaging.notificationTypes.newMessage) {
766                         this.preSendNewMessageNotificationAndUpdateDashboard(notificationData);
767 @@ -344,10 +345,40 @@
768                 
769                 future.then(this, function(future){
770                         if (future.result) {
771 +                               if(MessagingLib.Utils.isTextMessage(notificationData.message.serviceName)) {
772 +                                       notificationData.soundClass = future.result.getMsgAlert().getAlert();
773 +                                       notificationData.ringtonePath = future.result.getMsgRingtone().getLocation();
774 +                               }
775 +                               else {
776 +                                       notificationData.soundClass = future.result.getIMsgAlert().getAlert();
777 +                                       notificationData.ringtonePath = future.result.getIMsgRingtone().getLocation();
778 +                               }
779 +                                                       
780                                 notificationData.message.displayName = future.result.generateDisplayName(false);
781 +
782 +                               future.result = future.result;
783 +                               this.sendNewMessageNotificationAndUpdateDashboard(notificationData);
784 +                       }
785 +                       else if(MessagingLib.Utils.isTextMessage(notificationData.message.serviceName)) {
786 +                               if(this.contactPrefs)
787 +                                       delete this.contactPrefs;
788 +       
789 +                               this.contactPrefs = new ContactsLib.AppPrefs(function(future) {
790 +                                       var prefs = this.contactPrefs.get(ContactsLib.AppPrefs.Pref.unknownContacts);
791 +
792 +                                       if((prefs) && (prefs.msgAlert)) {
793 +                                               notificationData.soundClass = prefs.msgAlert;
794 +                                               notificationData.ringtonePath = prefs.msgRingtonePath;
795 +                                       }
796 +
797 +                                       future.result = future.result;
798 +                                       this.sendNewMessageNotificationAndUpdateDashboard(notificationData);
799 +                               }.bind(this, future));                  
800 +                       }
801 +                       else {
802 +                               future.result = future.result;
803 +                               this.sendNewMessageNotificationAndUpdateDashboard(notificationData);
804                         }
805 -                       future.result = future.result;
806 -                       this.sendNewMessageNotificationAndUpdateDashboard(notificationData);
807                 });
808         }
809         else {
810 @@ -411,7 +442,7 @@
811         var bannerParams = {
812                 messageText: notificationText
813         };
814 -       this.setNotificationSound(bannerParams);
815 +       this.setNotificationSound(bannerParams, notificationData);
816         var bannerLaunchParams =  {
817                 chatThreadId: chatThreadId,
818                 clearBanner: true               
819 @@ -480,11 +511,16 @@
820         var dashboard = this.controller.getStageController(dashboardStagename);
821         
822         if (dashboard) {
823 -               dashboard.delegateToSceneAssistant("update", true);
824 +               if(this.Messaging.messagingPrefs.getNotificationBlink(notificationData.message.serviceName))
825 +                       dashboard.delegateToSceneAssistant("update", true);
826 +               else
827 +                       dashboard.delegateToSceneAssistant("update", false);            
828         } else {
829 +               var blinkNotify = this.Messaging.messagingPrefs.getNotificationBlink(notificationData.message.serviceName);
830 +       
831                 // Create a dashboard
832                 var f = function(stageController){
833 -                       stageController.pushScene('dashboardMessage', dashboardData);
834 +                       stageController.pushScene('dashboardMessage', dashboardData, blinkNotify);
835                 }.bind(this);
836                 var params = {
837                         name: dashboardStagename,
838 @@ -509,6 +545,8 @@
839                         createDashboard(); // if the screen is off, create the dashboard right away
840                 }
841         }
842 +       
843 +       this.schedulePlayNotificationSoundTasks(notificationData.message.serviceName);
844  };
845  
846  // ISSUES: what are the error types?  What is the max number / types of dashboards that we could have?
847 @@ -542,7 +580,7 @@
848         var bannerParams = {
849                 messageText: notificationText.escapeHTML()
850         };
851 -       if (this.Messaging.messagingPrefs.getNotificationSound() !== "mute") {
852 +       if (this.Messaging.messagingPrefs.getNotificationSound(notificationData.message.serviceName) !== "mute") {
853                 bannerParams.soundClass = "alerts";     
854         }
855         var bannerLaunchParams =  {
856 @@ -747,6 +785,8 @@
857  };
858  
859  NotificationAssistant.prototype.clearNotificationsForChat = function(chatThreadId){    
860 +       this.removePlayNotificationSoundTasks();
861 +
862         var i;
863         var newestTimestamp = 0;
864         var newestChat;
865 @@ -841,6 +881,8 @@
866  };
867  
868  NotificationAssistant.prototype.resetNewMessages = function(){
869 +       this.removePlayNotificationSoundTasks();
870 +               
871         this.messageDashboardData = {};
872  };
873  
874 @@ -849,8 +891,12 @@
875  };
876  
877  NotificationAssistant.prototype.clearMessageDashboard = function(){
878 -       var dashboard = this.controller.getStageController(DashboardMessageStageName);
879 +       this.removePlayNotificationSoundTasks();
880 +
881         this.messageDashboardData = {};
882 +
883 +       var dashboard = this.controller.getStageController(DashboardMessageStageName);
884 +
885         if (dashboard) {
886                 dashboard.delegateToSceneAssistant("closeDashboard");
887         }
888 @@ -884,15 +930,26 @@
889         }
890  };
891  
892 -NotificationAssistant.prototype.setNotificationSound = function(bannerParams){
893 -       switch (this.Messaging.messagingPrefs.getNotificationSound()) {
894 +NotificationAssistant.prototype.setNotificationSound = function(bannerParams, notificationData){
895 +       var soundClass = this.Messaging.messagingPrefs.getNotificationSound(notificationData.message.serviceName);
896 +       var ringtonePath = this.Messaging.messagingPrefs.getRingtone(notificationData.message.serviceName).path;
897 +
898 +       if((notificationData.soundClass != undefined) && 
899 +               (notificationData.soundClass != "") &&
900 +               (notificationData.soundClass != "default"))
901 +       {
902 +               soundClass = notificationData.soundClass;
903 +               ringtonePath = notificationData.ringtonePath;           
904 +       }
905 +       
906 +       switch (soundClass) {
907                 case "alert": 
908                         bannerParams.soundClass = "notifications";
909                         bannerParams.soundFile = undefined;
910                         break;
911                 case "ringtone":
912                         bannerParams.soundClass = "notifications";
913 -                       bannerParams.soundFile = this.Messaging.messagingPrefs.getRingtone().path;
914 +                       bannerParams.soundFile = ringtonePath;
915                         break;
916                 case "vibrate":
917                         bannerParams.soundClass = "vibrate";
918 @@ -907,4 +964,74 @@
919         Mojo.Log.info("setNotificationSound result=%j", bannerParams);
920  };
921  
922 +NotificationAssistant.prototype.schedulePlayNotificationSoundTasks = function(serviceName) {
923 +       var repeatDelay = 0;
924 +       var currentTime = new Date();
925 +
926 +       if(this.notificationsData[serviceName] == undefined)
927 +               this.notificationsData[serviceName] = 0;
928 +       
929 +       for(var serviceName in this.notificationsData) {
930 +               if(this.Messaging.messagingPrefs.getNotificationsEnabled(serviceName) == false) {
931 +                       delete this.notificationsData[serviceName];
932 +               }
933 +               else if((this.Messaging.messagingPrefs.getNotificationSound(serviceName) != "mute") &&
934 +                       (this.Messaging.messagingPrefs.getRepeatInterval(serviceName) != 0))
935 +               {
936 +                       if(this.notificationsData[serviceName]++ >= this.Messaging.messagingPrefs.getRepeatLimit(serviceName)) {
937 +                               delete this.notificationsData[serviceName];
938 +                       }
939 +                       else {
940 +                               var repeatInterval = this.Messaging.messagingPrefs.getRepeatInterval(serviceName);
941 +               
942 +                               var playSoundTime = new Date(currentTime.getTime() + (parseInt(repeatInterval) * 1000) + (repeatDelay++ * 10));
943 +
944 +                               var month = playSoundTime.getUTCMonth()+1;
945 +                               if(month < 10) month = "0" + month;
946 +                               var day = playSoundTime.getUTCDate();
947 +                               if(day < 10) day = "0" + day;
948 +                               var year = playSoundTime.getUTCFullYear();
949 +
950 +                               var hours = playSoundTime.getUTCHours();
951 +                               if(hours < 10) hours = "0" + hours;
952 +                               var minutes = playSoundTime.getUTCMinutes();
953 +                               if(minutes < 10) minutes = "0" + minutes;
954 +                               var seconds = playSoundTime.getUTCSeconds();
955 +                               if(seconds < 10) seconds = "0" + seconds;
956 +
957 +                               var scheduledTimeStr = month + "/" + day + "/" + year + " " + hours + ":" + minutes + ":" + seconds;
958 +               
959 +                               this.updateTimeoutRequest = new Mojo.Service.Request('palm://com.palm.power/timeout/', {
960 +                                       'method': "set", 'parameters': { 'key': 'messagingPlayNotificationSound-' + serviceName, 
961 +                                       'wakeup': true, 'at': scheduledTimeStr, 'uri': "palm://com.palm.applicationManager/open", 
962 +                                       'params': {'id': 'com.palm.app.messaging', 'params': {'serviceName': serviceName,
963 +                                               'playNotificationSound': this.notificationsData[serviceName]}}} }); 
964 +                       }
965 +               }
966 +       }
967 +};
968 +       
969 +NotificationAssistant.prototype.removePlayNotificationSoundTasks = function() {
970 +       for(var serviceName in this.notificationsData) {
971 +               if(this.notificationsData[serviceName] > 0) {
972 +                       this.removeTimeoutRequest = new Mojo.Service.Request("palm://com.palm.power/timeout/", {
973 +                               'method': "clear", 'parameters': {"key": 'messagingPlayNotificationSound-' + serviceName} });
974 +               }
975 +       }
976 +       
977 +       this.notificationsData = {};
978 +};
979 +
980 +NotificationAssistant.prototype.playNotificationSound = function(serviceName) {
981 +       var notifyType = this.Messaging.messagingPrefs.getNotificationSound(serviceName);
982 +
983 +       var ringtonePath = this.Messaging.messagingPrefs.getRingtone(serviceName).path;
984 +               
985 +       if(notifyType == "ringtone")
986 +               this.controller.playSoundNotification("notifications", ringtonePath);
987 +       else if(notifyType == "alert")
988 +               this.controller.playSoundNotification("notifications");
989 +       else if(notifyType == "vibrate")
990 +               this.controller.playSoundNotification("vibrate");       
991 +};
992  
993 --- .orig/usr/palm/applications/com.palm.app.messaging/stylesheets/messaging.css
994 +++ /usr/palm/applications/com.palm.app.messaging/stylesheets/messaging.css
995 @@ -150,6 +150,10 @@
996                 margin: 1px -4px 0px -4px;
997  }
998  
999 +.buddy-list .palm-row {
1000 +               height: auto;
1001 +}
1002 +
1003  /* background: url(../images/simple-splitter.png) bottom left repeat-x;*/
1004  
1005  #groups-list .showGroup {
1006 @@ -1187,6 +1191,23 @@
1007  
1008  /* Preferences */
1009  
1010 +.palm-account-icon.left {
1011 +       float: left;
1012 +}
1013 +.palm-page-header .palm-account-icon {
1014 +       position: absolute;
1015 +       left: 0px;
1016 +       top: 0px;
1017 +       min-height: 52px;
1018 +       width: 56px;
1019 +}
1020 +.default-account-list.palm-account-icon {
1021 +       margin: 0px -5px 0px 10px;
1022 +}
1023 +.palm-account-icon {
1024 +    background: url(../images/serviceicon-sms.png) center center no-repeat;
1025 +}
1026 +
1027  .text-group .title {
1028                 line-height: auto !important;
1029                 padding: 0 !important;
1030 --- .orig/usr/palm/applications/com.palm.app.messaging/app/models/messaging-prefs.js
1031 +++ /usr/palm/applications/com.palm.app.messaging/app/models/messaging-prefs.js
1032 @@ -13,7 +13,7 @@
1033  
1034                 var future = MojoDB.find({
1035                         from: MessagingPrefsService.prefsDB
1036 -               });
1037 +               }, true);
1038  
1039                 future.then(this, function(future) {
1040                         if (future.result.results && future.result.results.length === 0) {
1041 @@ -87,7 +87,18 @@
1042                 }
1043         },
1044         
1045 -       getNotificationsEnabled: function() {
1046 +       getNotificationsEnabled: function(serviceName) {
1047 +               if((serviceName != undefined) && (serviceName != "sms")) {
1048 +                       if (this._prefs === undefined || this._prefs.accountNotifications === undefined ||
1049 +                               this._prefs.accountNotifications[serviceName] === undefined || 
1050 +                               this._prefs.accountNotifications[serviceName].enableNotification === undefined) 
1051 +                       {
1052 +                               return this._getDefaultPrefs().enableNotification;
1053 +                       } else {
1054 +                               return this._prefs.accountNotifications[serviceName].enableNotification;
1055 +                       }
1056 +               }
1057 +               
1058                 if (this._prefs === undefined || this._prefs.enableNotification === undefined) {
1059                         return this._getDefaultPrefs().enableNotification;
1060                 } else {
1061 @@ -95,11 +106,69 @@
1062                 }
1063         },
1064         
1065 -       setNotificationsEnabled: function(enabled) {
1066 -               this._dbMerge({enableNotification:enabled});
1067 +       setNotificationsEnabled: function(enabled, serviceName) {
1068 +               if((serviceName != undefined) && (serviceName != "sms")) {
1069 +                       if (this._prefs.accountNotifications === undefined)
1070 +                               this._prefs.accountNotifications = {};
1071 +
1072 +                       if (this._prefs.accountNotifications[serviceName] === undefined)
1073 +                               this._prefs.accountNotifications[serviceName] = {};
1074 +                       
1075 +                       this._prefs.accountNotifications[serviceName].enableNotification = enabled;
1076 +
1077 +                       this._dbMerge({accountNotifications:this._prefs.accountNotifications});
1078 +               }
1079 +               else
1080 +                       this._dbMerge({enableNotification:enabled});
1081 +       },
1082 +       
1083 +       getNotificationBlink: function(serviceName) {
1084 +               if((serviceName != undefined) && (serviceName != "sms")) {
1085 +                       if (this._prefs === undefined || this._prefs.accountNotifications === undefined ||
1086 +                               this._prefs.accountNotifications[serviceName] === undefined || 
1087 +                               this._prefs.accountNotifications[serviceName].blinkNotification === undefined) 
1088 +                       {
1089 +                               return this._getDefaultPrefs().blinkNotification;
1090 +                       } else {
1091 +                               return this._prefs.accountNotifications[serviceName].blinkNotification;
1092 +                       }
1093 +               }
1094 +               
1095 +               if (this._prefs === undefined || this._prefs.blinkNotification === undefined) {
1096 +                       return this._getDefaultPrefs().blinkNotification;
1097 +               } else {
1098 +                       return this._prefs.blinkNotification;
1099 +               }
1100         },
1101         
1102 -       getNotificationSound: function() {
1103 +       setNotificationBlink: function(blink, serviceName) {
1104 +               if((serviceName != undefined) && (serviceName != "sms")) {
1105 +                       if (this._prefs.accountNotifications === undefined)
1106 +                               this._prefs.accountNotifications = {};
1107 +
1108 +                       if (this._prefs.accountNotifications[serviceName] === undefined)
1109 +                               this._prefs.accountNotifications[serviceName] = {};
1110 +                       
1111 +                       this._prefs.accountNotifications[serviceName].blinkNotification = blink;
1112 +
1113 +                       this._dbMerge({accountNotifications:this._prefs.accountNotifications});
1114 +               }
1115 +               else
1116 +                       this._dbMerge({blinkNotification:blink});
1117 +       },
1118 +
1119 +       getNotificationSound: function(serviceName) {
1120 +               if((serviceName != undefined) && (serviceName != "sms")) {
1121 +                       if (this._prefs === undefined || this._prefs.accountNotifications === undefined ||
1122 +                               this._prefs.accountNotifications[serviceName] === undefined || 
1123 +                               this._prefs.accountNotifications[serviceName].notificationSound === undefined) 
1124 +                       {
1125 +                               return this._getDefaultPrefs().notificationSound;
1126 +                       } else {
1127 +                               return this._prefs.accountNotifications[serviceName].notificationSound;
1128 +                       }
1129 +               }
1130 +               
1131                 if (this._prefs === undefined || this._prefs.notificationSound === undefined) {
1132                         return this._getDefaultPrefs().notificationSound;
1133                 } else {
1134 @@ -107,11 +176,34 @@
1135                 }
1136         },
1137         
1138 -       setNotificationSound: function(sound) {
1139 -               this._dbMerge({notificationSound:sound});
1140 +       setNotificationSound: function(sound, serviceName) {
1141 +               if((serviceName != undefined) && (serviceName != "sms")) {
1142 +                       if (this._prefs.accountNotifications === undefined)
1143 +                               this._prefs.accountNotifications = {};
1144 +
1145 +                       if (this._prefs.accountNotifications[serviceName] === undefined)
1146 +                               this._prefs.accountNotifications[serviceName] = {};
1147 +                       
1148 +                       this._prefs.accountNotifications[serviceName].notificationSound = sound;
1149 +
1150 +                       this._dbMerge({accountNotifications:this._prefs.accountNotifications});
1151 +               }
1152 +               else
1153 +                       this._dbMerge({notificationSound:sound});
1154         },
1155         
1156 -       getRingtone: function() {
1157 +       getRingtone: function(serviceName) {
1158 +               if((serviceName != undefined) && (serviceName != "sms")) {
1159 +                       if (this._prefs === undefined || this._prefs.accountNotifications === undefined ||
1160 +                               this._prefs.accountNotifications[serviceName] === undefined || 
1161 +                               this._prefs.accountNotifications[serviceName].ringtone === undefined)  
1162 +                       {
1163 +                               return this._getDefaultPrefs().ringtone;
1164 +                       } else {
1165 +                               return this._prefs.accountNotifications[serviceName].ringtone;
1166 +                       }
1167 +               }
1168 +               
1169                 if (this._prefs === undefined || this._prefs.ringtone === undefined) {
1170                         return this._getDefaultPrefs().ringtone;
1171                 } else {
1172 @@ -119,11 +211,163 @@
1173                 }
1174         },
1175         
1176 -       setRingtone: function(ringtone) {
1177 +       setRingtone: function(ringtone, serviceName) {
1178                 if (ringtone === undefined) {
1179                         ringtone = {};
1180                 }
1181 -               this._dbMerge({ringtone:ringtone});
1182 +
1183 +               if((serviceName != undefined) && (serviceName != "sms")) {
1184 +                       if (this._prefs.accountNotifications === undefined)
1185 +                               this._prefs.accountNotifications = {};
1186 +
1187 +                       if (this._prefs.accountNotifications[serviceName] === undefined)
1188 +                               this._prefs.accountNotifications[serviceName] = {};
1189 +                       
1190 +                       this._prefs.accountNotifications[serviceName].ringtone = ringtone;
1191 +
1192 +                       this._dbMerge({accountNotifications:this._prefs.accountNotifications});
1193 +               }
1194 +               else
1195 +                       this._dbMerge({ringtone:ringtone});
1196 +       },
1197 +
1198 +       getRepeatInterval: function(serviceName) {
1199 +               if((serviceName != undefined) && (serviceName != "sms")) {
1200 +                       if (this._prefs === undefined || this._prefs.accountNotifications === undefined ||
1201 +                               this._prefs.accountNotifications[serviceName] === undefined || 
1202 +                               this._prefs.accountNotifications[serviceName].repeatInterval === undefined)
1203 +                       {
1204 +                               return this._getDefaultPrefs().repeatInterval;
1205 +                       } else {
1206 +                               return this._prefs.accountNotifications[serviceName].repeatInterval;
1207 +                       }
1208 +               }
1209 +               
1210 +               if (this._prefs === undefined || this._prefs.repeatInterval === undefined) {
1211 +                       return this._getDefaultPrefs().repeatInterval;
1212 +               } else {
1213 +                       return this._prefs.repeatInterval;
1214 +               }
1215 +       },
1216 +       
1217 +       setRepeatInterval: function(interval, serviceName) {
1218 +               if((serviceName != undefined) && (serviceName != "sms")) {
1219 +                       if (this._prefs.accountNotifications === undefined)
1220 +                               this._prefs.accountNotifications = {};
1221 +               
1222 +                       if (this._prefs.accountNotifications[serviceName] === undefined)
1223 +                               this._prefs.accountNotifications[serviceName] = {};
1224 +                       
1225 +                       this._prefs.accountNotifications[serviceName].repeatInterval = interval;
1226 +
1227 +                       this._dbMerge({accountNotifications:this._prefs.accountNotifications});
1228 +               }
1229 +               else
1230 +                       this._dbMerge({repeatInterval:interval});
1231 +       },
1232 +       
1233 +       getRepeatLimit: function(serviceName) {
1234 +               if((serviceName != undefined) && (serviceName != "sms")) {
1235 +                       if (this._prefs === undefined || this._prefs.accountNotifications === undefined ||
1236 +                               this._prefs.accountNotifications[serviceName] === undefined || 
1237 +                               this._prefs.accountNotifications[serviceName].repeatLimit === undefined)
1238 +                       {
1239 +                               return this._getDefaultPrefs().repeatLimit;
1240 +                       } else {
1241 +                               return this._prefs.accountNotifications[serviceName].repeatLimit;
1242 +                       }
1243 +               }
1244 +               
1245 +               if (this._prefs === undefined || this._prefs.repeatLimit === undefined) {
1246 +                       return this._getDefaultPrefs().repeatLimit;
1247 +               } else {
1248 +                       return this._prefs.repeatLimit;
1249 +               }
1250 +       },
1251 +       
1252 +       setRepeatLimit: function(limit, serviceName) {
1253 +               if((serviceName != undefined) && (serviceName != "sms")) {
1254 +                       if(this._prefs.accountNotifications[serviceName] === undefined)
1255 +                               this._prefs.accountNotifications[serviceName] = {};
1256 +                       
1257 +                       this._prefs.accountNotifications[serviceName].repeatLimit = limit;
1258 +
1259 +                       this._dbMerge({accountNotifications:this._prefs.accountNotifications});
1260 +               }
1261 +               else
1262 +                       this._dbMerge({repeatLimit:limit});
1263 +       },
1264 +       
1265 +       getPrependForward: function() {
1266 +               if (this._prefs === undefined || this._prefs.prependForward === undefined) {
1267 +                       return this._getDefaultPrefs().prependForward;
1268 +               } else {
1269 +                       return this._prefs.prependForward;
1270 +               }
1271 +       },
1272 +       
1273 +       setPrependForward: function(forward) {
1274 +               this._dbMerge({prependForward:forward});
1275 +       },
1276 +
1277 +       getMessageGreeting: function() {
1278 +               if (this._prefs === undefined || this._prefs.messageGreeting === undefined) {
1279 +                       return this._getDefaultPrefs().messageGreeting;
1280 +               } else {
1281 +                       return this._prefs.messageGreeting;
1282 +               }
1283 +       },
1284 +       
1285 +       setMessageGreeting: function(greeting) {
1286 +               this._dbMerge({messageGreeting:greeting});
1287 +       },
1288 +
1289 +       getMessageSignature: function() {
1290 +               if (this._prefs === undefined || this._prefs.messageSignature === undefined) {
1291 +                       return this._getDefaultPrefs().messageSignature;
1292 +               } else {
1293 +                       return this._prefs.messageSignature;
1294 +               }
1295 +       },
1296 +       
1297 +       setMessageSignature: function(signature) {
1298 +               this._dbMerge({messageSignature:signature});
1299 +       },
1300 +
1301 +       getUseAutomaticMsgDrafts: function() {
1302 +               if (this._prefs === undefined || this._prefs.useAutomaticMsgDrafts === undefined) {
1303 +                       return this._getDefaultPrefs().useAutomaticMsgDrafts;
1304 +               } else {
1305 +                       return this._prefs.useAutomaticMsgDrafts;
1306 +               }
1307 +       },
1308 +
1309 +       setUseAutomaticMsgDrafts: function(set) {
1310 +               this._dbMerge({useAutomaticMsgDrafts:set});
1311 +       },
1312 +
1313 +       getUseClipboardMsgDrafts: function() {
1314 +               if (this._prefs === undefined || this._prefs.useClipboardMsgDrafts === undefined) {
1315 +                       return this._getDefaultPrefs().useClipboardMsgDrafts;
1316 +               } else {
1317 +                       return this._prefs.useClipboardMsgDrafts;
1318 +               }
1319 +       },
1320 +       
1321 +       setUseClipboardMsgDrafts: function(set) {
1322 +               this._dbMerge({useClipboardMsgDrafts:set});
1323 +       },
1324 +
1325 +       getUseDeleteConfirmation: function() {
1326 +               if (this._prefs === undefined || this._prefs.useDeleteConfirmation === undefined) {
1327 +                       return this._getDefaultPrefs().useDeleteConfirmation;
1328 +               } else {
1329 +                       return this._prefs.useDeleteConfirmation;
1330 +               }
1331 +       },
1332 +
1333 +       setUseDeleteConfirmation: function(set) {
1334 +               this._dbMerge({useDeleteConfirmation:set});
1335         },
1336         
1337         getUseImmediateMmsRetrieval: function() {
1338 @@ -188,12 +432,22 @@
1339                 return {
1340                                 "_kind": MessagingPrefsService.prefsDB,
1341                                 "enableNotification": true,
1342 -                               "notificationSound":"alert",
1343 +                               "blinkNotification": true,
1344 +                               "notificationSound": "alert",
1345                                 "ringtone": {},
1346 +                               "repeatInterval": 0,
1347 +                               "repeatLimit": 3,
1348 +                               "prependForward": false,
1349 +                               "messageGreeting": "",
1350 +                               "messageSignature": "",
1351                                 "isHistoryViewSelected": true,
1352                                 "showOnlineBuddiesOnly": true,
1353                                 "useImmediateMmsRetrieval": true,
1354 -                               "firstUseMode":true
1355 +                               "firstUseMode": true,
1356 +                               "useAutomaticMsgDrafts": true,
1357 +                               "useClipboardMsgDrafts": false,
1358 +                               "useDeleteConfirmation": true,
1359 +                               "accountNotifications": {}
1360                 };
1361         },
1362  
1363 --- .orig/usr/palm/applications/com.palm.app.messaging/app/controllers/prefsAccountSummary-assistant.js
1364 +++ /usr/palm/applications/com.palm.app.messaging/app/controllers/prefsAccountSummary-assistant.js
1365 @@ -8,13 +8,15 @@
1366          this.Messaging = this.appController.Messaging;      
1367          this.params = params || {};
1368          this.requests = [];
1369 +        this.listSettingChanged = false;
1370                 
1371                 this.handleAddAccountTap = this.handleAddAccountTap.bindAsEventListener(this);
1372 -               this.notificationToggleChanged = this.notificationToggleChanged.bindAsEventListener(this);
1373 +/*             this.notificationToggleChanged = this.notificationToggleChanged.bindAsEventListener(this);
1374                 this.notificationSoundToggleChanged = this.notificationSoundToggleChanged.bindAsEventListener(this);
1375                 this.chooseNotificationRingtone = this.chooseNotificationRingtone.bindAsEventListener(this);
1376                 this.autoDownloadToggleChanged = this.autoDownloadToggleChanged.bindAsEventListener(this);
1377                 this.deliveryReceiptsToggleChanged = this.deliveryReceiptsToggleChanged.bindAsEventListener(this);
1378 +*/
1379      },
1380   
1381      setup: function(){
1382 @@ -33,24 +35,39 @@
1383                 
1384        this.controller.listen('addAccountButton',Mojo.Event.tap, this.handleAddAccountTap);   
1385     
1386 -      this.controller.listen('currentringtonerow',Mojo.Event.tap, this.chooseNotificationRingtone);
1387 +//      this.controller.listen('currentringtonerow',Mojo.Event.tap, this.chooseNotificationRingtone);
1388      },
1389         
1390         cleanup: function() {
1391                 this.controller.stopListening('addAccountButton',Mojo.Event.tap, this.handleAddAccountTap);
1392 -               if (this.saveSMSPrefs) {
1393 +/*             if (this.saveSMSPrefs) {
1394                         this.controller.stopListening('savePrefs', Mojo.Event.tap, this.saveSMSPrefs);
1395                 }
1396           this.controller.stopListening('deliveryReceiptsToggle',Mojo.Event.propertyChange,this.deliveryReceiptsToggleChanged);
1397        this.controller.stopListening('notificationToggle',Mojo.Event.propertyChange,this.notificationToggleChanged);
1398        this.controller.stopListening('notificationSoundSelector',Mojo.Event.propertyChange,this.notificationSoundToggleChanged);                
1399        this.controller.stopListening('autoDownloadToggle',Mojo.Event.propertyChange,this.autoDownloadToggleChanged);
1400 +*/
1401         },
1402  
1403 -       handleAccountsListTap: function(account, template){
1404 +       handleCommand: function(event){
1405 +               if((event.type == Mojo.Event.back) && (this.listSettingChanged)) {
1406 +             event.stopPropagation();
1407 +          event.preventDefault();
1408 +                       this.controller.stageController.swapScene('listview');
1409 +               }
1410 +       },
1411 +       
1412 +       handleAccountsListTap: function(account, template, target){
1413                 var capabilityProvider = this.getMessagingCapabilityProvider(account);
1414                 var accountSettingsUI;
1415                 
1416 +               if(target == "notifications") {
1417 +             this.controller.stageController.pushScene('prefsSetupNotifications', this.Messaging.messagingPrefs, capabilityProvider.serviceName, account.icon.loc_32x32);
1418 +               
1419 +                       return;
1420 +               }
1421 +               
1422                 if (capabilityProvider && capabilityProvider.settingsUI) {
1423                         accountSettingsUI = capabilityProvider.settingsUI;
1424                         
1425 @@ -76,7 +93,7 @@
1426                         
1427                 }
1428                 else if(capabilityProvider && capabilityProvider.serviceName === undefined && capabilityProvider.capabilitySubtype === "SMS"){
1429 -                       //Do nothing when SMS is taped.
1430 +                       this.controller.stageController.pushScene('prefsSetupSMSAccount', this.Messaging);
1431                 }
1432                 else {
1433                         this.controller.stageController.pushScene("accountlogin", {
1434 @@ -105,12 +122,52 @@
1435       **************************************************/
1436      
1437      preferencesSetup: function() {
1438 -      this.prefsAutoSignIn();
1439 +//      this.prefsAutoSignIn();
1440        //this.prefsSmsMmsSetup();
1441 -      this.prefsNotification();
1442 +//      this.prefsNotification();
1443 +      this.prefsDraftsSetup();
1444 +      this.prefsListSetup();
1445 +    },
1446 +    
1447 +    prefsDraftsSetup: function() {
1448 +       var messageDraftsAttributes = {
1449 +                       trueValue: true,
1450 +                       falseValue: false };
1451 +       
1452 +       this.modelMessageDraftsClipboard = {value: this.Messaging.messagingPrefs.getUseClipboardMsgDrafts()};
1453 +
1454 +               this.controller.setupWidget('prefs-clipboard-drafts-toggle', messageDraftsAttributes, this.modelMessageDraftsClipboard);
1455 +      this.controller.listen('prefs-clipboard-drafts-toggle',Mojo.Event.propertyChange, this.prefsDraftsSave.bind(this));      
1456 +
1457 +       this.modelMessageDraftsAutomatic = {value: this.Messaging.messagingPrefs.getUseAutomaticMsgDrafts()};
1458 +       
1459 +       this.controller.setupWidget('prefs-automatic-drafts-toggle', messageDraftsAttributes, this.modelMessageDraftsAutomatic);
1460 +      this.controller.listen('prefs-automatic-drafts-toggle',Mojo.Event.propertyChange, this.prefsDraftsSave.bind(this));      
1461 +    },
1462 +
1463 +    prefsDraftsSave: function() {
1464 +               this.Messaging.messagingPrefs.setUseClipboardMsgDrafts(this.modelMessageDraftsClipboard.value);
1465 +               this.Messaging.messagingPrefs.setUseAutomaticMsgDrafts(this.modelMessageDraftsAutomatic.value);
1466      },
1467 +                   
1468 +    prefsListSetup: function() {
1469 +       var messageDeleteConfirmAttributes = {
1470 +                       trueValue: true,
1471 +                       falseValue: false };
1472 +       
1473 +       this.modelMessageDeleteConfirm = {value: this.Messaging.messagingPrefs.getUseDeleteConfirmation()};
1474 +       
1475 +       this.controller.setupWidget('prefs-delete-confirmation-toggle', messageDeleteConfirmAttributes, this.modelMessageDeleteConfirm);
1476 +      this.controller.listen('prefs-delete-confirmation-toggle',Mojo.Event.propertyChange, this.prefsListSave.bind(this));      
1477 +    },
1478 +
1479 +    prefsListSave: function() {
1480 +               this.listSettingChanged = true;
1481      
1482 -    prefsAutoSignIn: function() {
1483 +               this.Messaging.messagingPrefs.setUseDeleteConfirmation(this.modelMessageDeleteConfirm.value);
1484 +        },
1485 +
1486 +//    prefsAutoSignIn: function() {
1487        /*
1488        var autoSignin = {
1489          modelProperty : 'auto-signin-toggle',
1490 @@ -126,13 +183,14 @@
1491  //        this.controller.get('AutoSignon').observe('mojo-property-change', 
1492  //                     this.autoSignonChange.bind(this));            
1493         */       
1494 -    },
1495 -    
1496 + //   },
1497 +/*    
1498      prefsSmsMmsSetup: function() {
1499 +*/
1500        /************************
1501        * Setup widgets
1502        ************************/
1503 -      var smscAttributes = {
1504 +/*      var smscAttributes = {
1505          inputName: "smscAddressText",
1506          hintText: '',
1507          modelProperty: 'original',
1508 @@ -187,11 +245,11 @@
1509          value: false
1510        };
1511        this.controller.setupWidget('useSettings', mmsSmsUseSettingsAttributes, this.mmsSmsUseSettingsModel);        
1512 -        
1513 +*/        
1514        /*********************************************
1515        * Methods for rendering existing pref values
1516        *********************************************/        
1517 -      this.renderEditSMSCAddress = function(response) {
1518 + /*     this.renderEditSMSCAddress = function(response) {
1519          this.smscModel.original = response.smscAddr;
1520          this.controller.modelChanged(this.smscModel,this);
1521          this.emailGatewayModel.original = response.emailGateway;
1522 @@ -367,7 +425,7 @@
1523  
1524                 this.controller.get('currentringtone').update(file.name);
1525         }
1526 -       
1527 +*/     
1528  //    editAccount: function(targetRow){
1529  //      // iterate through hidden inputs
1530  //      var inputHash = {};
1531 --- .orig/usr/palm/applications/com.palm.app.messaging/app/views/prefsAccountSummary/prefsAccountSummary-scene.html
1532 +++ /usr/palm/applications/com.palm.app.messaging/app/views/prefsAccountSummary/prefsAccountSummary-scene.html
1533 @@ -5,7 +5,7 @@
1534        <div id="prefHeaderText" class="title" x-mojo-loc=''>Preferences &amp; Accounts</div>
1535      </div>
1536    </div>
1537 -
1538 +<!--
1539         <div class="palm-group">
1540                 <div class="palm-group-title" x-mojo-loc=''>
1541                         New message
1542 @@ -20,8 +20,8 @@
1543                                 </div> 
1544                         </div>                
1545                         <div id="notificationSoundContainer">   
1546 -                               <!-- <div class="palm-row-divider"></div> -->
1547 -                               <div id="soundselectrow" class="palm-row" x-mojo-tap-highlight="momentary">
1548 +-->                            <!-- <div class="palm-row-divider"></div> -->
1549 +<!--                           <div id="soundselectrow" class="palm-row" x-mojo-tap-highlight="momentary">
1550                                         <div class="palm-row-wrapper">
1551                                                 <div id="notificationSoundSelector" x-mojo-element="ListSelector"></div>
1552                                         </div>
1553 @@ -53,5 +53,43 @@
1554                 </div>
1555         </div>
1556         <div id="accounts_list" x-mojo-element="AccountsList"></div>
1557 +-->
1558 +
1559 +       <div class="palm-group">
1560 +               <div class="palm-group-title" x-mojo-loc=''>Message Drafts</div>
1561 +               <div class="palm-list">
1562 +                       <div class="palm-row first">
1563 +                               <div class="palm-row-wrapper">
1564 +                                       <div x-mojo-element="ToggleButton" id="prefs-clipboard-drafts-toggle"></div>
1565 +                                       <div class="title" x-mojo-loc=''>Copy to Clipboard</div>
1566 +                               </div>
1567 +                       </div>  
1568 +                       <div class="palm-row last">
1569 +                               <div class="palm-row-wrapper">
1570 +                                       <div x-mojo-element="ToggleButton" id="prefs-automatic-drafts-toggle"></div>
1571 +                                       <div class="title" x-mojo-loc=''>Copy to Message</div>
1572 +                               </div>
1573 +                       </div>  
1574 +               </div>
1575 +       </div>
1576 +       
1577 +       <div x-mojo-loc="" class="palm-info-text">The above settings controls how aborted messages are handled.</div>
1578 +
1579 +       <div class="palm-group">
1580 +               <div class="palm-group-title" x-mojo-loc=''>Message List</div>
1581 +               <div class="palm-list">
1582 +                       <div class="palm-row first">
1583 +                               <div class="palm-row-wrapper">
1584 +                                       <div x-mojo-element="ToggleButton" id="prefs-delete-confirmation-toggle"></div>
1585 +                                       <div class="title" x-mojo-loc=''>Delete Confirmation</div>
1586 +                               </div>
1587 +                       </div>  
1588 +               </div>
1589 +       </div>
1590 +
1591 +       <div id="accounts_list" x-mojo-element="AccountsList" class="show-notifications"></div>
1592 +       
1593 +       <div x-mojo-loc="" class="palm-info-text">IM accounts from same provider share notification preferences.</div>
1594 +       
1595         <div id="addAccountButton" class="palm-button" x-mojo-loc=''>Add IM Account</div>
1596  </div>
1597 \ No newline at end of file
1598 --- .orig/usr/palm/applications/com.palm.app.messaging/sources.json
1599 +++ /usr/palm/applications/com.palm.app.messaging/sources.json
1600 @@ -51,6 +51,12 @@
1601      "source": "app\/controllers\/prefsAccountSummary-assistant.js"
1602    },
1603    {
1604 +    "source": "app\/controllers\/prefsSetupSMSAccount-assistant.js"
1605 +  },   
1606 +  {
1607 +    "source": "app\/controllers\/prefsSetupNotifications-assistant.js"
1608 +  },   
1609 +  {
1610      "source": "app\/controllers\/compose-assistant.js"
1611    },
1612    {