This repository has been archived by the owner on Nov 3, 2021. It is now read-only.
/
activity_handler.js
executable file
·196 lines (171 loc) · 5.85 KB
/
activity_handler.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/*global ActivityClient,
App,
Attachment,
Draft,
Drafts,
MessageManager,
Navigation,
Settings,
Utils
*/
/*exported ActivityHandler */
'use strict';
/**
* Describes available data types that can be associated with the activities.
* @enum {string}
*/
const ActivityDataType = {
IMAGE: 'image/*',
AUDIO: 'audio/*',
VIDEO: 'video/*',
URL: 'url',
VCARD: 'text/vcard'
};
var ActivityHandler = {
init: function() {
ActivityClient.init(App.instanceId);
ActivityClient.on(
'new-activity-request', this._onNewActivity.bind(this)
);
ActivityClient.on(
'share-activity-request', this._onShareActivity.bind(this)
);
},
_onNewActivity: function newHandler(activityData) {
var viewInfo = {
body: activityData.body,
number: activityData.target || activityData.number,
threadId: null
};
var threadPromise;
var focus = '';
if (viewInfo.number) {
// It's reasonable to focus on composer if we already have some phone
// number or even contact to fill recipients input
focus = 'composer';
/* If we have a body, we're always redirecting to the new message view,
* because we don't want to overwrite any possible draft from an existing
* conversation. */
if (!viewInfo.body) {
// try to get a thread from number
// if no thread, promise is rejected and we try to find a contact
threadPromise = MessageManager.findThreadFromNumber(viewInfo.number)
.then((threadId) => viewInfo.threadId = threadId)
// case no contact and no thread id: gobble the error
.catch(() => {});
}
}
return (threadPromise || Promise.resolve()).then(
() => this.toView(viewInfo, focus)
);
},
_onShareActivity: function shareHandler(activityData) {
var dataToShare = null;
switch(activityData.type) {
case ActivityDataType.AUDIO:
case ActivityDataType.VIDEO:
case ActivityDataType.IMAGE:
var attachments = activityData.blobs.map(function(blob, idx) {
var attachment = new Attachment(blob, {
name: activityData.filenames[idx],
isDraft: true
});
return attachment;
});
var size = attachments.reduce(function(size, attachment) {
if (attachment.type !== 'img') {
size += attachment.size;
}
return size;
}, 0);
if (size > Settings.mmsSizeLimitation) {
Utils.alert({
id: 'attached-files-too-large',
args: {
n: activityData.blobs.length,
mmsSize: (Settings.mmsSizeLimitation / 1024).toFixed(0)
}
}).then(() => ActivityClient.postResult());
return;
}
dataToShare = attachments;
break;
case ActivityDataType.URL:
dataToShare = activityData.url;
break;
// As for the moment we only allow to share one vcard we treat this case
// in an specific block
case ActivityDataType.VCARD:
dataToShare = new Attachment(activityData.blobs[0], {
name: activityData.filenames[0],
isDraft: true
});
break;
default:
ActivityClient.postError(
'Unsupported activity data type: ' + activityData.type
);
return;
}
if (!dataToShare) {
ActivityClient.postError('No data to share found!');
return;
}
return this.toView({ body: dataToShare });
},
/**
* Store a draft for this message, and returns a draftId.
*
* @param {Object} message Message to save
* @param {Number} message.threadId Conversation where this messages is
* located.
* @param {String} message.number The recipient as a phone number or email
* address.
* @param {(String|Attachment|Array.<Attachment>)} [message.body] The data to
* add to the message's body.
* @returns {Promise.<Number>} The new draft id.
*/
_storeDraftFromMessage(message) {
var content = message.body || null;
var isSimpleContent = !content || typeof content === 'string';
var isEmailAddress = message.number && Utils.isEmailAddress(message.number);
var draft = new Draft({
threadId: message.threadId || null,
recipients: message.number && [message.number] || null,
content: !content || Array.isArray(content) ? content : [content],
type: isSimpleContent && !isEmailAddress ? 'sms' : 'mms'
});
return Drafts.request().then(
() => Drafts.add(draft).store()
).then(() => draft.id);
},
/**
* Delivers the user to the correct view based on the params provided in the
* "message" parameter.
* @param {{number: string, body: string, threadId: number}} message It's
* either a message object that belongs to a thread, or a message object from
* the system. "number" is a string phone number to pre-populate the
* recipients list with, "body" is an optional body to preset the compose
* input with, "threadId" is an optional threadId corresponding to a new or
* existing thread.
* @param {string?} focus indicates which of 'composer' or 'recipients' field
* we need to focus when we navigate to Thread panel.
*/
toView: function ah_toView(message, focus) {
return Utils.onceDocumentIsVisible().then(() => {
// If we have appropriate thread then let's forward user there, otherwise
// open new message composer.
if (message.threadId) {
return Navigation.toPanel('thread', {
id: message.threadId,
focus
});
}
return this._storeDraftFromMessage(message).then(
(draftId) => Navigation.toPanel('composer', { draftId, focus })
);
});
}
};