Completed
Push — master ( 51b9e4...c7e97b )
by Rain
01:27
created

ComposePopupView.addAttachmentHelper   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 14
rs 9.4285
1
2
var
3
	window = require('window'),
4
	_ = require('_'),
5
	$ = require('$'),
6
	ko = require('ko'),
7
	key = require('key'),
8
	JSON = require('JSON'),
0 ignored issues
show
Comprehensibility introduced by
You are shadowing the built-in type JSON. This makes code hard to read, consider using a different name.
Loading history...
9
	Jua = require('Jua'),
10
11
	Enums = require('Common/Enums'),
12
	Consts = require('Common/Consts'),
13
	Utils = require('Common/Utils'),
14
	Globals = require('Common/Globals'),
15
	Events = require('Common/Events'),
16
	Links = require('Common/Links'),
17
	HtmlEditor = require('Common/HtmlEditor').default,
18
19
	Translator = require('Common/Translator'),
20
	Momentor = require('Common/Momentor'),
21
22
	Cache = require('Common/Cache'),
23
24
	AppStore = require('Stores/User/App'),
25
	SettingsStore = require('Stores/User/Settings'),
26
	IdentityStore = require('Stores/User/Identity'),
27
	AccountStore = require('Stores/User/Account'),
28
	FolderStore = require('Stores/User/Folder'),
29
	PgpStore = require('Stores/User/Pgp'),
30
	MessageStore = require('Stores/User/Message'),
31
	SocialStore = require('Stores/Social'),
32
33
	Settings = require('Storage/Settings'),
34
	Remote = require('Remote/User/Ajax'),
35
36
	ComposeAttachmentModel = require('Model/ComposeAttachment').default,
37
38
	kn = require('Knoin/Knoin'),
39
	AbstractView = require('Knoin/AbstractView');
40
41
/**
42
 * @constructor
43
 * @extends AbstractView
44
 */
45
function ComposePopupView()
46
{
47
	AbstractView.call(this, 'Popups', 'PopupsCompose');
48
49
	var
50
		self = this,
51
		fEmailOutInHelper = function(context, oIdentity, sName, bIn) {
52
			if (oIdentity && context && oIdentity[sName]() && (bIn ? true : context[sName]()))
53
			{
54
				var
55
					sIdentityEmail = oIdentity[sName](),
56
					aList = Utils.trim(context[sName]()).split(/[,]/);
57
58
				aList = _.filter(aList, function(sEmail) {
59
					sEmail = Utils.trim(sEmail);
60
					return sEmail && Utils.trim(sIdentityEmail) !== sEmail;
61
				});
62
63
				if (bIn)
64
				{
65
					aList.push(sIdentityEmail);
66
				}
67
68
				context[sName](aList.join(','));
69
			}
70
		};
71
72
	this.oLastMessage = null;
73
	this.oEditor = null;
74
	this.aDraftInfo = null;
75
	this.sInReplyTo = '';
76
	this.bFromDraft = false;
77
	this.sReferences = '';
78
79
	this.sLastFocusedField = 'to';
80
81
	this.resizerTrigger = _.bind(this.resizerTrigger, this);
82
83
	this.allowContacts = !!AppStore.contactsIsAllowed();
84
	this.allowFolders = !!Settings.capa(Enums.Capa.Folders);
85
86
	this.bSkipNextHide = false;
87
	this.composeInEdit = AppStore.composeInEdit;
88
	this.editorDefaultType = SettingsStore.editorDefaultType;
89
90
	this.capaOpenPGP = PgpStore.capaOpenPGP;
91
92
	this.identitiesDropdownTrigger = ko.observable(false);
93
94
	this.to = ko.observable('');
95
	this.to.focused = ko.observable(false);
96
	this.cc = ko.observable('');
97
	this.cc.focused = ko.observable(false);
98
	this.bcc = ko.observable('');
99
	this.bcc.focused = ko.observable(false);
100
	this.replyTo = ko.observable('');
101
	this.replyTo.focused = ko.observable(false);
102
103
	ko.computed(function() {
104
		switch (true)
105
		{
106
			case this.to.focused():
107
				this.sLastFocusedField = 'to';
108
				break;
109
			case this.cc.focused():
110
				this.sLastFocusedField = 'cc';
111
				break;
112
			case this.bcc.focused():
113
				this.sLastFocusedField = 'bcc';
114
				break;
115
			// no default
116
		}
117
	}, this).extend({'notify': 'always'});
118
119
	this.subject = ko.observable('');
120
	this.subject.focused = ko.observable(false);
121
122
	this.isHtml = ko.observable(false);
123
124
	this.requestDsn = ko.observable(false);
125
	this.requestReadReceipt = ko.observable(false);
126
	this.markAsImportant = ko.observable(false);
127
128
	this.sendError = ko.observable(false);
129
	this.sendSuccessButSaveError = ko.observable(false);
130
	this.savedError = ko.observable(false);
131
132
	this.sendButtonSuccess = ko.computed(function() {
133
		return !this.sendError() && !this.sendSuccessButSaveError();
134
	}, this);
135
136
	this.sendErrorDesc = ko.observable('');
137
	this.savedErrorDesc = ko.observable('');
138
139
	this.sendError.subscribe(function(bValue) {
140
		if (!bValue)
141
		{
142
			this.sendErrorDesc('');
143
		}
144
	}, this);
145
146
	this.savedError.subscribe(function(bValue) {
147
		if (!bValue)
148
		{
149
			this.savedErrorDesc('');
150
		}
151
	}, this);
152
153
	this.sendSuccessButSaveError.subscribe(function(bValue) {
154
		if (!bValue)
155
		{
156
			this.savedErrorDesc('');
157
		}
158
	}, this);
159
160
	this.savedTime = ko.observable(0);
161
	this.savedTimeText = ko.computed(function() {
162
		return 0 < this.savedTime() ? Translator.i18n('COMPOSE/SAVED_TIME', {
163
			'TIME': Momentor.format(this.savedTime() - 1, 'LT')
164
		}) : '';
165
	}, this);
166
167
	this.emptyToError = ko.observable(false);
168
	this.emptyToErrorTooltip = ko.computed(function() {
169
		return this.emptyToError() ? Translator.i18n('COMPOSE/EMPTY_TO_ERROR_DESC') : '';
170
	}, this);
171
172
	this.attachmentsInProcessError = ko.observable(false);
173
	this.attachmentsInErrorError = ko.observable(false);
174
175
	this.attachmentsErrorTooltip = ko.computed(function() {
176
177
		var sResult = '';
178
		switch (true)
179
		{
180
			case this.attachmentsInProcessError():
181
				sResult = Translator.i18n('COMPOSE/ATTACHMENTS_UPLOAD_ERROR_DESC');
182
				break;
183
			case this.attachmentsInErrorError():
184
				sResult = Translator.i18n('COMPOSE/ATTACHMENTS_ERROR_DESC');
185
				break;
186
			// no default
187
		}
188
189
		return sResult;
190
191
	}, this);
192
193
	this.showCc = ko.observable(false);
194
	this.showBcc = ko.observable(false);
195
	this.showReplyTo = ko.observable(false);
196
197
	this.cc.subscribe(function(aValue) {
198
		if (false === self.showCc() && 0 < aValue.length)
199
		{
200
			self.showCc(true);
201
		}
202
	}, this);
203
204
	this.bcc.subscribe(function(aValue) {
205
		if (false === self.showBcc() && 0 < aValue.length)
206
		{
207
			self.showBcc(true);
208
		}
209
	}, this);
210
211
	this.replyTo.subscribe(function(aValue) {
212
		if (false === self.showReplyTo() && 0 < aValue.length)
213
		{
214
			self.showReplyTo(true);
215
		}
216
	}, this);
217
218
	this.draftFolder = ko.observable('');
219
	this.draftUid = ko.observable('');
220
	this.sending = ko.observable(false);
221
	this.saving = ko.observable(false);
222
	this.attachments = ko.observableArray([]);
223
224
	this.attachmentsInProcess = this.attachments.filter(function(oItem) {
225
		return oItem && !oItem.complete();
226
	});
227
228
	this.attachmentsInReady = this.attachments.filter(function(oItem) {
229
		return oItem && oItem.complete();
230
	});
231
232
	this.attachmentsInError = this.attachments.filter(function(oItem) {
233
		return oItem && '' !== oItem.error();
234
	});
235
236
	this.attachmentsCount = ko.computed(function() {
237
		return this.attachments().length;
238
	}, this);
239
240
	this.attachmentsInErrorCount = ko.computed(function() {
241
		return this.attachmentsInError().length;
242
	}, this);
243
244
	this.attachmentsInProcessCount = ko.computed(function() {
245
		return this.attachmentsInProcess().length;
246
	}, this);
247
248
	this.isDraftFolderMessage = ko.computed(function() {
249
		return '' !== this.draftFolder() && '' !== this.draftUid();
250
	}, this);
251
252
	this.attachmentsPlace = ko.observable(false);
253
254
	this.attachments.subscribe(this.resizerTrigger);
255
	this.attachmentsPlace.subscribe(this.resizerTrigger);
256
257
	this.attachmentsInErrorCount.subscribe(function(iN) {
258
		if (0 === iN)
259
		{
260
			this.attachmentsInErrorError(false);
261
		}
262
	}, this);
263
264
	this.composeUploaderButton = ko.observable(null);
265
	this.composeUploaderDropPlace = ko.observable(null);
266
	this.dragAndDropEnabled = ko.observable(false);
267
	this.dragAndDropOver = ko.observable(false).extend({'throttle': 1});
268
	this.dragAndDropVisible = ko.observable(false).extend({'throttle': 1});
269
	this.attacheMultipleAllowed = ko.observable(false);
270
	this.addAttachmentEnabled = ko.observable(false);
271
272
	this.composeEditorArea = ko.observable(null);
273
274
	this.identities = IdentityStore.identities;
275
	this.identitiesOptions = ko.computed(function() {
276
		return _.map(IdentityStore.identities(), function(oItem) {
277
			return {
278
				'item': oItem,
279
				'optValue': oItem.id(),
280
				'optText': oItem.formattedName()
281
			};
282
		});
283
	}, this);
284
285
	this.currentIdentity = ko.observable(
286
		this.identities()[0] ? this.identities()[0] : null);
287
288
	this.currentIdentity.extend({'toggleSubscribe': [this,
289
		function(oIdentity) {
290
			fEmailOutInHelper(this, oIdentity, 'bcc');
291
			fEmailOutInHelper(this, oIdentity, 'replyTo');
292
		}, function(oIdentity) {
293
			fEmailOutInHelper(this, oIdentity, 'bcc', true);
294
			fEmailOutInHelper(this, oIdentity, 'replyTo', true);
295
		}
296
	]});
297
298
	this.currentIdentityView = ko.computed(function() {
299
		var oItem = this.currentIdentity();
300
		return oItem ? oItem.formattedName() : 'unknown';
301
	}, this);
302
303
	this.to.subscribe(function(sValue) {
304
		if (this.emptyToError() && 0 < sValue.length)
305
		{
306
			this.emptyToError(false);
307
		}
308
	}, this);
309
310
	this.attachmentsInProcess.subscribe(function(aValue) {
311
		if (this.attachmentsInProcessError() && Utils.isArray(aValue) && 0 === aValue.length)
312
		{
313
			this.attachmentsInProcessError(false);
314
		}
315
	}, this);
316
317
	this.resizer = ko.observable(false).extend({'throttle': 50});
318
319
	this.resizer.subscribe(_.bind(function() {
320
		if (this.oEditor) {
321
			this.oEditor.resize();
322
		}
323
	}, this));
324
325
	this.canBeSentOrSaved = ko.computed(function() {
326
		return !this.sending() && !this.saving();
327
	}, this);
328
329
	this.deleteCommand = Utils.createCommand(this, function() {
330
331
		var
332
			PopupsAskViewModel = require('View/Popup/Ask');
333
334
		if (!kn.isPopupVisible(PopupsAskViewModel) && this.modalVisibility())
335
		{
336
			kn.showScreenPopup(PopupsAskViewModel, [Translator.i18n('POPUPS_ASK/DESC_WANT_DELETE_MESSAGES'), function() {
337
				if (self.modalVisibility())
338
				{
339
					require('App/User').default.deleteMessagesFromFolderWithoutCheck(self.draftFolder(), [self.draftUid()]);
340
					kn.hideScreenPopup(ComposePopupView);
341
				}
342
			}]);
343
		}
344
345
	}, function() {
346
		return this.isDraftFolderMessage();
347
	});
348
349
	this.sendMessageResponse = _.bind(this.sendMessageResponse, this);
350
	this.saveMessageResponse = _.bind(this.saveMessageResponse, this);
351
352
	this.sendCommand = Utils.createCommand(this, function() {
353
354
		var
355
			sTo = Utils.trim(this.to()),
356
			sCc = Utils.trim(this.cc()),
357
			sBcc = Utils.trim(this.bcc()),
358
			sSentFolder = FolderStore.sentFolder();
359
360
		this.attachmentsInProcessError(false);
361
		this.attachmentsInErrorError(false);
362
		this.emptyToError(false);
363
364
		if (0 < this.attachmentsInProcess().length)
365
		{
366
			this.attachmentsInProcessError(true);
367
			this.attachmentsPlace(true);
368
		}
369
		else if (0 < this.attachmentsInError().length)
370
		{
371
			this.attachmentsInErrorError(true);
372
			this.attachmentsPlace(true);
373
		}
374
375
		if ('' === sTo && '' === sCc && '' === sBcc)
376
		{
377
			this.emptyToError(true);
378
		}
379
380
		if (!this.emptyToError() && !this.attachmentsInErrorError() && !this.attachmentsInProcessError())
381
		{
382
			if (SettingsStore.replySameFolder())
383
			{
384
				if (Utils.isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length && Utils.isNormal(this.aDraftInfo[2]) && 0 < this.aDraftInfo[2].length)
385
				{
386
					sSentFolder = this.aDraftInfo[2];
387
				}
388
			}
389
390
			if (!this.allowFolders)
391
			{
392
				sSentFolder = Consts.UNUSED_OPTION_VALUE;
393
			}
394
395
			if ('' === sSentFolder)
396
			{
397
				kn.showScreenPopup(require('View/Popup/FolderSystem'), [Enums.SetSystemFoldersNotification.Sent]);
398
			}
399
			else
400
			{
401
				this.sendError(false);
402
				this.sending(true);
403
404
				if (Utils.isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length)
405
				{
406
					var aFlagsCache = Cache.getMessageFlagsFromCache(this.aDraftInfo[2], this.aDraftInfo[1]);
407
					if (aFlagsCache)
408
					{
409
						if ('forward' === this.aDraftInfo[0])
410
						{
411
							aFlagsCache[3] = true;
412
						}
413
						else
414
						{
415
							aFlagsCache[2] = true;
416
						}
417
418
						Cache.setMessageFlagsToCache(this.aDraftInfo[2], this.aDraftInfo[1], aFlagsCache);
419
						require('App/User').default.reloadFlagsCurrentMessageListAndMessageFromCache();
420
						Cache.setFolderHash(this.aDraftInfo[2], '');
421
					}
422
				}
423
424
				sSentFolder = Consts.UNUSED_OPTION_VALUE === sSentFolder ? '' : sSentFolder;
425
426
				Cache.setFolderHash(this.draftFolder(), '');
427
				Cache.setFolderHash(sSentFolder, '');
428
429
				Remote.sendMessage(
430
					this.sendMessageResponse,
431
					this.currentIdentity() ? this.currentIdentity().id() : '',
432
					this.draftFolder(),
433
					this.draftUid(),
434
					sSentFolder,
435
					sTo,
436
					this.cc(),
437
					this.bcc(),
438
					this.replyTo(),
439
					this.subject(),
440
					this.oEditor ? this.oEditor.isHtml() : false,
441
					this.oEditor ? this.oEditor.getData(true, true) : '',
442
					this.prepearAttachmentsForSendOrSave(),
443
					this.aDraftInfo,
444
					this.sInReplyTo,
445
					this.sReferences,
446
					this.requestDsn(),
447
					this.requestReadReceipt(),
448
					this.markAsImportant()
449
				);
450
			}
451
		}
452
453
	}, this.canBeSentOrSaved);
454
455
	this.saveCommand = Utils.createCommand(this, function() {
456
457
		if (!this.allowFolders)
458
		{
459
			return false;
460
		}
461
462
		if (FolderStore.draftFolderNotEnabled())
463
		{
464
			kn.showScreenPopup(require('View/Popup/FolderSystem'), [Enums.SetSystemFoldersNotification.Draft]);
465
		}
466
		else
467
		{
468
			this.savedError(false);
469
			this.saving(true);
470
471
			this.autosaveStart();
472
473
			Cache.setFolderHash(FolderStore.draftFolder(), '');
474
475
			Remote.saveMessage(
476
				this.saveMessageResponse,
477
				this.currentIdentity() ? this.currentIdentity().id() : '',
478
				this.draftFolder(),
479
				this.draftUid(),
480
				FolderStore.draftFolder(),
481
				this.to(),
482
				this.cc(),
483
				this.bcc(),
484
				this.replyTo(),
485
				this.subject(),
486
				this.oEditor ? this.oEditor.isHtml() : false,
487
				this.oEditor ? this.oEditor.getData(true) : '',
488
				this.prepearAttachmentsForSendOrSave(),
489
				this.aDraftInfo,
490
				this.sInReplyTo,
491
				this.sReferences,
492
				this.markAsImportant()
493
			);
494
		}
495
496
		return true;
497
498
	}, this.canBeSentOrSaved);
499
500
	this.skipCommand = Utils.createCommand(this, function() {
501
502
		this.bSkipNextHide = true;
503
504
		if (this.modalVisibility() && !this.saving() && !this.sending() &&
505
			!FolderStore.draftFolderNotEnabled())
506
		{
507
			this.saveCommand();
508
		}
509
510
		this.tryToClosePopup();
511
512
	}, this.canBeSentOrSaved);
513
514
	this.contactsCommand = Utils.createCommand(this, function() {
515
516
		if (this.allowContacts)
517
		{
518
			this.skipCommand();
519
			_.delay(function() {
520
				kn.showScreenPopup(require('View/Popup/Contacts'),
521
					[true, self.sLastFocusedField]);
522
			}, Enums.Magics.Time200ms);
523
		}
524
525
	}, function() {
526
		return this.allowContacts;
527
	});
528
529
	Events.sub('interval.2m', function() {
530
531
		if (this.modalVisibility() && !FolderStore.draftFolderNotEnabled() && !this.isEmptyForm(false) &&
532
			!this.saving() && !this.sending() && !this.savedError())
533
		{
534
			this.saveCommand();
535
		}
536
	}, this);
537
538
	this.showCc.subscribe(this.resizerTrigger);
539
	this.showBcc.subscribe(this.resizerTrigger);
540
	this.showReplyTo.subscribe(this.resizerTrigger);
541
542
	this.dropboxEnabled = SocialStore.dropbox.enabled;
543
	this.dropboxApiKey = SocialStore.dropbox.apiKey;
544
545
	this.dropboxCommand = Utils.createCommand(this, function() {
546
547
		if (window.Dropbox)
548
		{
549
			window.Dropbox.choose({
550
				'success': function(files) {
551
					if (files && files[0] && files[0].link)
552
					{
553
						self.addDropboxAttachment(files[0]);
554
					}
555
				},
556
				'linkType': 'direct',
557
				'multiselect': false
558
			});
559
		}
560
561
		return true;
562
563
	}, function() {
564
		return this.dropboxEnabled();
565
	});
566
567
	this.driveEnabled = ko.observable(Globals.bXMLHttpRequestSupported &&
568
		!!Settings.settingsGet('AllowGoogleSocial') && !!Settings.settingsGet('AllowGoogleSocialDrive') &&
569
		!!Settings.settingsGet('GoogleClientID') && !!Settings.settingsGet('GoogleApiKey'));
570
571
	this.driveVisible = ko.observable(false);
572
573
	this.driveCommand = Utils.createCommand(this, function() {
574
575
		this.driveOpenPopup();
576
		return true;
577
578
	}, function() {
579
		return this.driveEnabled();
580
	});
581
582
	this.driveCallback = _.bind(this.driveCallback, this);
583
584
	this.onMessageUploadAttachments = _.bind(this.onMessageUploadAttachments, this);
585
586
	this.bDisabeCloseOnEsc = true;
587
	this.sDefaultKeyScope = Enums.KeyState.Compose;
588
589
	this.tryToClosePopup = _.debounce(_.bind(this.tryToClosePopup, this), Enums.Magics.Time200ms);
590
591
	this.emailsSource = _.bind(this.emailsSource, this);
592
	this.autosaveFunction = _.bind(this.autosaveFunction, this);
593
594
	this.iTimer = 0;
595
596
	kn.constructorEnd(this);
597
}
598
599
kn.extendAsViewModel(['View/Popup/Compose', 'PopupsComposeViewModel'], ComposePopupView);
600
_.extend(ComposePopupView.prototype, AbstractView.prototype);
601
602
ComposePopupView.prototype.autosaveFunction = function()
603
{
604
	if (this.modalVisibility() && !FolderStore.draftFolderNotEnabled() && !this.isEmptyForm(false) &&
605
		!this.saving() && !this.sending() && !this.savedError())
606
	{
607
		this.saveCommand();
608
	}
609
610
	this.autosaveStart();
611
};
612
613
ComposePopupView.prototype.autosaveStart = function()
614
{
615
	window.clearTimeout(this.iTimer);
616
	this.iTimer = window.setTimeout(this.autosaveFunction, Enums.Magics.Time1m);
617
};
618
619
ComposePopupView.prototype.autosaveStop = function()
620
{
621
	window.clearTimeout(this.iTimer);
622
};
623
624
ComposePopupView.prototype.emailsSource = function(oData, fResponse)
625
{
626
	require('App/User').default.getAutocomplete(oData.term, function(aData) {
627
		fResponse(_.map(aData, function(oEmailItem) {
628
			return oEmailItem.toLine(false);
629
		}));
630
	});
631
};
632
633
ComposePopupView.prototype.openOpenPgpPopup = function()
634
{
635
	if (PgpStore.capaOpenPGP() && this.oEditor && !this.oEditor.isHtml())
636
	{
637
		var self = this;
638
		kn.showScreenPopup(require('View/Popup/ComposeOpenPgp'), [
639
			function(sResult) {
640
				self.editor(function(oEditor) {
641
					oEditor.setPlain(sResult);
642
				});
643
			},
644
			this.oEditor.getData(false, true),
645
			this.currentIdentity(),
646
			this.to(),
647
			this.cc(),
648
			this.bcc()
649
		]);
650
	}
651
};
652
653
ComposePopupView.prototype.reloadDraftFolder = function()
654
{
655
	var
656
		sDraftFolder = FolderStore.draftFolder();
657
658
	if ('' !== sDraftFolder && Consts.UNUSED_OPTION_VALUE !== sDraftFolder)
659
	{
660
		Cache.setFolderHash(sDraftFolder, '');
661
		if (FolderStore.currentFolderFullNameRaw() === sDraftFolder)
662
		{
663
			require('App/User').default.reloadMessageList(true);
664
		}
665
		else
666
		{
667
			require('App/User').default.folderInformation(sDraftFolder);
668
		}
669
	}
670
};
671
672
ComposePopupView.prototype.findIdentityByMessage = function(sComposeType, oMessage)
673
{
674
	var
675
		aIdentities = IdentityStore.identities(),
676
		iResultIndex = 1000,
677
		oResultIdentity = null,
678
		oIdentitiesCache = {},
679
680
		fEachHelper = function(oItem) {
681
682
			if (oItem && oItem.email && oIdentitiesCache[oItem.email])
683
			{
684
				if (!oResultIdentity || iResultIndex > oIdentitiesCache[oItem.email][1])
685
				{
686
					oResultIdentity = oIdentitiesCache[oItem.email][0];
687
					iResultIndex = oIdentitiesCache[oItem.email][1];
688
				}
689
			}
690
		};
691
692
	_.each(aIdentities, function(oItem, iIndex) {
693
		oIdentitiesCache[oItem.email()] = [oItem, iIndex];
694
	});
695
696
	if (oMessage)
697
	{
698
		switch (sComposeType)
699
		{
700
			case Enums.ComposeType.Empty:
701
				break;
702
			case Enums.ComposeType.Reply:
703
			case Enums.ComposeType.ReplyAll:
704
			case Enums.ComposeType.Forward:
705
			case Enums.ComposeType.ForwardAsAttachment:
706
				_.each(_.union(oMessage.to, oMessage.cc, oMessage.bcc), fEachHelper);
707
				if (!oResultIdentity) {
708
					_.each(oMessage.deliveredTo, fEachHelper);
709
				}
710
				break;
711
			case Enums.ComposeType.Draft:
712
				_.each(_.union(oMessage.from, oMessage.replyTo), fEachHelper);
713
				break;
714
			// no default
715
		}
716
	}
717
718
	return oResultIdentity || aIdentities[0] || null;
719
};
720
721
ComposePopupView.prototype.selectIdentity = function(oIdentity)
722
{
723
	if (oIdentity && oIdentity.item)
724
	{
725
		this.currentIdentity(oIdentity.item);
726
		this.setSignatureFromIdentity(oIdentity.item);
727
	}
728
};
729
730
ComposePopupView.prototype.sendMessageResponse = function(sResult, oData)
731
{
732
	var
733
		bResult = false,
734
		sMessage = '';
735
736
	this.sending(false);
737
738
	if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
739
	{
740
		bResult = true;
741
		if (this.modalVisibility())
742
		{
743
			Utils.delegateRun(this, 'closeCommand');
744
		}
745
	}
746
747
	if (this.modalVisibility() && !bResult)
748
	{
749
		if (oData && Enums.Notification.CantSaveMessage === oData.ErrorCode)
750
		{
751
			this.sendSuccessButSaveError(true);
752
			this.savedErrorDesc(Utils.trim(Translator.i18n('COMPOSE/SAVED_ERROR_ON_SEND')));
753
		}
754
		else
755
		{
756
			sMessage = Translator.getNotification(oData && oData.ErrorCode ? oData.ErrorCode : Enums.Notification.CantSendMessage,
757
				oData && oData.ErrorMessage ? oData.ErrorMessage : '');
758
759
			this.sendError(true);
760
			this.sendErrorDesc(sMessage || Translator.getNotification(Enums.Notification.CantSendMessage));
761
		}
762
	}
763
764
	this.reloadDraftFolder();
765
};
766
767
ComposePopupView.prototype.saveMessageResponse = function(sResult, oData)
768
{
769
	var bResult = false;
770
771
	this.saving(false);
772
773
	if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
774
	{
775
		if (oData.Result.NewFolder && oData.Result.NewUid)
776
		{
777
			bResult = true;
778
779
			if (this.bFromDraft)
780
			{
781
				var oMessage = MessageStore.message();
782
				if (oMessage && this.draftFolder() === oMessage.folderFullNameRaw && this.draftUid() === oMessage.uid)
783
				{
784
					MessageStore.message(null);
785
				}
786
			}
787
788
			this.draftFolder(oData.Result.NewFolder);
789
			this.draftUid(oData.Result.NewUid);
790
791
			this.savedTime(window.Math.round((new window.Date()).getTime() / 1000));
792
793
			if (this.bFromDraft)
794
			{
795
				Cache.setFolderHash(this.draftFolder(), '');
796
			}
797
		}
798
	}
799
800
	if (!bResult)
801
	{
802
		this.savedError(true);
803
		this.savedErrorDesc(Translator.getNotification(Enums.Notification.CantSaveMessage));
804
	}
805
806
	this.reloadDraftFolder();
807
};
808
809
ComposePopupView.prototype.onHide = function()
810
{
811
	this.autosaveStop();
812
813
	if (!this.bSkipNextHide)
814
	{
815
		AppStore.composeInEdit(false);
816
		this.reset();
817
	}
818
819
	this.bSkipNextHide = false;
820
821
	this.to.focused(false);
822
823
	kn.routeOn();
824
};
825
826
ComposePopupView.prototype.editor = function(fOnInit)
827
{
828
	if (fOnInit)
829
	{
830
		var self = this;
831
		if (!this.oEditor && this.composeEditorArea())
832
		{
833
// _.delay(function() {
834
			self.oEditor = new HtmlEditor(self.composeEditorArea(), null, function() {
835
				fOnInit(self.oEditor);
836
				self.resizerTrigger();
837
			}, function(bHtml) {
838
				self.isHtml(!!bHtml);
839
			});
840
// }, 1000);
841
		}
842
		else if (this.oEditor)
843
		{
844
			fOnInit(this.oEditor);
845
			this.resizerTrigger();
846
		}
847
	}
848
};
849
850
ComposePopupView.prototype.converSignature = function(sSignature)
851
{
852
	var
853
		iLimit = 10,
854
		aMoments = [],
855
		oMomentRegx = /{{MOMENT:([^}]+)}}/g,
856
		sFrom = '';
857
858
	sSignature = sSignature.replace(/[\r]/g, '');
859
860
	sFrom = this.oLastMessage ? this.emailArrayToStringLineHelper(this.oLastMessage.from, true) : '';
861
	if ('' !== sFrom)
862
	{
863
		sSignature = sSignature.replace(/{{FROM-FULL}}/g, sFrom);
864
865
		if (-1 === sFrom.indexOf(' ') && 0 < sFrom.indexOf('@'))
866
		{
867
			sFrom = sFrom.replace(/@[\S]+/, '');
868
		}
869
870
		sSignature = sSignature.replace(/{{FROM}}/g, sFrom);
871
	}
872
873
	sSignature = sSignature.replace(/[\s]{1,2}{{FROM}}/g, '{{FROM}}');
874
	sSignature = sSignature.replace(/[\s]{1,2}{{FROM-FULL}}/g, '{{FROM-FULL}}');
875
876
	sSignature = sSignature.replace(/{{FROM}}/g, '');
877
	sSignature = sSignature.replace(/{{FROM-FULL}}/g, '');
878
879
	if (-1 < sSignature.indexOf('{{DATE}}'))
880
	{
881
		sSignature = sSignature.replace(/{{DATE}}/g, Momentor.format(0, 'llll'));
882
	}
883
884
	if (-1 < sSignature.indexOf('{{TIME}}'))
885
	{
886
		sSignature = sSignature.replace(/{{TIME}}/g, Momentor.format(0, 'LT'));
887
	}
888
	if (-1 < sSignature.indexOf('{{MOMENT:'))
889
	{
890
		try
891
		{
892
			var oMatch = null;
0 ignored issues
show
Unused Code introduced by
The assignment to oMatch seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
893
			while (null !== (oMatch = oMomentRegx.exec(sSignature))) // eslint-disable-line no-cond-assign
894
			{
895
				if (oMatch && oMatch[0] && oMatch[1])
896
				{
897
					aMoments.push([oMatch[0], oMatch[1]]);
898
				}
899
900
				iLimit -= 1;
901
				if (0 === iLimit)
902
				{
903
					break;
904
				}
905
			}
906
907
			if (aMoments && 0 < aMoments.length)
908
			{
909
				_.each(aMoments, function(aData) {
910
					sSignature = sSignature.replace(
911
						aData[0], Momentor.format(0, aData[1]));
912
				});
913
			}
914
915
			sSignature = sSignature.replace(/{{MOMENT:[^}]+}}/g, '');
916
		}
917
		catch (e) {} // eslint-disable-line no-empty
918
	}
919
920
	return sSignature;
921
};
922
923
ComposePopupView.prototype.setSignatureFromIdentity = function(oIdentity)
924
{
925
	if (oIdentity)
926
	{
927
		var self = this;
928
		this.editor(function(oEditor) {
929
			var
930
				bHtml = false,
931
				sSignature = oIdentity.signature();
932
933
			if ('' !== sSignature)
934
			{
935
				if (':HTML:' === sSignature.substr(0, 6))
936
				{
937
					bHtml = true;
938
					sSignature = sSignature.substr(6);
939
				}
940
			}
941
942
			oEditor.setSignature(self.converSignature(sSignature),
943
				bHtml, !!oIdentity.signatureInsertBefore());
944
		});
945
	}
946
};
947
948
/**
949
 * @param {string=} sType = Enums.ComposeType.Empty
950
 * @param {?MessageModel|Array=} oMessageOrArray = null
951
 * @param {Array=} aToEmails = null
952
 * @param {Array=} aCcEmails = null
953
 * @param {Array=} aBccEmails = null
954
 * @param {string=} sCustomSubject = null
955
 * @param {string=} sCustomPlainText = null
956
 */
957
ComposePopupView.prototype.onShow = function(sType, oMessageOrArray,
958
	aToEmails, aCcEmails, aBccEmails, sCustomSubject, sCustomPlainText)
959
{
960
	kn.routeOff();
961
962
	this.autosaveStart();
963
964
	if (AppStore.composeInEdit())
965
	{
966
		sType = sType || Enums.ComposeType.Empty;
967
968
		var self = this;
969
970
		if (Enums.ComposeType.Empty !== sType)
971
		{
972
			kn.showScreenPopup(require('View/Popup/Ask'), [Translator.i18n('COMPOSE/DISCARD_UNSAVED_DATA'), function() {
973
				self.initOnShow(sType, oMessageOrArray, aToEmails, aCcEmails, aBccEmails, sCustomSubject, sCustomPlainText);
974
			}, null, null, null, false]);
975
		}
976
		else
977
		{
978
			this.addEmailsTo(this.to, aToEmails);
979
			this.addEmailsTo(this.cc, aCcEmails);
980
			this.addEmailsTo(this.bcc, aBccEmails);
981
982
			if (Utils.isNormal(sCustomSubject) && '' !== sCustomSubject &&
983
				'' === this.subject())
984
			{
985
				this.subject(sCustomSubject);
986
			}
987
		}
988
	}
989
	else
990
	{
991
		this.initOnShow(sType, oMessageOrArray, aToEmails, aCcEmails, aBccEmails, sCustomSubject, sCustomPlainText);
992
	}
993
};
994
995
/**
996
 * @param {Function} fKoValue
997
 * @param {Array} emails
998
 */
999
ComposePopupView.prototype.addEmailsTo = function(fKoValue, emails)
1000
{
1001
	var value = Utils.trim(fKoValue());
1002
	if (Utils.isNonEmptyArray(emails))
1003
	{
1004
		var values = _.uniq(_.compact(_.map(emails, function(oItem) {
1005
			return oItem ? oItem.toLine(false) : null;
1006
		})));
1007
1008
		fKoValue(value + ('' === value ? '' : ', ') + Utils.trim(values.join(', ')));
1009
	}
1010
};
1011
1012
/**
1013
 *
1014
 * @param {Array} aList
1015
 * @param {boolean} bFriendly
1016
 * @returns {string}
1017
 */
1018
ComposePopupView.prototype.emailArrayToStringLineHelper = function(aList, bFriendly)
1019
{
1020
	bFriendly = !!bFriendly;
1021
	var aResult = _.map(aList, function(item) {
1022
		return item.toLine(bFriendly);
1023
	});
1024
1025
	return aResult.join(', ');
1026
};
1027
1028
/**
1029
 * @param {string=} sType = Enums.ComposeType.Empty
1030
 * @param {?MessageModel|Array=} oMessageOrArray = null
1031
 * @param {Array=} aToEmails = null
1032
 * @param {Array=} aCcEmails = null
1033
 * @param {Array=} aBccEmails = null
1034
 * @param {string=} sCustomSubject = null
1035
 * @param {string=} sCustomPlainText = null
1036
 */
1037
ComposePopupView.prototype.initOnShow = function(sType, oMessageOrArray,
1038
	aToEmails, aCcEmails, aBccEmails, sCustomSubject, sCustomPlainText)
1039
{
1040
	AppStore.composeInEdit(true);
1041
1042
	var
1043
		self = this,
1044
		sFrom = '',
1045
		sTo = '',
1046
		sCc = '',
1047
		sDate = '',
1048
		sSubject = '',
1049
		sText = '',
1050
		sReplyTitle = '',
1051
		oExcludeEmail = {},
1052
		oIdentity = null,
1053
		mEmail = AccountStore.email(),
1054
		aDraftInfo = null,
1055
		oMessage = null,
1056
		sComposeType = sType || Enums.ComposeType.Empty;
1057
1058
	oMessageOrArray = oMessageOrArray || null;
1059
	if (oMessageOrArray && Utils.isNormal(oMessageOrArray))
1060
	{
1061
		oMessage = Utils.isArray(oMessageOrArray) && 1 === oMessageOrArray.length ? oMessageOrArray[0] :
1062
			(!Utils.isArray(oMessageOrArray) ? oMessageOrArray : null);
1063
	}
1064
1065
	this.oLastMessage = oMessage;
1066
1067
	if (null !== mEmail)
1068
	{
1069
		oExcludeEmail[mEmail] = true;
1070
	}
1071
1072
	this.reset();
1073
1074
	oIdentity = this.findIdentityByMessage(sComposeType, oMessage);
1075
	if (oIdentity)
1076
	{
1077
		oExcludeEmail[oIdentity.email()] = true;
1078
	}
1079
1080
	if (Utils.isNonEmptyArray(aToEmails))
1081
	{
1082
		this.to(this.emailArrayToStringLineHelper(aToEmails));
1083
	}
1084
1085
	if (Utils.isNonEmptyArray(aCcEmails))
1086
	{
1087
		this.cc(this.emailArrayToStringLineHelper(aCcEmails));
1088
	}
1089
1090
	if (Utils.isNonEmptyArray(aBccEmails))
1091
	{
1092
		this.bcc(this.emailArrayToStringLineHelper(aBccEmails));
1093
	}
1094
1095
	if ('' !== sComposeType && oMessage)
1096
	{
1097
		sDate = Momentor.format(oMessage.dateTimeStampInUTC(), 'FULL');
1098
		sSubject = oMessage.subject();
1099
		aDraftInfo = oMessage.aDraftInfo;
1100
1101
		var oText = $(oMessage.body).clone();
1102
		if (oText)
1103
		{
1104
			Utils.clearBqSwitcher(oText);
1105
1106
			sText = oText.html();
1107
		}
1108
1109
		switch (sComposeType)
1110
		{
1111
			case Enums.ComposeType.Empty:
1112
				break;
1113
1114
			case Enums.ComposeType.Reply:
1115
				this.to(this.emailArrayToStringLineHelper(oMessage.replyEmails(oExcludeEmail)));
1116
				this.subject(Utils.replySubjectAdd('Re', sSubject));
1117
				this.prepearMessageAttachments(oMessage, sComposeType);
1118
				this.aDraftInfo = ['reply', oMessage.uid, oMessage.folderFullNameRaw];
1119
				this.sInReplyTo = oMessage.sMessageId;
1120
				this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.sReferences);
1121
				break;
1122
1123
			case Enums.ComposeType.ReplyAll:
1124
				var aResplyAllParts = oMessage.replyAllEmails(oExcludeEmail);
1125
				this.to(this.emailArrayToStringLineHelper(aResplyAllParts[0]));
1126
				this.cc(this.emailArrayToStringLineHelper(aResplyAllParts[1]));
1127
				this.subject(Utils.replySubjectAdd('Re', sSubject));
1128
				this.prepearMessageAttachments(oMessage, sComposeType);
1129
				this.aDraftInfo = ['reply', oMessage.uid, oMessage.folderFullNameRaw];
1130
				this.sInReplyTo = oMessage.sMessageId;
1131
				this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.references());
1132
				break;
1133
1134
			case Enums.ComposeType.Forward:
1135
				this.subject(Utils.replySubjectAdd('Fwd', sSubject));
1136
				this.prepearMessageAttachments(oMessage, sComposeType);
1137
				this.aDraftInfo = ['forward', oMessage.uid, oMessage.folderFullNameRaw];
1138
				this.sInReplyTo = oMessage.sMessageId;
1139
				this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.sReferences);
1140
				break;
1141
1142
			case Enums.ComposeType.ForwardAsAttachment:
1143
				this.subject(Utils.replySubjectAdd('Fwd', sSubject));
1144
				this.prepearMessageAttachments(oMessage, sComposeType);
1145
				this.aDraftInfo = ['forward', oMessage.uid, oMessage.folderFullNameRaw];
1146
				this.sInReplyTo = oMessage.sMessageId;
1147
				this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.sReferences);
1148
				break;
1149
1150
			case Enums.ComposeType.Draft:
1151
				this.to(this.emailArrayToStringLineHelper(oMessage.to));
1152
				this.cc(this.emailArrayToStringLineHelper(oMessage.cc));
1153
				this.bcc(this.emailArrayToStringLineHelper(oMessage.bcc));
1154
				this.replyTo(this.emailArrayToStringLineHelper(oMessage.replyTo));
1155
1156
				this.bFromDraft = true;
1157
1158
				this.draftFolder(oMessage.folderFullNameRaw);
1159
				this.draftUid(oMessage.uid);
1160
1161
				this.subject(sSubject);
1162
				this.prepearMessageAttachments(oMessage, sComposeType);
1163
1164
				this.aDraftInfo = Utils.isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
1165
				this.sInReplyTo = oMessage.sInReplyTo;
1166
				this.sReferences = oMessage.sReferences;
1167
				break;
1168
1169
			case Enums.ComposeType.EditAsNew:
1170
				this.to(this.emailArrayToStringLineHelper(oMessage.to));
1171
				this.cc(this.emailArrayToStringLineHelper(oMessage.cc));
1172
				this.bcc(this.emailArrayToStringLineHelper(oMessage.bcc));
1173
				this.replyTo(this.emailArrayToStringLineHelper(oMessage.replyTo));
1174
1175
				this.subject(sSubject);
1176
				this.prepearMessageAttachments(oMessage, sComposeType);
1177
1178
				this.aDraftInfo = Utils.isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
1179
				this.sInReplyTo = oMessage.sInReplyTo;
1180
				this.sReferences = oMessage.sReferences;
1181
				break;
1182
			// no default
1183
		}
1184
1185
		switch (sComposeType)
1186
		{
1187
			case Enums.ComposeType.Reply:
1188
			case Enums.ComposeType.ReplyAll:
1189
				sFrom = oMessage.fromToLine(false, true);
1190
				sReplyTitle = Translator.i18n('COMPOSE/REPLY_MESSAGE_TITLE', {
1191
					'DATETIME': sDate,
1192
					'EMAIL': sFrom
1193
				});
1194
1195
				sText = '<br /><br />' + sReplyTitle + ':' +
1196
					'<blockquote>' + Utils.trim(sText) + '</blockquote>';
1197
//						'<blockquote><p>' + Utils.trim(sText) + '</p></blockquote>';
1198
1199
				break;
1200
1201
			case Enums.ComposeType.Forward:
1202
				sFrom = oMessage.fromToLine(false, true);
1203
				sTo = oMessage.toToLine(false, true);
1204
				sCc = oMessage.ccToLine(false, true);
1205
				sText = '<br /><br />' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_TITLE') +
1206
						'<br />' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_FROM') + ': ' + sFrom +
1207
						'<br />' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_TO') + ': ' + sTo +
1208
						(0 < sCc.length ? '<br />' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_CC') + ': ' + sCc : '') +
1209
						'<br />' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_SENT') + ': ' + Utils.encodeHtml(sDate) +
1210
						'<br />' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_SUBJECT') + ': ' + Utils.encodeHtml(sSubject) +
1211
						'<br /><br />' + Utils.trim(sText) + '<br /><br />';
1212
				break;
1213
1214
			case Enums.ComposeType.ForwardAsAttachment:
1215
				sText = '';
1216
				break;
1217
			// no default
1218
		}
1219
1220
		this.editor(function(oEditor) {
1221
1222
			oEditor.setHtml(sText, false);
1223
1224
			if (Enums.EditorDefaultType.PlainForced === self.editorDefaultType() ||
1225
				(!oMessage.isHtml() && Enums.EditorDefaultType.HtmlForced !== self.editorDefaultType()))
1226
			{
1227
				oEditor.modeToggle(false);
1228
			}
1229
1230
			if (oIdentity && Enums.ComposeType.Draft !== sComposeType && Enums.ComposeType.EditAsNew !== sComposeType)
1231
			{
1232
				self.setSignatureFromIdentity(oIdentity);
1233
			}
1234
1235
			self.setFocusInPopup();
1236
		});
1237
	}
1238
	else if (Enums.ComposeType.Empty === sComposeType)
1239
	{
1240
		this.subject(Utils.isNormal(sCustomSubject) ? '' + sCustomSubject : '');
1241
1242
		sText = Utils.isNormal(sCustomPlainText) ? '' + sCustomPlainText : '';
1243
1244
		this.editor(function(oEditor) {
1245
1246
			oEditor.setHtml(sText, false);
1247
1248
			if (Enums.EditorDefaultType.Html !== self.editorDefaultType() &&
1249
				Enums.EditorDefaultType.HtmlForced !== self.editorDefaultType())
1250
			{
1251
				oEditor.modeToggle(false);
1252
			}
1253
1254
			if (oIdentity)
1255
			{
1256
				self.setSignatureFromIdentity(oIdentity);
1257
			}
1258
1259
			self.setFocusInPopup();
1260
		});
1261
	}
1262
	else if (Utils.isNonEmptyArray(oMessageOrArray))
1263
	{
1264
		_.each(oMessageOrArray, function(oItem) {
1265
			self.addMessageAsAttachment(oItem);
1266
		});
1267
1268
		this.editor(function(oEditor) {
1269
1270
			oEditor.setHtml('', false);
1271
1272
			if (Enums.EditorDefaultType.Html !== self.editorDefaultType() &&
1273
				Enums.EditorDefaultType.HtmlForced !== self.editorDefaultType())
1274
			{
1275
				oEditor.modeToggle(false);
1276
			}
1277
1278
			if (oIdentity && Enums.ComposeType.Draft !== sComposeType && Enums.ComposeType.EditAsNew !== sComposeType)
1279
			{
1280
				self.setSignatureFromIdentity(oIdentity);
1281
			}
1282
1283
			self.setFocusInPopup();
1284
		});
1285
	}
1286
	else
1287
	{
1288
		this.setFocusInPopup();
1289
	}
1290
1291
	var downloads = this.getAttachmentsDownloadsForUpload();
1292
	if (Utils.isNonEmptyArray(downloads))
1293
	{
1294
		Remote.messageUploadAttachments(this.onMessageUploadAttachments, downloads);
1295
	}
1296
1297
	if (oIdentity)
1298
	{
1299
		this.currentIdentity(oIdentity);
1300
	}
1301
1302
	this.resizerTrigger();
1303
};
1304
1305
ComposePopupView.prototype.onMessageUploadAttachments = function(sResult, oData)
1306
{
1307
	if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
1308
	{
1309
		var self = this;
1310
		if (!this.viewModelVisibility())
1311
		{
1312
			_.each(oData.Result, function(id, tempName) {
1313
				var attachment = self.getAttachmentById(id);
1314
				if (attachment)
1315
				{
1316
					attachment.tempName(tempName);
1317
					attachment.waiting(false).uploading(false).complete(true);
1318
				}
1319
			});
1320
		}
1321
	}
1322
	else
1323
	{
1324
		this.setMessageAttachmentFailedDownloadText();
1325
	}
1326
};
1327
1328
ComposePopupView.prototype.setFocusInPopup = function()
1329
{
1330
	if (!Globals.bMobileDevice)
1331
	{
1332
		var self = this;
1333
		_.delay(function() {
1334
1335
			if ('' === self.to())
1336
			{
1337
				self.to.focused(true);
1338
			}
1339
			else if (self.oEditor)
1340
			{
1341
				if (!self.to.focused())
1342
				{
1343
					self.oEditor.focus();
1344
				}
1345
			}
1346
1347
		}, Enums.Magics.Time100ms);
1348
	}
1349
};
1350
1351
ComposePopupView.prototype.onShowWithDelay = function()
1352
{
1353
	this.resizerTrigger();
1354
};
1355
1356
ComposePopupView.prototype.tryToClosePopup = function()
1357
{
1358
	var
1359
		self = this,
1360
		PopupsAskViewModel = require('View/Popup/Ask');
1361
1362
	if (!kn.isPopupVisible(PopupsAskViewModel) && this.modalVisibility())
1363
	{
1364
		if (this.bSkipNextHide || (this.isEmptyForm() && !this.draftUid()))
1365
		{
1366
			Utils.delegateRun(self, 'closeCommand');
1367
		}
1368
		else
1369
		{
1370
			kn.showScreenPopup(PopupsAskViewModel, [Translator.i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'), function() {
1371
				if (self.modalVisibility())
1372
				{
1373
					Utils.delegateRun(self, 'closeCommand');
1374
				}
1375
			}]);
1376
		}
1377
	}
1378
};
1379
1380
ComposePopupView.prototype.onBuild = function()
1381
{
1382
	this.initUploader();
1383
1384
	var
1385
		self = this,
1386
		oScript = null;
0 ignored issues
show
Unused Code introduced by
The assignment to oScript seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
1387
1388
	key('ctrl+q, command+q, ctrl+w, command+w', Enums.KeyState.Compose, function() {
1389
		return false;
1390
	});
1391
1392
	key('`', Enums.KeyState.Compose, function() {
1393
		if (self.oEditor && !self.oEditor.hasFocus() && !Utils.inFocus())
1394
		{
1395
			self.identitiesDropdownTrigger(true);
1396
			return false;
1397
		}
1398
1399
		return true;
1400
	});
1401
1402
	key('ctrl+`', Enums.KeyState.Compose, function() {
1403
		self.identitiesDropdownTrigger(true);
1404
		return false;
1405
	});
1406
1407
	key('esc, ctrl+down, command+down', Enums.KeyState.Compose, function() {
1408
		self.skipCommand();
1409
		return false;
1410
	});
1411
1412
	if (this.allowFolders)
1413
	{
1414
		key('ctrl+s, command+s', Enums.KeyState.Compose, function() {
1415
			self.saveCommand();
1416
			return false;
1417
		});
1418
	}
1419
1420
	if (Settings.appSettingsGet('allowCtrlEnterOnCompose'))
1421
	{
1422
		key('ctrl+enter, command+enter', Enums.KeyState.Compose, function() {
1423
			self.sendCommand();
1424
			return false;
1425
		});
1426
	}
1427
1428
	key('shift+esc', Enums.KeyState.Compose, function() {
1429
		if (self.modalVisibility())
1430
		{
1431
			self.tryToClosePopup();
1432
		}
1433
		return false;
1434
	});
1435
1436
	Events.sub('window.resize.real', this.resizerTrigger);
1437
	Events.sub('window.resize.real', _.debounce(this.resizerTrigger, Enums.Magics.Time50ms));
1438
1439
	if (this.dropboxEnabled() && this.dropboxApiKey() && !window.Dropbox)
1440
	{
1441
		oScript = window.document.createElement('script');
1442
		oScript.type = 'text/javascript';
1443
		oScript.src = 'https://www.dropbox.com/static/api/2/dropins.js';
1444
		$(oScript).attr('id', 'dropboxjs').attr('data-app-key', self.dropboxApiKey());
1445
1446
		window.document.body.appendChild(oScript);
1447
	}
1448
1449
	if (this.driveEnabled())
1450
	{
1451
		$.getScript('https://apis.google.com/js/api.js', function() {
1452
			if (window.gapi)
1453
			{
1454
				self.driveVisible(true);
1455
			}
1456
		});
1457
	}
1458
1459
	window.setInterval(function() {
1460
		if (self.modalVisibility() && self.oEditor)
1461
		{
1462
			self.oEditor.resize();
1463
		}
1464
	}, Enums.Magics.Time5s);
1465
};
1466
1467
ComposePopupView.prototype.driveCallback = function(sAccessToken, oData)
1468
{
1469
	if (oData && window.XMLHttpRequest && window.google &&
1470
		oData[window.google.picker.Response.ACTION] === window.google.picker.Action.PICKED &&
1471
		oData[window.google.picker.Response.DOCUMENTS] && oData[window.google.picker.Response.DOCUMENTS][0] &&
1472
		oData[window.google.picker.Response.DOCUMENTS][0].id)
1473
	{
1474
		var
1475
			self = this,
1476
			oRequest = new window.XMLHttpRequest();
1477
1478
		oRequest.open('GET', 'https://www.googleapis.com/drive/v2/files/' + oData[window.google.picker.Response.DOCUMENTS][0].id);
1479
		oRequest.setRequestHeader('Authorization', 'Bearer ' + sAccessToken);
1480
		oRequest.addEventListener('load', function() {
1481
			if (oRequest && oRequest.responseText)
1482
			{
1483
				var
1484
					oResponse = JSON.parse(oRequest.responseText),
1485
					fExport = function(oItem, sMimeType, sExt) {
1486
						if (oItem && oItem.exportLinks)
1487
						{
1488
							if (oItem.exportLinks[sMimeType])
1489
							{
1490
								oResponse.downloadUrl = oItem.exportLinks[sMimeType];
1491
								oResponse.title = oItem.title + '.' + sExt;
1492
								oResponse.mimeType = sMimeType;
1493
							}
1494
							else if (oItem.exportLinks['application/pdf'])
1495
							{
1496
								oResponse.downloadUrl = oItem.exportLinks['application/pdf'];
1497
								oResponse.title = oItem.title + '.pdf';
1498
								oResponse.mimeType = 'application/pdf';
1499
							}
1500
						}
1501
					};
1502
1503
				if (oResponse && !oResponse.downloadUrl && oResponse.mimeType && oResponse.exportLinks)
1504
				{
1505
					switch (oResponse.mimeType.toString().toLowerCase())
1506
					{
1507
						case 'application/vnd.google-apps.document':
1508
							fExport(oResponse, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'docx');
1509
							break;
1510
						case 'application/vnd.google-apps.spreadsheet':
1511
							fExport(oResponse, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xlsx');
1512
							break;
1513
						case 'application/vnd.google-apps.drawing':
1514
							fExport(oResponse, 'image/png', 'png');
1515
							break;
1516
						case 'application/vnd.google-apps.presentation':
1517
							fExport(oResponse, 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'pptx');
1518
							break;
1519
						default:
1520
							fExport(oResponse, 'application/pdf', 'pdf');
1521
							break;
1522
					}
1523
				}
1524
1525
				if (oResponse && oResponse.downloadUrl)
1526
				{
1527
					self.addDriveAttachment(oResponse, sAccessToken);
1528
				}
1529
			}
1530
		});
1531
1532
		oRequest.send();
1533
	}
1534
};
1535
1536
ComposePopupView.prototype.driveCreatePiker = function(oOauthToken)
1537
{
1538
	if (window.gapi && oOauthToken && oOauthToken.access_token)
1539
	{
1540
		var self = this;
1541
1542
		window.gapi.load('picker', {'callback': function() {
1543
1544
			if (window.google && window.google.picker)
1545
			{
1546
				var drivePicker = new window.google.picker.PickerBuilder()
1547
					// .addView(window.google.picker.ViewId.FOLDERS)
1548
					.addView(window.google.picker.ViewId.DOCS)
1549
					.setAppId(Settings.settingsGet('GoogleClientID'))
1550
					.setOAuthToken(oOauthToken.access_token)
1551
					.setCallback(_.bind(self.driveCallback, self, oOauthToken.access_token))
1552
					.enableFeature(window.google.picker.Feature.NAV_HIDDEN)
1553
					// .setOrigin(window.location.protocol + '//' + window.location.host)
1554
					.build();
1555
1556
				drivePicker.setVisible(true);
1557
			}
1558
		}});
1559
	}
1560
};
1561
1562
ComposePopupView.prototype.driveOpenPopup = function()
1563
{
1564
	if (window.gapi)
1565
	{
1566
		var self = this;
1567
1568
		window.gapi.load('auth', {'callback': function() {
1569
1570
			var
1571
				oAuthToken = window.gapi.auth.getToken(),
1572
				fResult = function(oAuthResult) {
1573
					if (oAuthResult && !oAuthResult.error)
1574
					{
1575
						var oToken = window.gapi.auth.getToken();
1576
						if (oToken)
1577
						{
1578
							self.driveCreatePiker(oToken);
1579
						}
1580
1581
						return true;
1582
					}
1583
1584
					return false;
1585
				};
1586
1587
			if (!oAuthToken)
1588
			{
1589
				window.gapi.auth.authorize({
1590
					'client_id': Settings.settingsGet('GoogleClientID'),
1591
					'scope': 'https://www.googleapis.com/auth/drive.readonly',
1592
					'immediate': true
1593
				}, function(oAuthResult) {
1594
1595
					if (!fResult(oAuthResult))
1596
					{
1597
						window.gapi.auth.authorize({
1598
							'client_id': Settings.settingsGet('GoogleClientID'),
1599
							'scope': 'https://www.googleapis.com/auth/drive.readonly',
1600
							'immediate': false
1601
						}, fResult);
1602
					}
1603
				});
1604
			}
1605
			else
1606
			{
1607
				self.driveCreatePiker(oAuthToken);
1608
			}
1609
		}});
1610
	}
1611
};
1612
1613
/**
1614
 * @param {string} sId
1615
 * @returns {?Object}
1616
 */
1617
ComposePopupView.prototype.getAttachmentById = function(sId)
1618
{
1619
	var
1620
		aAttachments = this.attachments(),
1621
		iIndex = 0,
1622
		iLen = aAttachments.length;
1623
1624
	for (; iIndex < iLen; iIndex++)
1625
	{
1626
		if (aAttachments[iIndex] && sId === aAttachments[iIndex].id)
1627
		{
1628
			return aAttachments[iIndex];
1629
		}
1630
	}
1631
1632
	return null;
1633
};
1634
1635
ComposePopupView.prototype.cancelAttachmentHelper = function(sId, oJua) {
1636
1637
	var self = this;
1638
	return function() {
1639
1640
		var attachment = _.find(self.attachments(), function(oItem) {
1641
			return oItem && oItem.id === sId;
1642
		});
1643
1644
		if (attachment)
1645
		{
1646
			self.attachments.remove(attachment);
1647
			Utils.delegateRunOnDestroy(attachment);
1648
1649
			if (oJua)
1650
			{
1651
				oJua.cancel(sId);
1652
			}
1653
		}
1654
	};
1655
1656
};
1657
1658
ComposePopupView.prototype.initUploader = function()
1659
{
1660
	if (this.composeUploaderButton())
1661
	{
1662
		var
1663
			oUploadCache = {},
1664
			iAttachmentSizeLimit = Utils.pInt(Settings.settingsGet('AttachmentLimit')),
1665
			oJua = new Jua({
1666
				'action': Links.upload(),
1667
				'name': 'uploader',
1668
				'queueSize': 2,
1669
				'multipleSizeLimit': 50,
1670
				'clickElement': this.composeUploaderButton(),
1671
				'dragAndDropElement': this.composeUploaderDropPlace()
1672
			});
1673
1674
		if (oJua)
1675
		{
1676
			oJua
1677
//				.on('onLimitReached', function(iLimit) {
1678
//					alert(iLimit);
1679
//				})
1680
				.on('onDragEnter', _.bind(function() {
1681
					this.dragAndDropOver(true);
1682
				}, this))
1683
				.on('onDragLeave', _.bind(function() {
1684
					this.dragAndDropOver(false);
1685
				}, this))
1686
				.on('onBodyDragEnter', _.bind(function() {
1687
					this.attachmentsPlace(true);
1688
					this.dragAndDropVisible(true);
1689
				}, this))
1690
				.on('onBodyDragLeave', _.bind(function() {
1691
					this.dragAndDropVisible(false);
1692
				}, this))
1693
				.on('onProgress', _.bind(function(sId, iLoaded, iTotal) {
1694
					var oItem = null;
0 ignored issues
show
Unused Code introduced by
The assignment to oItem seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
1695
					if (Utils.isUnd(oUploadCache[sId]))
1696
					{
1697
						oItem = this.getAttachmentById(sId);
1698
						if (oItem)
1699
						{
1700
							oUploadCache[sId] = oItem;
1701
						}
1702
					}
1703
					else
1704
					{
1705
						oItem = oUploadCache[sId];
1706
					}
1707
1708
					if (oItem)
1709
					{
1710
						oItem.progress(window.Math.floor(iLoaded / iTotal * 100));
1711
					}
1712
1713
				}, this))
1714
				.on('onSelect', _.bind(function(sId, oData) {
1715
1716
					this.dragAndDropOver(false);
1717
1718
					var
1719
						self = this,
1720
						sFileName = Utils.isUnd(oData.FileName) ? '' : oData.FileName.toString(),
1721
						mSize = Utils.isNormal(oData.Size) ? Utils.pInt(oData.Size) : null,
1722
						oAttachment = new ComposeAttachmentModel(sId, sFileName, mSize);
1723
1724
					oAttachment.cancel = self.cancelAttachmentHelper(sId, oJua);
1725
1726
					this.attachments.push(oAttachment);
1727
1728
					this.attachmentsPlace(true);
1729
1730
					if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize)
1731
					{
1732
						oAttachment
1733
							.waiting(false).uploading(true).complete(true)
1734
							.error(Translator.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG'));
1735
1736
						return false;
1737
					}
1738
1739
					return true;
1740
1741
				}, this))
1742
				.on('onStart', _.bind(function(sId) {
1743
1744
					var
1745
						oItem = null;
0 ignored issues
show
Unused Code introduced by
The assignment to oItem seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
1746
1747
					if (Utils.isUnd(oUploadCache[sId]))
1748
					{
1749
						oItem = this.getAttachmentById(sId);
1750
						if (oItem)
1751
						{
1752
							oUploadCache[sId] = oItem;
1753
						}
1754
					}
1755
					else
1756
					{
1757
						oItem = oUploadCache[sId];
1758
					}
1759
1760
					if (oItem)
1761
					{
1762
						oItem.waiting(false).uploading(true).complete(false);
1763
					}
1764
1765
				}, this))
1766
				.on('onComplete', _.bind(function(sId, bResult, oData) {
1767
1768
					var
1769
						sError = '',
1770
						oAttachment = this.getAttachmentById(sId),
1771
						mErrorCode = oData && oData.Result && oData.Result.ErrorCode ? oData.Result.ErrorCode : null,
1772
						oAttachmentJson = bResult && oData && oData.Result && oData.Result.Attachment ? oData.Result.Attachment : null;
1773
1774
					if (null !== mErrorCode)
1775
					{
1776
						sError = Translator.getUploadErrorDescByCode(mErrorCode);
1777
					}
1778
					else if (!oAttachmentJson)
1779
					{
1780
						sError = Translator.i18n('UPLOAD/ERROR_UNKNOWN');
1781
					}
1782
1783
					if (oAttachment)
1784
					{
1785
						if ('' !== sError && 0 < sError.length)
1786
						{
1787
							oAttachment
1788
								.waiting(false)
1789
								.uploading(false)
1790
								.complete(true)
1791
								.error(sError);
1792
						}
1793
						else if (oAttachmentJson)
1794
						{
1795
							oAttachment
1796
								.waiting(false)
1797
								.uploading(false)
1798
								.complete(true);
1799
1800
							oAttachment.initByUploadJson(oAttachmentJson);
1801
						}
1802
1803
						if (Utils.isUnd(oUploadCache[sId]))
1804
						{
1805
							delete (oUploadCache[sId]);
1806
						}
1807
					}
1808
1809
				}, this));
1810
1811
			this
1812
				.addAttachmentEnabled(true)
1813
				.dragAndDropEnabled(oJua.isDragAndDropSupported());
1814
		}
1815
		else
1816
		{
1817
			this
1818
				.addAttachmentEnabled(false)
1819
				.dragAndDropEnabled(false);
1820
		}
1821
	}
1822
};
1823
1824
/**
1825
 * @returns {Object}
1826
 */
1827
ComposePopupView.prototype.prepearAttachmentsForSendOrSave = function()
1828
{
1829
	var oResult = {};
1830
	_.each(this.attachmentsInReady(), function(oItem) {
1831
		if (oItem && '' !== oItem.tempName() && oItem.enabled())
1832
		{
1833
			oResult[oItem.tempName()] = [
1834
				oItem.fileName(),
1835
				oItem.isInline ? '1' : '0',
1836
				oItem.CID,
1837
				oItem.contentLocation
1838
			];
1839
		}
1840
	});
1841
1842
	return oResult;
1843
};
1844
1845
/**
1846
 * @param {MessageModel} oMessage
1847
 */
1848
ComposePopupView.prototype.addMessageAsAttachment = function(oMessage)
1849
{
1850
	if (oMessage)
1851
	{
1852
		var
1853
			oAttachment = null,
0 ignored issues
show
Unused Code introduced by
The assignment to oAttachment seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
1854
			sTemp = oMessage.subject();
1855
1856
		sTemp = '.eml' === sTemp.substr(-4).toLowerCase() ? sTemp : sTemp + '.eml';
1857
		oAttachment = new ComposeAttachmentModel(
1858
			oMessage.requestHash, sTemp, oMessage.size()
1859
		);
1860
1861
		oAttachment.fromMessage = true;
1862
		oAttachment.cancel = this.cancelAttachmentHelper(oMessage.requestHash);
1863
		oAttachment.waiting(false).uploading(true).complete(true);
1864
1865
		this.attachments.push(oAttachment);
1866
	}
1867
};
1868
1869
/**
1870
 * @param {string} url
1871
 * @param {string} name
1872
 * @param {number} size
1873
 * @returns {ComposeAttachmentModel}
1874
 */
1875
ComposePopupView.prototype.addAttachmentHelper = function(url, name, size)
1876
{
1877
	var oAttachment = new ComposeAttachmentModel(url, name, size);
1878
1879
	oAttachment.fromMessage = false;
1880
	oAttachment.cancel = this.cancelAttachmentHelper(url);
1881
	oAttachment.waiting(false).uploading(true).complete(false);
1882
1883
	this.attachments.push(oAttachment);
1884
1885
	this.attachmentsPlace(true);
1886
1887
	return oAttachment;
1888
};
1889
1890
/**
1891
 * @param {Object} oDropboxFile
1892
 * @returns {boolean}
1893
 */
1894
ComposePopupView.prototype.addDropboxAttachment = function(oDropboxFile)
1895
{
1896
	var
1897
		iAttachmentSizeLimit = Utils.pInt(Settings.settingsGet('AttachmentLimit')),
1898
		mSize = oDropboxFile.bytes,
1899
		oAttachment = this.addAttachmentHelper(oDropboxFile.link, oDropboxFile.name, mSize);
1900
1901
	if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize)
1902
	{
1903
		oAttachment.uploading(false).complete(true);
1904
		oAttachment.error(Translator.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG'));
1905
		return false;
1906
	}
1907
1908
	Remote.composeUploadExternals(function(sResult, oData) {
1909
1910
		var bResult = false;
1911
		oAttachment.uploading(false).complete(true);
1912
1913
		if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
1914
		{
1915
			if (oData.Result[oAttachment.id])
1916
			{
1917
				bResult = true;
1918
				oAttachment.tempName(oData.Result[oAttachment.id]);
1919
			}
1920
		}
1921
1922
		if (!bResult)
1923
		{
1924
			oAttachment.error(Translator.getUploadErrorDescByCode(Enums.UploadErrorCode.FileNoUploaded));
1925
		}
1926
1927
	}, [oDropboxFile.link]);
1928
1929
	return true;
1930
};
1931
1932
/**
1933
 * @param {Object} oDriveFile
1934
 * @param {string} sAccessToken
1935
 * @returns {boolean}
1936
 */
1937
ComposePopupView.prototype.addDriveAttachment = function(oDriveFile, sAccessToken)
1938
{
1939
	var
1940
		iAttachmentSizeLimit = Utils.pInt(Settings.settingsGet('AttachmentLimit')),
1941
		mSize = oDriveFile.fileSize ? Utils.pInt(oDriveFile.fileSize) : 0,
1942
		oAttachment = this.addAttachmentHelper(oDriveFile.downloadUrl, oDriveFile.title, mSize);
1943
1944
	if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize)
1945
	{
1946
		oAttachment.uploading(false).complete(true);
1947
		oAttachment.error(Translator.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG'));
1948
		return false;
1949
	}
1950
1951
	Remote.composeUploadDrive(function(sResult, oData) {
1952
1953
		var bResult = false;
1954
		oAttachment.uploading(false).complete(true);
1955
1956
		if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
1957
		{
1958
			if (oData.Result[oAttachment.id])
1959
			{
1960
				bResult = true;
1961
				oAttachment.tempName(oData.Result[oAttachment.id][0]);
1962
				oAttachment.size(Utils.pInt(oData.Result[oAttachment.id][1]));
1963
			}
1964
		}
1965
1966
		if (!bResult)
1967
		{
1968
			oAttachment.error(Translator.getUploadErrorDescByCode(Enums.UploadErrorCode.FileNoUploaded));
1969
		}
1970
1971
	}, oDriveFile.downloadUrl, sAccessToken);
1972
1973
	return true;
1974
};
1975
1976
/**
1977
 * @param {MessageModel} oMessage
1978
 * @param {string} sType
1979
 */
1980
ComposePopupView.prototype.prepearMessageAttachments = function(oMessage, sType)
1981
{
1982
	if (oMessage)
1983
	{
1984
		if (Enums.ComposeType.ForwardAsAttachment === sType)
1985
		{
1986
			this.addMessageAsAttachment(oMessage);
1987
		}
1988
		else
1989
		{
1990
			var aAttachments = oMessage.attachments();
1991
			_.each(Utils.isNonEmptyArray(aAttachments) ? aAttachments : [], function(oItem) {
1992
				var bAdd = false;
0 ignored issues
show
Unused Code introduced by
The assignment to variable bAdd seems to be never used. Consider removing it.
Loading history...
1993
				switch (sType)
1994
				{
1995
					case Enums.ComposeType.Reply:
1996
					case Enums.ComposeType.ReplyAll:
1997
						bAdd = oItem.isLinked;
1998
						break;
1999
2000
					case Enums.ComposeType.Forward:
2001
					case Enums.ComposeType.Draft:
2002
					case Enums.ComposeType.EditAsNew:
2003
						bAdd = true;
2004
						break;
2005
					// no default
2006
				}
2007
2008
				if (bAdd)
2009
				{
2010
					var oAttachment = new ComposeAttachmentModel(
2011
						oItem.download, oItem.fileName, oItem.estimatedSize,
2012
						oItem.isInline, oItem.isLinked, oItem.cid, oItem.contentLocation
2013
					);
2014
2015
					oAttachment.fromMessage = true;
2016
					oAttachment.cancel = this.cancelAttachmentHelper(oItem.download);
2017
					oAttachment.waiting(false).uploading(true).complete(false);
2018
2019
					this.attachments.push(oAttachment);
2020
				}
2021
			});
2022
		}
2023
	}
2024
};
2025
2026
ComposePopupView.prototype.removeLinkedAttachments = function()
2027
{
2028
	var arrachment = _.find(this.attachments(), function(oItem) {
2029
		return oItem && oItem.isLinked;
2030
	});
2031
2032
	if (arrachment)
2033
	{
2034
		this.attachments.remove(arrachment);
2035
		Utils.delegateRunOnDestroy(arrachment);
2036
	}
2037
};
2038
2039
ComposePopupView.prototype.setMessageAttachmentFailedDownloadText = function()
2040
{
2041
	_.each(this.attachments(), function(oAttachment) {
2042
		if (oAttachment && oAttachment.fromMessage)
2043
		{
2044
			oAttachment
2045
				.waiting(false)
2046
				.uploading(false)
2047
				.complete(true)
2048
				.error(Translator.getUploadErrorDescByCode(Enums.UploadErrorCode.FileNoUploaded));
2049
		}
2050
	}, this);
2051
};
2052
2053
/**
2054
 * @param {boolean=} bIncludeAttachmentInProgress = true
2055
 * @returns {boolean}
2056
 */
2057
ComposePopupView.prototype.isEmptyForm = function(bIncludeAttachmentInProgress)
2058
{
2059
	bIncludeAttachmentInProgress = Utils.isUnd(bIncludeAttachmentInProgress) ? true : !!bIncludeAttachmentInProgress;
2060
	var bWithoutAttach = bIncludeAttachmentInProgress ?
2061
		0 === this.attachments().length : 0 === this.attachmentsInReady().length;
2062
2063
	return 0 === this.to().length &&
2064
		0 === this.cc().length &&
2065
		0 === this.bcc().length &&
2066
		0 === this.replyTo().length &&
2067
		0 === this.subject().length &&
2068
		bWithoutAttach &&
2069
		(!this.oEditor || '' === this.oEditor.getData());
2070
};
2071
2072
ComposePopupView.prototype.reset = function()
2073
{
2074
	this.to('');
2075
	this.cc('');
2076
	this.bcc('');
2077
	this.replyTo('');
2078
	this.subject('');
2079
2080
	this.requestDsn(false);
2081
	this.requestReadReceipt(false);
2082
	this.markAsImportant(false);
2083
2084
	this.attachmentsPlace(false);
2085
2086
	this.aDraftInfo = null;
2087
	this.sInReplyTo = '';
2088
	this.bFromDraft = false;
2089
	this.sReferences = '';
2090
2091
	this.sendError(false);
2092
	this.sendSuccessButSaveError(false);
2093
	this.savedError(false);
2094
	this.savedTime(0);
2095
	this.emptyToError(false);
2096
	this.attachmentsInProcessError(false);
2097
2098
	this.showCc(false);
2099
	this.showBcc(false);
2100
	this.showReplyTo(false);
2101
2102
	Utils.delegateRunOnDestroy(this.attachments());
2103
	this.attachments([]);
2104
2105
	this.dragAndDropOver(false);
2106
	this.dragAndDropVisible(false);
2107
2108
	this.draftFolder('');
2109
	this.draftUid('');
2110
2111
	this.sending(false);
2112
	this.saving(false);
2113
2114
	if (this.oEditor)
2115
	{
2116
		this.oEditor.clear(false);
2117
	}
2118
};
2119
2120
/**
2121
 * @returns {Array}
2122
 */
2123
ComposePopupView.prototype.getAttachmentsDownloadsForUpload = function()
2124
{
2125
	return _.map(_.filter(this.attachments(), function(oItem) {
2126
		return oItem && '' === oItem.tempName();
2127
	}), function(oItem) {
2128
		return oItem.id;
2129
	});
2130
};
2131
2132
ComposePopupView.prototype.resizerTrigger = function()
2133
{
2134
	this.resizer(!this.resizer());
2135
};
2136
2137
module.exports = ComposePopupView;
2138