1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc.
  5  *
  6  * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at: https://www.zimbra.com/license
  9  * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15
 10  * have been added to cover use of software over a computer network and provide for limited attribution
 11  * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B.
 12  *
 13  * Software distributed under the License is distributed on an "AS IS" basis,
 14  * WITHOUT WARRANTY OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing rights and limitations under the License.
 16  * The Original Code is Zimbra Open Source Web Client.
 17  * The Initial Developer of the Original Code is Zimbra, Inc.  All rights to the Original Code were
 18  * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015.
 19  *
 20  * All portions of the code are Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 /**
 25  * @overview
 26  */
 27 
 28 /**
 29  * Creates the preferences application.
 30  * @class
 31  * This class represents the application for the preferences UI. This is where the preferences
 32  * hook into the overall application.
 33  * 
 34  * @param	{DwtControl}	container	the control that contains components
 35  * @param	{ZmController}	parentController	the parent window controller (set by the child window)
 36  * 
 37  * @extends		ZmApp
 38  */
 39 ZmPreferencesApp = function(container, parentController) {
 40 	ZmApp.call(this, ZmApp.PREFERENCES, container, parentController);
 41 
 42 	// must be hash for case of multi-accounts
 43 	this._filterRules = {};
 44 	this._outgoingFilterRules = {};
 45 };
 46 
 47 ZmPreferencesApp.prototype = new ZmApp;
 48 ZmPreferencesApp.prototype.constructor = ZmPreferencesApp;
 49 
 50 ZmPreferencesApp.prototype.isZmPreferencesApp = true;
 51 ZmPreferencesApp.prototype.toString = function() { return "ZmPreferencesApp"; };
 52 
 53 
 54 // Organizer and item-related constants
 55 ZmEvent.S_FILTER					= "FILTER";
 56 ZmEvent.S_PREF_ZIMLET				= "PREF_ZIMLET";
 57 ZmEvent.S_PREF_ACCOUNT				= "PREF_ACCOUNT";
 58 ZmEvent.S_PREF_BACKUP				= "PREF_BACKUP";
 59 
 60 // App-related constants
 61 /**
 62  * Defines the "preferences" application.
 63  */
 64 ZmApp.PREFERENCES					= ZmId.APP_PREFERENCES; 
 65 ZmApp.CLASS[ZmApp.PREFERENCES]		= "ZmPreferencesApp";
 66 ZmApp.SETTING[ZmApp.PREFERENCES]	= ZmSetting.OPTIONS_ENABLED;
 67 ZmApp.LOAD_SORT[ZmApp.PREFERENCES]	= 10;
 68 ZmApp.QS_ARG[ZmApp.PREFERENCES]		= "options";
 69 ZmOrganizer.PREF_PAGE				= "PREF_PAGE";
 70 ZmPreferencesApp.QS_ARG_SECTION		= "section";
 71 
 72 // NOTE: This is registered staticly to guarantee that all of the
 73 //       enabled app's preferences will be registered by the time
 74 //       that another app listener gets the launch event and may
 75 //       want to alter those prefs.
 76 ZmPreferencesApp._registerAllPrefs =
 77 function() {
 78 	AjxDispatcher.require("PreferencesCore");
 79 	appCtxt.getAppController().runAppFunction("_registerPrefs");
 80 };
 81 ZmZimbraMail.addAppListener(ZmApp.PREFERENCES, ZmAppEvent.PRE_LAUNCH, new AjxListener(ZmPreferencesApp._registerAllPrefs));
 82 
 83 //
 84 // Public methods
 85 //
 86 
 87 // App API
 88 
 89 ZmPreferencesApp.prototype.launch =
 90 function(params, callback) {
 91 	// first time launch of prefs app should reset active app to "local" account
 92 	if (appCtxt.multiAccounts) {
 93 		appCtxt.accountList.setActiveAccount(appCtxt.accountList.mainAccount);
 94 	}
 95 
 96 	var gotoSection = (params.qsParams && params.qsParams[ZmPreferencesApp.QS_ARG_SECTION]) || "GENERAL";
 97 	callback = new AjxCallback(this, this.gotoSection, [gotoSection, callback]);
 98 
 99 	var loadCallback = new AjxCallback(this, this._handleLoadLaunch, [callback]);
100 	AjxDispatcher.require(["PreferencesCore", "Preferences"], true, loadCallback, null, true);
101 };
102 
103 // Public methods
104 
105 /**
106  * Gets the preferences controller.
107  * 
108  * @return	{ZmPrefController}	the controller
109  */
110 ZmPreferencesApp.prototype.getPrefController =
111 function() {
112 	if (!this._prefController) {
113 		AjxDispatcher.require(["PreferencesCore", "Preferences"]);
114 		this._prefController = new ZmPrefController(this._container, this);
115 	}
116 	return this._prefController;
117 };
118 
119 /**
120  * Gets the filter controller.
121  * 
122  * @return	{ZmFilterController}	the controller
123  */
124 ZmPreferencesApp.prototype.getFilterController =
125 function() {
126 	if (!this._filterController) {
127 		this._filterController = this.getPrefController().getFilterController();
128 	}
129 	return this._filterController;
130 };
131 
132 /**
133  * Gets the filter rules.
134  * 
135  * @param	{String}	[accountName]		the account name or <code>null</code> to use the active account
136  * @return	{ZmFilterRules}		the filter rules
137  */
138 ZmPreferencesApp.prototype.getFilterRules =
139 function(accountName) {
140 	var ac = window.parentAppCtxt || window.appCtxt;
141 	var acct = accountName || ac.getActiveAccount().name;
142 
143 	if (!this._filterRules[acct]) {
144 		this._filterRules[acct] = new ZmFilterRules(acct);
145 	}
146 	return this._filterRules[acct];
147 };
148 
149 /**
150  * Gets the outgoing filter rules.
151  * 
152  * @param	{String}	[accountName]		the account name or <code>null</code> to use the active account
153  * @return	{ZmFilterRules}		the filter rules
154  */
155 ZmPreferencesApp.prototype.getOutgoingFilterRules =
156 function(accountName) {
157 	var ac = window.parentAppCtxt || window.appCtxt;
158 	var acct = accountName || ac.getActiveAccount().name;
159 
160 	if (!this._outgoingFilterRules[acct]) {
161 		this._outgoingFilterRules[acct] = new ZmFilterRules(acct, true);
162 	}
163 	return this._outgoingFilterRules[acct];
164 };
165 
166 ZmPreferencesApp.prototype.modifyNotify =
167 function(modifies, force) {
168 
169 	var sharingView = this._getSharingView();
170 	if (sharingView) {
171 		sharingView.notifyModify(modifies);
172 	}
173 };
174 
175 ZmPreferencesApp.prototype.refresh =
176 function(refresh, addr) {
177     var trustedPage = this.getPreferencesPage("TRUSTED_ADDR");
178     if(trustedPage && addr) {
179         trustedPage.addItem(addr);
180     }
181 	if (!appCtxt.inStartup) {
182 		var sharingView = this._getSharingView();
183 		if (sharingView) {
184 			sharingView.refresh(refresh);
185 		}
186 	}
187 };
188 
189 ZmPreferencesApp.prototype.gotoSection =
190 function(section, callback) {
191 	if (section) {
192 		var prefCtlr = this.getPrefController();
193 		var prefsView = prefCtlr && prefCtlr.getPrefsView();
194 		if (prefsView) {
195 			section = section.toUpperCase();
196 			var overview = this.getOverview();
197 			if (overview) {
198 				overview.setSelected([ZmOrganizer.PREF_PAGE, section].join("_"));
199 			}
200 			prefsView.selectSection(section);
201 		}
202 	}
203 	if (callback && callback.run) {
204 		callback.run();
205 	}
206 };
207 
208 
209 
210 //
211 // Protected methods
212 //
213 
214 // Construction
215 
216 ZmPreferencesApp.prototype._defineAPI =
217 function() {
218 	AjxDispatcher.registerMethod("GetFilterRules", ["PreferencesCore", "Preferences"], new AjxCallback(this, this.getFilterRules));
219 	AjxDispatcher.registerMethod("GetOutgoingFilterRules", ["PreferencesCore", "Preferences"], new AjxCallback(this, this.getOutgoingFilterRules));
220 	AjxDispatcher.registerMethod("GetPrefController", ["PreferencesCore", "Preferences"], new AjxCallback(this, this.getPrefController));
221 	AjxDispatcher.registerMethod("GetFilterController", ["PreferencesCore", "Preferences"], new AjxCallback(this, this.getFilterController));
222 };
223 
224 ZmPreferencesApp.prototype._registerOrganizers =  function() {
225 	ZmOrganizer.registerOrg(ZmOrganizer.PREF_PAGE,
226 							{app:				ZmApp.PREFERENCES,
227 							 orgClass:			"ZmPrefPage",
228 							 orgPackage:		"PreferencesCore",
229 							 treeController:	"ZmPrefPageTreeController",
230 							 labelKey:			"preferences",
231 							 treeType:			ZmOrganizer.PREF_PAGE,
232 							 displayOrder:		100
233 							});
234 
235 };
236 
237 ZmPreferencesApp.prototype._registerOperations =
238 function() {
239 	ZmOperation.registerOp(ZmId.OP_MOBILE_REMOVE, {textKey:"mobileRemoveFromList", image:"Delete"});
240 	ZmOperation.registerOp(ZmId.OP_MOBILE_RESUME_SYNC, {textKey:"mobileResumeSync", image:"ImAvailable"});
241 	ZmOperation.registerOp(ZmId.OP_MOBILE_SUSPEND_SYNC, {textKey:"mobileSuspendSync", image:"Offline"});
242 	ZmOperation.registerOp(ZmId.OP_MOBILE_WIPE, {textKey:"mobileWipe", image:"MobileWipe"}, ZmSetting.MOBILE_POLICY_ENABLED);
243 	ZmOperation.registerOp(ZmId.OP_MOBILE_CANCEL_WIPE, {textKey:"mobileWipeCancel", image:"MobileWipeCancel"}, ZmSetting.MOBILE_POLICY_ENABLED);
244 	ZmOperation.registerOp(ZmId.OP_REVERT_PAGE, {textKey:"restorePage"});
245 
246     /* ZmOperation.registerOp(ZmId.OP_ADD_QUICK_COMMAND, {textKey:"quickCommandAdd", image:"Plus"}, ZmSetting.FILTERS_ENABLED);
247     ZmOperation.registerOp(ZmId.OP_EDIT_QUICK_COMMAND, {textKey:"quickCommandEdit", image:"Edit"}, ZmSetting.FILTERS_ENABLED);
248     ZmOperation.registerOp(ZmId.OP_REMOVE_QUICK_COMMAND, {textKey:"quickCommandRemove", image:"Delete"}, ZmSetting.FILTERS_ENABLED); */
249 };
250 
251 ZmPreferencesApp.prototype._registerSettings =
252 function(settings) {
253 	settings = settings || appCtxt.getSettings();
254 	settings.registerSetting("IMPORT_FOLDER",				{type:ZmSetting.T_PSEUDO, dataType:ZmSetting.D_NONE});
255 	settings.registerSetting("IMPORT_BUTTON",				{type:ZmSetting.T_PSEUDO, dataType:ZmSetting.D_NONE});
256 	settings.registerSetting("EXPORT_FOLDER",				{type:ZmSetting.T_PSEUDO, dataType:ZmSetting.D_NONE});
257 	settings.registerSetting("EXPORT_BUTTON",				{type:ZmSetting.T_PSEUDO, dataType:ZmSetting.D_NONE});
258 	settings.registerSetting("PREF_SECTIONS",				{type:ZmSetting.T_PSEUDO, dataType:ZmSetting.D_HASH, isGlobal:true});
259 	settings.registerSetting("SIGNATURE_MAX_LENGTH",		{name:"zimbraMailSignatureMaxLength", type:ZmSetting.T_COS, dataType:ZmSetting.D_INT, defaultValue:1024});
260 	settings.registerSetting("DISCARD_IN_FILTER_ENABLED",	{name:"zimbraFeatureDiscardInFiltersEnabled", type:ZmSetting.T_COS, dataType:ZmSetting.D_BOOLEAN, defaultValue:true});
261 	settings.registerSetting("FROM_DISPLAY_ENABLED",		{name: "zimbraFeatureFromDisplayEnabled", type: ZmSetting.T_COS, dataType: ZmSetting.D_BOOLEAN, defaultValue: true});
262     //settings.registerSetting("QUICK_COMMAND_LIST",			{name:"zimbraPrefQuickCommand", type: ZmSetting.T_COS, dataType: ZmSetting.D_LIST});
263 };
264 
265 ZmPreferencesApp.prototype._registerApp =
266 function() {
267 	ZmApp.registerApp(ZmApp.PREFERENCES,
268 							 {mainPkg:				"Preferences",
269 							  nameKey:				"preferences",
270 							  icon:					"Preferences",
271 							  textPrecedence:		50,
272 							  chooserTooltipKey:	"goToOptions",
273 							  button:				appCtxt.isChildWindow ? null : ZmAppChooser.B_OPTIONS,
274 							  overviewTrees:		[ZmOrganizer.PREF_PAGE],
275 							  hideZimlets:			true,
276 							  gotoActionCode:		ZmKeyMap.GOTO_OPTIONS,
277 							  chooserSort:			180
278                   });
279 };
280 
281 ZmPreferencesApp.prototype._registerPrefs = function() {
282 
283 	var sections = {
284 
285 		GENERAL: {
286 			title: ZmMsg.general,
287 			templateId: "prefs.Pages#General",
288 			priority: 0,
289 			prefs: [
290 				ZmSetting.LOCALE_NAME,
291                 ZmSetting.COMPOSE_INIT_DIRECTION,
292                 ZmSetting.SHOW_COMPOSE_DIRECTION_BUTTONS,
293 				ZmSetting.FONT_NAME,
294 				ZmSetting.FONT_SIZE,
295 				ZmSetting.PASSWORD,
296 				ZmSetting.SEARCH_INCLUDES_SHARED,
297 				ZmSetting.SEARCH_INCLUDES_SPAM,
298 				ZmSetting.SEARCH_INCLUDES_TRASH,
299 				ZmSetting.OFFLINE_SHOW_ALL_MAILBOXES,
300 				ZmSetting.SHOW_SEARCH_STRING,
301 				ZmSetting.SHOW_SELECTION_CHECKBOX,
302 				ZmSetting.SKIN_NAME,
303 				ZmSetting.CLIENT_TYPE,
304 				ZmSetting.DEFAULT_TIMEZONE,
305                 ZmSetting.DEFAULT_PRINTFONTSIZE,
306 				ZmSetting.OFFLINE_IS_MAILTO_HANDLER,
307 				ZmSetting.SHORT_ADDRESS,
308                 ZmSetting.OFFLINE_UPDATE_NOTIFY //offline
309 			]
310 		},
311 
312         ACCOUNTS: {
313 			icon:           "Accounts",
314 			title:          appCtxt.isOffline ? ZmMsg.personas : ZmMsg.accounts,
315 			templateId:     "prefs.Pages#Accounts",
316 			priority:       9,
317 			precondition:   ZmSetting.MAIL_PREFERENCES_ENABLED,
318 			prefs:          [ ZmSetting.ACCOUNTS, ZmSetting.SAVE_TO_SENT_DELEGATED_TARGET ],
319 			manageDirty:    true,
320 			createView:     function(parent, section, controller) {
321 								return new ZmAccountsPage(parent, section, controller);
322 							}
323 		},
324 
325         FILTERS: {
326 			icon:           "MailRule",
327 			title:          ZmMsg.filterRules,
328 			templateId:     "prefs.Pages#MailFilters",
329 			priority:       50,
330 	        precondition:   [ ZmSetting.MAIL_PREFERENCES_ENABLED, ZmSetting.FILTERS_ENABLED ],
331 			prefs:          [ ZmSetting.FILTERS ],
332 			manageChanges:  true,
333 			createView:     function(parent, section, controller) {
334 								return controller.getFilterController(section).getFilterView();
335 							}
336 		},
337 
338         SIGNATURES: {
339 			icon:           "AddSignature",
340 			title:          ZmMsg.signatures,
341 			templateId:     "prefs.Pages#Signatures",
342 			priority:       51,
343 	        precondition:   [ ZmSetting.MAIL_PREFERENCES_ENABLED, ZmSetting.SIGNATURES_ENABLED ],
344 			prefs:          [ ZmSetting.SIGNATURES, ZmSetting.SIGNATURE_STYLE, ZmSetting.SIGNATURE_ENABLED ],
345 			manageDirty:    true,
346 			createView:     function(parent, section, controller) {
347 								return new ZmSignaturesPage(parent, section, controller);
348 							}
349 		},
350 
351         OUTOFOFFICE: {
352             icon:           "OutOfOffice",
353 			title:          ZmMsg.outOfOffice,
354             priority:       55,
355             templateId:     "prefs.Pages#OutOfOffice",
356 	        precondition:   [ ZmSetting.MAIL_PREFERENCES_ENABLED, ZmSetting.VACATION_MSG_FEATURE_ENABLED ],
357 	        prefs:          [
358 				                ZmSetting.START_DATE_ENABLED,
359 				                ZmSetting.END_DATE_ENABLED,
360 				                ZmSetting.VACATION_DURATION_ENABLED,
361 				                ZmSetting.VACATION_DURATION_ALL_DAY,
362 				                ZmSetting.VACATION_CALENDAR_ENABLED,
363 				                ZmSetting.VACATION_FROM,
364 				                ZmSetting.VACATION_FROM_TIME,
365 								ZmSetting.VACATION_MSG_ENABLED,
366 								ZmSetting.VACATION_MSG,
367 				                ZmSetting.VACATION_EXTERNAL_MSG_ENABLED,
368 								ZmSetting.VACATION_EXTERNAL_MSG,
369 				                ZmSetting.VACATION_EXTERNAL_TYPE,
370                                 ZmSetting.VACATION_EXTERNAL_SUPPRESS,
371 				                ZmSetting.VACATION_CALENDAR_TYPE,
372 								ZmSetting.VACATION_UNTIL,
373 				                ZmSetting.VACATION_UNTIL_TIME
374 				            ],
375             manageDirty:    true,
376 			createView:     function(parent, section, controller) {
377 								AjxDispatcher.require("Alert");
378 								return new ZmMailPrefsPage(parent, section, controller);
379 							}
380         },
381 
382         TRUSTED_ADDR: {
383 			title:          ZmMsg.trustedAddrs,
384 			icon:           "TrustedAddresses",
385 			templateId:     "prefs.Pages#Trusted",
386 			priority:       60,
387 	        precondition:   ZmSetting.MAIL_PREFERENCES_ENABLED,
388 			createView:     function(parent, section, controller) {
389 								return new ZmTrustedPage(parent, section, controller, "Prefs_Pages_TrustedAddresses");
390 							},
391             manageDirty:    true,
392             prefs:          [ ZmSetting.TRUSTED_ADDR_LIST ]
393 		},
394 
395 		SHARING: {
396 			title:          ZmMsg.sharing,
397 			icon:           "SharedContact",
398 			templateId:     "prefs.Pages#SharingPrefPage",
399 			priority:       85,
400 			precondition:   ZmSetting.SHARING_ENABLED,
401 			manageChanges:  true,
402 			createView:     function(parent, section, controller) {
403 								AjxDispatcher.require("Share");
404 								return new ZmSharingPage(parent, section, controller, "Prefs_Pages_Sharing");
405 							}
406 		},
407 
408 		NOTIFICATIONS: {
409 			title:              ZmMsg.notifications,
410 			icon:               "ApptReminder",
411 			templateId:         "prefs.Pages#Notifications",
412 			priority:           88,
413 			precondition:       [ ZmSetting.CALENDAR_ENABLED, ZmSetting.TASKS_ENABLED ],
414 			preconditionAny:    true,
415 			prefs:              [ ZmSetting.CAL_EMAIL_REMINDERS_ADDRESS, ZmSetting.CAL_DEVICE_EMAIL_REMINDERS_ADDRESS ],
416             createView:         function(parent, section, controller) {
417 					                return new ZmNotificationsPage(parent, section, controller);
418 					            }
419 		},
420 
421 		MOBILE: {
422 			title:          ZmMsg.connectedDevicesAndApps,
423 			icon:           "Mobile",
424 			templateId:     "prefs.Pages#MobileDevices",
425 			priority:       90,
426 			precondition:   ZmSetting.MOBILE_SYNC_ENABLED,
427 			manageChanges:  true,
428 			createView:     function(parent, section, controller) {
429 								return new ZmMobileDevicesPage(parent, section, controller);
430 							}
431 		},
432 
433 		IMPORT_EXPORT: {
434 			title:              ZmMsg.importExport,
435 			icon:               "SendReceive",
436 			templateId:         "data.ImportExport#ImportExportPrefPage",
437 			priority:           100,
438 			precondition:       [ ZmSetting.IMPORT_ENABLED, ZmSetting.EXPORT_ENABLED ],
439 			preconditionAny:    true,
440 			prefs:              [
441 									ZmSetting.IMPORT_FOLDER,
442 									ZmSetting.IMPORT_BUTTON,
443 									ZmSetting.EXPORT_FOLDER,
444 									ZmSetting.EXPORT_BUTTON
445 								],
446 			manageChanges:      true,
447 			createView:         function(parent, section, controller) {
448 									AjxDispatcher.require("ImportExport");
449 									return new ZmImportExportPage(parent, section, controller);
450 								}
451 		},
452 
453 		SHORTCUTS: {
454 			title:          ZmMsg.shortcuts,
455 			icon:           "Shortcut",
456 			templateId:     "prefs.Pages#Shortcuts",
457 			priority:       120,
458 			precondition:   ZmSetting.USE_KEYBOARD_SHORTCUTS,
459 			createView:     function(parent, section, controller) {
460 								return new ZmShortcutsPage(parent, section, controller);
461 							}
462 		},
463 
464         PREF_ZIMLETS: {
465 			title:          ZmMsg.zimlets,
466 	        icon:           "Zimlet",
467 			templateId:     "prefs.Pages#Zimlets",
468 			manageDirty:    true,
469             priority:       140,
470 			precondition:   ZmSetting.CHECKED_ZIMLETS_ENABLED,
471 			prefs:          [
472 								ZmSetting.CHECKED_ZIMLETS,
473 				                ZmSetting.OFFLINE_ZIMLET_SYNC_ACCOUNT_ID
474 							],
475             createView:     function(parent, section, controller) {
476 								return new ZmZimletsPage(parent, section, controller);
477 							}
478 		}
479 	};
480 
481     if (appCtxt.isOffline) {
482         sections["BACKUP"] = {
483 			title:          ZmMsg.offlineBackups,
484 			icon:           "backup",
485             manageDirty:    true,
486 			templateId:     "prefs.Pages#BackUp",
487 			priority:       130,
488             prefs:          [
489 				                ZmSetting.OFFLINE_BACKUP_NOW_BUTTON,
490 				                ZmSetting.OFFLINE_BACKUP_INTERVAL,
491 				                ZmSetting.OFFLINE_BACKUP_PATH,
492 				                ZmSetting.OFFLINE_BACKUP_KEEP,
493 				                ZmSetting.OFFLINE_BACKUP_ACCOUNT_ID,
494 				                ZmSetting.OFFLINE_BACKUP_RESTORE
495 				            ],
496 			createView:     function(parent, section, controller) {
497 								return new ZmBackupPage(parent, section, controller);
498 							}
499 		}
500     }
501 
502 	if (appCtxt.get(ZmSetting.CHAT_FEATURE_ENABLED)) {
503 		ZmPref.registerPref("CHAT_ENABLED", {
504 			displayName:		ZmMsg.chatFeatureStatus,
505 			displayContainer:	ZmPref.TYPE_RADIO_GROUP,
506 			orientation:		ZmPref.ORIENT_VERTICAL,
507 			displayOptions:		[ZmMsg.chatFeatureEnabled, ZmMsg.chatFeatureDisabled],
508 			options:			[true, false]
509 		});
510 
511 		ZmPref.registerPref("CHAT_PLAY_SOUND", {
512 			displayName:		ZmMsg.chatPlaySound,
513 			displayContainer:	ZmPref.TYPE_CHECKBOX
514 		});
515 
516 		sections["CHAT"] = {
517 			title: ZmMsg.chat,
518 			icon: "Conversation",
519 			templateId: "prefs.Pages#Chat",
520 			priority: 65,
521 			prefs: [
522 				ZmSetting.CHAT_ENABLED,
523 				ZmSetting.CHAT_PLAY_SOUND
524 			]
525 		}
526 	}
527 
528 
529 	for (var id in sections) {
530 		ZmPref.registerPrefSection(id, sections[id]);
531 	}
532 
533 	ZmPref.registerPref("CLIENT_TYPE", {
534 		displayName:		ZmMsg.clientType,
535 		displayContainer:	ZmPref.TYPE_RADIO_GROUP,
536 		orientation:		ZmPref.ORIENT_VERTICAL,
537 		displayOptions: 	[ZmMsg.clientAdvanced, ZmMsg.clientStandard],
538 		options: 			[ZmSetting.CLIENT_ADVANCED, ZmSetting.CLIENT_STANDARD]
539 	});
540 
541 	ZmPref.registerPref("COMPOSE_AS_FORMAT", {
542 		displayName:		ZmMsg.composeUsing,
543 		displayContainer:	ZmPref.TYPE_RADIO_GROUP,
544 		orientation:		ZmPref.ORIENT_VERTICAL,
545 		displayOptions: 	[ZmMsg.composeAsHTML, ZmMsg.composeAsText],
546 		options: 			[ZmSetting.COMPOSE_HTML, ZmSetting.COMPOSE_TEXT],
547 		precondition:		ZmSetting.HTML_COMPOSE_ENABLED,
548 		inputId:            ["COMPOSE_AS_HTML", "COMPOSE_AS_TEXT"]
549 	});
550 
551 	ZmPref.registerPref("COMPOSE_INIT_FONT_COLOR", {
552 		displayOptions: 	["rgb(0, 0, 0)"],
553 		displayContainer:	ZmPref.TYPE_COLOR,
554 		precondition:		ZmSetting.HTML_COMPOSE_ENABLED
555 	});
556 
557 	var styles=[],names=[];
558 	for (var key in ZmPref.FONT_FAMILY) {
559 		var obj = ZmPref.FONT_FAMILY[key];
560 		styles.push(obj.value);
561 		names.push(obj.name);
562 	}
563 
564 	ZmPref.registerPref("COMPOSE_INIT_FONT_FAMILY", {
565 		displayName:		ZmMsg.defaultFontSettings,
566 		displayContainer:	ZmPref.TYPE_SELECT,
567 		displayOptions: 	names,
568 		options: 			styles,
569 		precondition:		[ ZmSetting.HTML_COMPOSE_ENABLED, ZmSetting.NOTEBOOK_ENABLED ],
570 		preconditionAny:    true,
571 		approximateFunction: function(id) {
572 			// Choose the style that comes closest, or the first if none is found
573 			if (AjxUtil.indexOf(styles, id) != -1) {
574 				return id;
575 			}
576 			return ZmPref._normalizeFontId(id);
577 		}
578 	});
579 
580     var fontSizes = [ 8, 9, 10, 11, 12, 13, 14, 16, 18, 24, 36, 48 ],   // match what TinyMCE provides
581         fontSizeOptions = AjxUtil.map(fontSizes, function(fontSize) {
582             return AjxMessageFormat.format(ZmMsg.pt, fontSize); // pref page version (localized)
583         }),
584         fontSizeValueOptions = AjxUtil.map(fontSizes, function(fontSize) {
585             return fontSize + 'pt'; // server version
586         });
587 
588     var getZimbraAccountList = function(){
589         var visAccts = appCtxt.accountList.visibleAccounts;
590         var accts = [];
591         accts.push(ZmMsg.zimletPrefDontSync);
592         for (var k=0; k<visAccts.length; k++) {
593             if(visAccts[k].isZimbraAccount && !visAccts[k].isMain) {
594                 accts.push([ZmMsg.zimletPrefSyncWith, " ", visAccts[k].name].join(""));
595             }
596         }
597         return accts;
598     };
599     var getZimbraAccountIds = function(){
600         var visAccts = appCtxt.accountList.visibleAccounts;
601         var accts = [];
602         accts.push("");
603         for (var k=0; k<visAccts.length; k++) {
604             if(visAccts[k].isZimbraAccount && !visAccts[k].isMain) {
605                 accts.push(visAccts[k].id);
606             }
607         }
608         return accts;
609 
610     };
611 	ZmPref.registerPref("COMPOSE_INIT_FONT_SIZE", {
612 		displayName:		null,
613 		displayContainer:	ZmPref.TYPE_SELECT,
614 		displayOptions: 	fontSizeOptions,
615         options:            fontSizeValueOptions,
616 		precondition:		ZmSetting.HTML_COMPOSE_ENABLED
617 	});
618 
619 	ZmPref.registerPref("COMPOSE_SAME_FORMAT", {
620 		displayName:		ZmMsg.replyForwardInSameFormat,
621 		displayContainer:	ZmPref.TYPE_CHECKBOX
622 	});
623 
624     ZmPref.registerPref("CHECKED_ZIMLETS", {
625 		displayName:		ZmMsg.zimlets,
626 		displayContainer:	ZmPref.TYPE_CUSTOM
627 	});
628 
629     ZmPref.registerPref("OFFLINE_ZIMLET_SYNC_ACCOUNT_ID", {
630 		displayName:		ZmMsg.zimletSyncPref,
631 		displayContainer:	ZmPref.TYPE_SELECT,
632         displayOptions:     getZimbraAccountList(),
633         options:            getZimbraAccountIds()
634 	});
635 
636     ZmPref.registerPref("DEFAULT_TIMEZONE", {
637         displayName:		ZmMsg.selectTimezone,
638         displayContainer:	ZmPref.TYPE_SELECT,
639         displayParams:		{ layout: DwtMenu.LAYOUT_SCROLL, maxRows:ZmPref.MAX_ROWS },
640         displayOptions:		AjxTimezone.getZonePreferences(),
641         options:			AjxTimezone.getZonePreferencesOptions()
642     });
643 
644     ZmPref.registerPref("DEFAULT_PRINTFONTSIZE", {
645 		displayName:		ZmMsg.printFontSizePref,
646 		displayContainer:	ZmPref.TYPE_SELECT,
647 		displayOptions: 	fontSizeOptions,
648         options:            fontSizeValueOptions
649 	});
650 
651     ZmPref.registerPref("EXPORT_FOLDER", {
652         displayContainer:	ZmPref.TYPE_CUSTOM
653     });
654 
655     ZmPref.registerPref("EXPORT_BUTTON", {
656         displayName:		ZmMsg._export,
657         displayContainer:	ZmPref.TYPE_CUSTOM
658     });
659 
660 	ZmPref.registerPref("FORWARD_INCLUDE_WHAT", {
661 		displayName:		ZmMsg.forwardInclude,
662 		displayContainer:	ZmPref.TYPE_SELECT,
663 		displayOptions:		[ZmMsg.includeInBody, ZmMsg.includeOriginalAsAttach],
664 		options:			[ZmSetting.INC_BODY, ZmSetting.INC_ATTACH],
665         setFunction:		ZmPref.setIncludeOrig,
666 		initFunction:		ZmPref.initIncludeWhat,
667 		changeFunction:		ZmPref.onChangeIncludeWhat
668 	});
669 
670 	ZmPref.registerPref("FORWARD_USE_PREFIX", {
671 		displayName:		ZmMsg.usePrefix,
672 		displayContainer:	ZmPref.TYPE_CHECKBOX,
673         setFunction:		ZmPref.setIncludeOrig
674 	});
675 
676 	ZmPref.registerPref("FORWARD_INCLUDE_HEADERS", {
677 		displayName:		ZmMsg.includeHeaders,
678 		displayContainer:	ZmPref.TYPE_CHECKBOX,
679         setFunction:		ZmPref.setIncludeOrig
680 	});
681 
682 	ZmPref.registerPref("IMPORT_FOLDER", {
683 		loadFunction:       ZmPref.loadCsvFormats,
684 		displayContainer:	ZmPref.TYPE_CUSTOM
685 	});
686 	ZmPref.registerPref("IMPORT_BUTTON", {
687 		displayName:		ZmMsg._import,
688 		displayContainer:	ZmPref.TYPE_CUSTOM
689 	});
690 
691 	ZmPref.registerPref("LOCALE_NAME", {
692 		displayName:		ZmMsg.selectLanguage,
693 		displayContainer:	ZmPref.TYPE_LOCALES,
694 		precondition:		ZmSetting.LOCALE_CHANGE_ENABLED
695 	});
696 
697     ZmPref.registerPref("COMPOSE_INIT_DIRECTION", {
698         displayName:		ZmMsg.composeDirectionLabel,
699         displayContainer:	ZmPref.TYPE_SELECT,
700         displayOptions:		[ZmMsg.directionLTR, ZmMsg.directionRTL],
701         options:			[ZmSetting.LTR, ZmSetting.RTL]
702     });
703 
704     ZmPref.registerPref("SHOW_COMPOSE_DIRECTION_BUTTONS", {
705         displayName:		ZmMsg.showDirectionButtons,
706         displayContainer:	ZmPref.TYPE_CHECKBOX
707     });
708 
709 	ZmPref.registerPref("FONT_NAME", {
710 		displayName:		ZmMsg.selectFong,
711 		displayContainer:	ZmPref.TYPE_FONT
712 	});
713 
714 	ZmPref.registerPref("FONT_SIZE", {
715 		displayName:		ZmMsg.selectFontSize, //this was never defined in ZmMsg in the above case (font_name) and see the typo there too. So not sure what's this for.
716 		displayContainer:	ZmPref.TYPE_FONT_SIZE
717 	});
718 
719 	var markReadTime = AjxMessageFormat.format(ZmMsg.messageReadTime, DwtId.makeId(ZmId.WIDGET_INPUT, ZmId.OP_MARK_READ));
720 	ZmPref.registerPref("MARK_MSG_READ", {
721 		displayName:		ZmMsg.messageReadLabel,
722 		displayContainer:	ZmPref.TYPE_RADIO_GROUP,
723 		displayFunction:	ZmPref.markMsgReadDisplay,
724         orientation:        ZmPref.ORIENT_VERTICAL,
725         displayOptions:     [ZmMsg.messageReadNow, markReadTime, ZmMsg.messageReadNone],
726         options:            [ZmSetting.MARK_READ_NOW, ZmSetting.MARK_READ_TIME, ZmSetting.MARK_READ_NONE],
727         valueFunction:		ZmPref.markMsgReadValue
728     });
729 
730 	ZmPref.registerPref("NEW_WINDOW_COMPOSE", {
731 		displayName:		ZmMsg.composeInNewWin,
732 		displayContainer:	ZmPref.TYPE_CHECKBOX,
733 		precondition:		[ ZmSetting.MAIL_ENABLED, ZmSetting.DETACH_COMPOSE_ENABLED ]
734 	});
735 
736     ZmPref.registerPref("MAIL_MANDATORY_SPELLCHECK", {
737 		displayName:		ZmMsg.mandatorySpellcheck,
738 		displayContainer:	ZmPref.TYPE_CHECKBOX		
739 	});
740 
741 	ZmPref.registerPref("PAGE_SIZE", {
742 		displayContainer:	ZmPref.TYPE_SELECT,
743 		displayOptions:		["25", "50", "100", "200"]
744 	});
745 
746 	ZmPref.registerPref("PASSWORD", {
747 		displayName:		ZmMsg.changePassword,
748 		displayContainer:	ZmPref.TYPE_PASSWORD,
749 		precondition:		ZmSetting.CHANGE_PASSWORD_ENABLED
750 	});
751 
752 	ZmPref.registerPref("SHARING", {
753 		displayContainer:	ZmPref.TYPE_CUSTOM
754 	});
755 
756 	ZmPref.registerPref("SHORT_ADDRESS", {
757 		displayName:		ZmMsg.shortAddress,
758 		displayContainer:	ZmPref.TYPE_CHECKBOX
759 	});
760 
761 	
762 	if (appCtxt.isOffline) {
763 		ZmPref.registerPref("OFFLINE_IS_MAILTO_HANDLER", {
764 			displayName:		ZmMsg.offlineAllowMailTo,
765 			displayContainer:	ZmPref.TYPE_CHECKBOX
766 		});
767 
768         ZmPref.registerPref("OFFLINE_BACKUP_ACCOUNT_ID", {
769             displayName:		ZmMsg.offlineBackUpAccounts,
770             displayContainer:	ZmPref.TYPE_CUSTOM
771         });
772 
773         ZmPref.registerPref("OFFLINE_BACKUP_RESTORE", {
774             displayContainer:	ZmPref.TYPE_CUSTOM
775         });
776 
777         ZmPref.registerPref("OFFLINE_BACKUP_NOW_BUTTON", {
778             displayName:		ZmMsg.offlineBackUpButton,
779             displayContainer:	ZmPref.TYPE_CUSTOM
780         });
781 
782         ZmPref.registerPref("OFFLINE_BACKUP_INTERVAL", {
783             displayName:		ZmMsg.offlineBackUpInterval,
784             displayContainer:	ZmPref.TYPE_SELECT,
785             displayOptions:		[ZmMsg.pollNever, ZmMsg.everyDay, ZmMsg.everyWeek, ZmMsg.everyMonth],
786             options:			[0, 86400000, 604800000, 2628000000]
787         });
788 
789         ZmPref.registerPref("OFFLINE_BACKUP_PATH", {
790             displayName:		ZmMsg.offlineBackUpPath,
791             displayContainer:	ZmPref.TYPE_INPUT
792         });
793 
794         ZmPref.registerPref("OFFLINE_BACKUP_KEEP", {
795             displayName:		ZmMsg.offlineBackUpKeep,
796             displayContainer:	ZmPref.TYPE_SELECT,
797             displayOptions:		["1", "2", "3", "4", "5"]
798         });
799 
800         ZmPref.registerPref("OFFLINE_UPDATE_NOTIFY", {
801             displayName:		ZmMsg.offlineUpdateNotify,
802 		    displayContainer:	ZmPref.TYPE_SELECT,
803             displayOptions:		[ZmMsg.offlineUpdateRelease, ZmMsg.offlineUpdateBeta],
804             options:    		["release", "beta"]
805         });
806 
807 	}
808 
809 	// Polling Interval Options - Dynamically constructed according to MIN_POLLING_INTERVAL,POLLING_INTERVAL
810     var neverValue = 525600;
811     var numOptions = 10;
812 	var options = [neverValue];
813     var displayOptions = [ZmMsg.pollManually];
814     var pollInstant = appCtxt.get(ZmSetting.INSTANT_NOTIFY) ? true : false;
815 
816     if (pollInstant) {
817         options.push(appCtxt.get(ZmSetting.INSTANT_NOTIFY_INTERVAL));
818         displayOptions.push(ZmMsg.pollInstant);
819     }
820 
821     var startValue = ZmPref.pollingIntervalDisplay(appCtxt.get(ZmSetting.MIN_POLLING_INTERVAL));
822 	startValue = (startValue < 1) ? 1 : Math.round(startValue);
823 
824 	var pollInterval = ZmPref.pollingIntervalDisplay(appCtxt.get(ZmSetting.POLLING_INTERVAL));
825 	pollInterval = Math.round(pollInterval);
826 
827 	while (startValue <= numOptions) {
828 		options.push(startValue);
829 		startValue++;
830 	}
831 	startValue = startValue - 1;
832 
833 	var count = options.length;
834 	while (count < numOptions) {
835 		startValue = startValue + 5;
836 		options.push(startValue);
837 		count++;
838 	}
839 
840 	if (pollInterval > startValue && pollInterval !=neverValue && (pollInstant && pollInterval != appCtxt.get(ZmSetting.INSTANT_NOTIFY_INTERVAL))) {
841         //pollInterval may have been set by admin
842 		var p = pollInterval % 5;
843 		p = (p == 0) ? pollInterval : ((pollInterval / 5 + 1) * 5);
844         options.push(p);
845 	} else {
846 		startValue = startValue + 5;
847 		options.push(startValue);
848 	}
849 
850 	while (displayOptions.length <= count) {
851 		displayOptions.push(ZmMsg.pollEveryNMinutes);
852 	}
853 
854 	ZmPref.registerPref("POLLING_INTERVAL", {
855 		displayName:		ZmMsg.pollingInterval,
856 		displayContainer:	ZmPref.TYPE_SELECT,
857 		displayOptions:		displayOptions,
858 		//displayOptions:		[ ZmMsg.pollNever, ZmMsg.pollEveryNMinutes, ZmMsg.pollEveryNMinutes, ZmMsg.pollEveryNMinutes, ZmMsg.pollEveryNMinutes, ZmMsg.pollEveryNMinutes ],
859 		// NOTE: 525600 is the number of minutes in a year. I think that's a
860 		//       reasonable value for "never" since the server must have
861 		//       *some* number.
862 		options:			 options,
863 		approximateFunction: ZmPref.approximateInterval,
864 		displayFunction:	 ZmPref.pollingIntervalDisplay,
865 		valueFunction:	 	 ZmPref.pollingIntervalValue,
866 		validationFunction:  ZmPref.validatePollingInterval
867 	});
868 
869 	ZmPref.registerPref("REPLY_INCLUDE_WHAT", {
870 		displayName:		ZmMsg.replyInclude,
871 		displayContainer:	ZmPref.TYPE_SELECT,
872 		displayOptions:		[ZmMsg.dontInclude,
873 							ZmMsg.includeInBody,
874 							ZmMsg.smartInclude,
875 							ZmMsg.includeOriginalAsAttach],
876 		options:			[ZmSetting.INC_NONE,
877 							ZmSetting.INC_BODY,
878 							ZmSetting.INC_SMART,
879 							ZmSetting.INC_ATTACH],
880 		setFunction:		ZmPref.setIncludeOrig,
881 		initFunction:		ZmPref.initIncludeWhat,
882 		changeFunction:		ZmPref.onChangeIncludeWhat
883 	});
884 
885 	ZmPref.registerPref("REPLY_USE_PREFIX", {
886 		displayName:		ZmMsg.usePrefix,
887 		displayContainer:	ZmPref.TYPE_CHECKBOX,
888 		setFunction:		ZmPref.setIncludeOrig
889 	});
890 
891 	ZmPref.registerPref("REPLY_INCLUDE_HEADERS", {
892 		displayName:		ZmMsg.includeHeaders,
893 		displayContainer:	ZmPref.TYPE_CHECKBOX,
894 		setFunction:		ZmPref.setIncludeOrig
895 	});
896 
897 	ZmPref.registerPref("REPLY_PREFIX", {
898 		displayName:		ZmMsg.prefix,
899 		displayContainer:	ZmPref.TYPE_RADIO_GROUP,
900 		orientation:		ZmPref.ORIENT_HORIZONTAL,
901 		displayOptions:		[">", "|"]
902 	});
903 
904 	ZmPref.registerPref("SAVE_TO_SENT", {
905 		displayName:		ZmMsg.saveToSent,
906 		displayContainer:	ZmPref.TYPE_CHECKBOX,
907 		precondition:		ZmSetting.MAIL_ENABLED,
908 		changeFunction:		AjxCallback.simpleClosure(ZmPref.onChangeConfirm, null, ZmMsg.saveToSentWarning, ZmPref.getSendToFiltersActive, true, new AjxCallback(null, ZmPref.setFormValue, ["SAVE_TO_SENT", true]))
909 	});
910 
911 	ZmPref.registerPref("SAVE_TO_SENT_DELEGATED_TARGET", {
912 		displayName:		ZmMsg.saveToSentDelegatedTarget,
913 		displayContainer:	ZmPref.TYPE_RADIO_GROUP,
914 		orientation:		ZmPref.ORIENT_VERTICAL,
915 		displayOptions:		[ZmMsg.saveToSentDelegatedOwner,
916 							ZmMsg.saveToSentDelegatedSender,
917 							ZmMsg.saveToSentDelegatedBoth,
918 							ZmMsg.saveToSentDelegatedNone],
919 		options:			["owner", "sender", "both", "none"],
920 		precondition:		ZmSetting.MAIL_ENABLED
921 	});
922 
923 	ZmPref.registerPref("SEARCH_INCLUDES_SHARED", {
924 		displayName:		ZmMsg.includeSharedItems,
925 		displayContainer:	ZmPref.TYPE_CHECKBOX,
926 		precondition:		ZmSetting.SHARING_ENABLED
927 	});
928 	
929 	ZmPref.registerPref("SEARCH_INCLUDES_SPAM", {
930 		displayName:		ZmMsg.includeJunkFolder,
931 		displayContainer:	ZmPref.TYPE_CHECKBOX,
932 		precondition:		[ ZmSetting.MAIL_ENABLED, ZmSetting.SPAM_ENABLED ]
933 	});
934 
935 	ZmPref.registerPref("SEARCH_INCLUDES_TRASH", {
936 		displayName:		ZmMsg.includeTrashFolder,
937 		displayContainer:	ZmPref.TYPE_CHECKBOX,
938 		precondition:		[ ZmSetting.MAIL_ENABLED, ZmSetting.CONTACTS_ENABLED ],
939 		preconditionAny:    true
940 	});
941 
942 	ZmPref.registerPref("SHOW_FRAGMENTS", {
943 		displayName:		ZmMsg.showFragments,
944 		displayContainer:	ZmPref.TYPE_CHECKBOX
945 	});
946 
947 	ZmPref.registerPref("COLOR_MESSAGES", {
948 		displayName:		ZmMsg.colorMessages,
949 		displayContainer:	ZmPref.TYPE_CHECKBOX
950 	});
951 
952 	if (appCtxt.isOffline) {
953 		ZmPref.registerPref("OFFLINE_SHOW_ALL_MAILBOXES", {
954 			displayName:		ZmMsg.showAllMailboxes,
955 			displayContainer:	ZmPref.TYPE_CHECKBOX
956 		});
957 	}
958 
959 	ZmPref.registerPref("SHOW_SEARCH_STRING", {
960 		displayName:		ZmMsg.showSearchString,
961 		displayContainer:	ZmPref.TYPE_CHECKBOX
962 	});
963 
964 	ZmPref.registerPref("SHOW_SELECTION_CHECKBOX", {
965 		displayName:		ZmMsg.showSelectionString,
966 		displayContainer:	ZmPref.TYPE_CHECKBOX
967 	});
968 
969 	ZmPref.registerPref("SKIN_NAME", {
970 		displayName:		ZmMsg.selectSkin,
971 		displayContainer:	ZmPref.TYPE_SELECT,
972 		displayOptions:		[],
973 		options:			[],
974 		loadFunction:		ZmPref.loadSkins,
975 		precondition:		ZmSetting.SKIN_CHANGE_ENABLED
976 	});
977 
978 	ZmPref.registerPref("VIEW_AS_HTML", {
979 		displayName:		ZmMsg.displayMail,
980 		displayContainer:	ZmPref.TYPE_RADIO_GROUP,
981 		orientation:		ZmPref.ORIENT_VERTICAL,
982 		displayOptions:		[ZmMsg.displayAsHTML, ZmMsg.displayAsText],
983 		options:			[true, false]
984 	});
985 };
986 
987 // other
988 
989 ZmPreferencesApp.prototype._handleLoadLaunch =
990 function(callback) {
991 	var respCallback = new AjxCallback(this, this._handleResponseLaunch, [callback]);
992 	appCtxt.getSettings().loadPreferenceData(respCallback);
993 };
994 
995 ZmPreferencesApp.prototype._handleResponseLaunch =
996 function(callback) {
997 	AjxDispatcher.run("GetPrefController").show();
998 	if (callback) {
999 		callback.run();
1000 	}
1001 };
1002 
1003 ZmPreferencesApp.prototype._getSharingView =
1004 function() {
1005 	var sharingSection = this.getPreferencesPage("SHARING");
1006 	return (sharingSection && sharingSection.view);
1007 };
1008 
1009 ZmPreferencesApp.prototype.getPreferencesPage =
1010 function(id) {
1011 	if (!this._prefController) {
1012 		return null;
1013 	}
1014 	var prefCtlr = this.getPrefController();
1015 	var prefsView = prefCtlr && prefCtlr.getPrefsView();
1016 	return prefsView && prefsView.getView(id);
1017 };
1018 
1019 // needed to hide zimlet tree view for multi-account
1020 ZmPreferencesApp.prototype._getOverviewParams =
1021 function() {
1022 	var params = ZmApp.prototype._getOverviewParams.call(this);
1023 	params.omit = {};
1024 	params.omit[ZmOrganizer.ID_ZIMLET] = true;
1025 	params.actionSupported = false;
1026 	return params;
1027 };
1028 
1029 ZmPreferencesApp.getFilterRulesController =
1030 function(outgoing) {
1031     var prefController = AjxDispatcher.run("GetPrefController");
1032     if (prefController && prefController.getPrefsView()) {
1033         var filterController = prefController.getFilterController();
1034         return outgoing ? filterController.getOutgoingFilterRulesController() : filterController.getIncomingFilterRulesController();
1035     }
1036 
1037     return null;
1038 };
1039 
1040 ZmPreferencesApp.prototype.getNewButtonProps =
1041 function (){
1042     return {hidden:true};
1043 }
1044