Skip to content

Commit

Permalink
feat: Send images with flag "eternal" if team content (WEBAPP-4840) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
bennycode authored Mar 17, 2018
1 parent 38edc41 commit 25852a8
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 46 deletions.
29 changes: 18 additions & 11 deletions app/script/assets/AssetService.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ z.assets.AssetService = class AssetService {
return Promise.all([this._compressProfileImage(image), this._compressImage(image)])
.then(([{compressedBytes: smallImageBytes}, {compressedBytes: mediumImageBytes}]) => {
return Promise.all([
this.postAsset(smallImageBytes, {public: true}),
this.postAsset(mediumImageBytes, {public: true}),
this.postAsset(smallImageBytes, {public: true, retention: z.assets.AssetRetentionPolicy.ETERNAL}),
this.postAsset(mediumImageBytes, {public: true, retention: z.assets.AssetRetentionPolicy.ETERNAL}),
]);
})
.then(([smallCredentials, mediumCredentials]) => [smallCredentials.key, mediumCredentials.key]);
Expand Down Expand Up @@ -173,36 +173,43 @@ z.assets.AssetService = class AssetService {
});
}

getAssetRetention(userEntity, conversationEntity) {
const isTeamMember = userEntity.is_team_member();
const isTeamConversation = conversationEntity.inTeam();
const isEternal = isTeamMember || isTeamConversation;
return isEternal ? z.assets.AssetRetentionPolicy.ETERNAL : z.assets.AssetRetentionPolicy.PERSISTENT;
}

/**
* Post assets.
*
* @param {Uint8Array} assetData - Asset data
* @param {Object} metadata - Asset metadata
* @param {boolean} [metadata.public] - Flag whether asset is public
* @param {z.assets.AssetRetentionPolicy} [metadata.retention] - Retention duration policy for asset
* @param {Object} options - Asset metadata
* @param {boolean} options.public - Flag whether asset is public
* @param {z.assets.AssetRetentionPolicy} options.retention - Retention duration policy for asset
* @param {Function} [xhrAccessorFunction] - Function will get a reference to the underlying XMLHTTPRequest
* @returns {Promise} Resolves when asset has been uploaded
*/
postAsset(assetData, metadata, xhrAccessorFunction) {
postAsset(assetData, options, xhrAccessorFunction) {
return new Promise((resolve, reject) => {
const BOUNDARY = 'frontier';

metadata = Object.assign(
options = Object.assign(
{
public: false,
retention: z.assets.AssetRetentionPolicy.PERSISTENT,
},
metadata
options
);

metadata = JSON.stringify(metadata);
options = JSON.stringify(options);

let body = '';
body += `--${BOUNDARY}\r\n`;
body += 'Content-Type: application/json; charset=utf-8\r\n';
body += `Content-length: ${metadata.length}\r\n`;
body += `Content-length: ${options.length}\r\n`;
body += '\r\n';
body += `${metadata}\r\n`;
body += `${options}\r\n`;
body += `--${BOUNDARY}\r\n`;
body += 'Content-Type: application/octet-stream\r\n';
body += `Content-length: ${assetData.length}\r\n`;
Expand Down
82 changes: 47 additions & 35 deletions app/script/conversation/ConversationRepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -1497,47 +1497,50 @@ z.conversation.ConversationRepository = class ConversationRepository {
// Send encrypted events
//##############################################################################

send_asset_remotedata(conversation_et, file, message_id) {
let generic_message;
send_asset_remotedata(conversationEntity, file, messageId) {
let genericMessage;

return this.get_message_in_conversation_by_id(conversation_et, message_id)
.then(message_et => {
const asset_et = message_et.get_first_asset();
return this.get_message_in_conversation_by_id(conversationEntity, messageId)
.then(messageEntity => {
const assetEntity = messageEntity.get_first_asset();
const options = {
retention: this.asset_service.getAssetRetention(this.selfUser(), conversationEntity),
};

asset_et.uploaded_on_this_client(true);
return this.asset_service.uploadAsset(file, null, xhr => {
xhr.upload.onprogress = event => asset_et.upload_progress(Math.round(event.loaded / event.total * 100));
asset_et.upload_cancel = () => xhr.abort();
assetEntity.uploaded_on_this_client(true);
return this.asset_service.uploadAsset(file, options, xhr => {
xhr.upload.onprogress = event => assetEntity.upload_progress(Math.round(event.loaded / event.total * 100));
assetEntity.upload_cancel = () => xhr.abort();
});
})
.then(asset => {
generic_message = new z.proto.GenericMessage(message_id);
generic_message.set(z.cryptography.GENERIC_MESSAGE_TYPE.ASSET, asset);
genericMessage = new z.proto.GenericMessage(messageId);
genericMessage.set(z.cryptography.GENERIC_MESSAGE_TYPE.ASSET, asset);

if (conversation_et.ephemeral_timer()) {
generic_message = this._wrap_in_ephemeral_message(generic_message, conversation_et.ephemeral_timer());
if (conversationEntity.ephemeral_timer()) {
genericMessage = this._wrap_in_ephemeral_message(genericMessage, conversationEntity.ephemeral_timer());
}

return this.send_generic_message_to_conversation(conversation_et.id, generic_message);
return this.send_generic_message_to_conversation(conversationEntity.id, genericMessage);
})
.then(payload => {
const {uploaded: asset_data} = conversation_et.ephemeral_timer()
? generic_message.ephemeral.asset
: generic_message.asset;
const {uploaded: assetData} = conversationEntity.ephemeral_timer()
? genericMessage.ephemeral.asset
: genericMessage.asset;

const data = {
key: asset_data.asset_id,
otr_key: asset_data.otr_key,
sha256: asset_data.sha256,
token: asset_data.asset_token,
key: assetData.asset_id,
otr_key: assetData.otr_key,
sha256: assetData.sha256,
token: assetData.asset_token,
};

const asset_add_event = z.conversation.EventBuilder.buildAssetAdd(conversation_et, data, this.timeOffset);
const assetAddEvent = z.conversation.EventBuilder.buildAssetAdd(conversationEntity, data, this.timeOffset);

asset_add_event.id = message_id;
asset_add_event.time = payload.time;
assetAddEvent.id = messageId;
assetAddEvent.time = payload.time;

return this._on_asset_upload_complete(conversation_et, asset_add_event);
return this._on_asset_upload_complete(conversationEntity, assetAddEvent);
});
}

Expand Down Expand Up @@ -1609,7 +1612,11 @@ z.conversation.ConversationRepository = class ConversationRepository {
throw Error('No image available');
}

return this.asset_service.uploadAsset(imageBlob).then(uploadedImageAsset => {
const options = {
retention: this.asset_service.getAssetRetention(this.selfUser(), conversationEntity),
};

return this.asset_service.uploadAsset(imageBlob, options).then(uploadedImageAsset => {
const asset = new z.proto.Asset();
const assetPreview = new z.proto.Asset.Preview(imageBlob.type, imageBlob.size, uploadedImageAsset.uploaded);
asset.set('preview', assetPreview);
Expand Down Expand Up @@ -1727,25 +1734,30 @@ z.conversation.ConversationRepository = class ConversationRepository {
/**
* Sends image asset in specified conversation using v3 api.
*
* @param {Conversation} conversation_et - Conversation to send image in
* @param {Conversation} conversationEntity - Conversation to send image in
* @param {File|Blob} image - Image
* @returns {Promise} Resolves when the image was sent
*/
send_image_asset(conversation_et, image) {
send_image_asset(conversationEntity, image) {
const options = {
retention: this.asset_service.getAssetRetention(this.selfUser(), conversationEntity),
};

return this.asset_service
.uploadImageAsset(image)
.uploadImageAsset(image, options)
.then(asset => {
let generic_message = new z.proto.GenericMessage(z.util.create_random_uuid());
generic_message.set(z.cryptography.GENERIC_MESSAGE_TYPE.ASSET, asset);
let genericMessage = new z.proto.GenericMessage(z.util.create_random_uuid());
genericMessage.set(z.cryptography.GENERIC_MESSAGE_TYPE.ASSET, asset);

if (conversation_et.ephemeral_timer()) {
generic_message = this._wrap_in_ephemeral_message(generic_message, conversation_et.ephemeral_timer());
if (conversationEntity.ephemeral_timer()) {
genericMessage = this._wrap_in_ephemeral_message(genericMessage, conversationEntity.ephemeral_timer());
}

return this._send_and_inject_generic_message(conversation_et, generic_message);
return this._send_and_inject_generic_message(conversationEntity, genericMessage);
})
.catch(error => {
this.logger.error(`Failed to upload otr asset for conversation ${conversation_et.id}: ${error.message}`, error);
const message = `Failed to upload otr asset for conversation ${conversationEntity.id}: ${error.message}`;
this.logger.error(message, error);
throw error;
});
}
Expand Down

0 comments on commit 25852a8

Please sign in to comment.