Merge pull request #767 from vector-im/bwindels/download-media
Menu option to download attached image or video of event
This commit is contained in:
commit
ad8ad22cc1
3 changed files with 55 additions and 10 deletions
|
@ -27,6 +27,29 @@ export class BaseMediaTile extends BaseMessageTile {
|
|||
this._decryptedFile = null;
|
||||
this._isVisible = false;
|
||||
this._error = null;
|
||||
this._downloading = false;
|
||||
this._downloadError = null;
|
||||
}
|
||||
|
||||
async downloadMedia() {
|
||||
if (this._downloading || this.isPending) {
|
||||
return;
|
||||
}
|
||||
const content = this._getContent();
|
||||
const filename = content.body;
|
||||
this._downloading = true;
|
||||
this.emitChange("status");
|
||||
let blob;
|
||||
try {
|
||||
blob = await this._mediaRepository.downloadAttachment(content);
|
||||
this.platform.saveFileAs(blob, filename);
|
||||
} catch (err) {
|
||||
this._downloadError = err;
|
||||
} finally {
|
||||
blob?.dispose();
|
||||
this._downloading = false;
|
||||
}
|
||||
this.emitChange("status");
|
||||
}
|
||||
|
||||
get isUploading() {
|
||||
|
@ -38,7 +61,7 @@ export class BaseMediaTile extends BaseMessageTile {
|
|||
return pendingEvent && Math.round((pendingEvent.attachmentsSentBytes / pendingEvent.attachmentsTotalBytes) * 100);
|
||||
}
|
||||
|
||||
get sendStatus() {
|
||||
get status() {
|
||||
const {pendingEvent} = this._entry;
|
||||
switch (pendingEvent?.status) {
|
||||
case SendStatus.Waiting:
|
||||
|
@ -53,6 +76,12 @@ export class BaseMediaTile extends BaseMessageTile {
|
|||
case SendStatus.Error:
|
||||
return this.i18n`Error: ${pendingEvent.error.message}`;
|
||||
default:
|
||||
if (this._downloadError) {
|
||||
return `Download failed`;
|
||||
}
|
||||
if (this._downloading) {
|
||||
return this.i18n`Downloading…`;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -233,7 +233,7 @@ only loads when the top comes into view*/
|
|||
align-self: stretch;
|
||||
}
|
||||
|
||||
.Timeline_messageBody .media > .sendStatus {
|
||||
.Timeline_messageBody .media > .status {
|
||||
align-self: end;
|
||||
justify-self: start;
|
||||
font-size: 0.8em;
|
||||
|
@ -251,7 +251,7 @@ only loads when the top comes into view*/
|
|||
}
|
||||
|
||||
.Timeline_messageBody .media > time,
|
||||
.Timeline_messageBody .media > .sendStatus {
|
||||
.Timeline_messageBody .media > .status {
|
||||
color: var(--text-color);
|
||||
display: block;
|
||||
padding: 2px;
|
||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {BaseMessageView} from "./BaseMessageView.js";
|
||||
import {Menu} from "../../../general/Menu.js";
|
||||
|
||||
export class BaseMediaView extends BaseMessageView {
|
||||
renderMessageBody(t, vm) {
|
||||
|
@ -35,24 +36,39 @@ export class BaseMediaView extends BaseMessageView {
|
|||
this.renderMedia(t, vm),
|
||||
t.time(vm.date + " " + vm.time),
|
||||
];
|
||||
if (vm.isPending) {
|
||||
const sendStatus = t.div({
|
||||
const status = t.div({
|
||||
className: {
|
||||
sendStatus: true,
|
||||
hidden: vm => !vm.sendStatus
|
||||
status: true,
|
||||
hidden: vm => !vm.status
|
||||
},
|
||||
}, vm => vm.sendStatus);
|
||||
}, vm => vm.status);
|
||||
children.push(status);
|
||||
if (vm.isPending) {
|
||||
const progress = t.progress({
|
||||
min: 0,
|
||||
max: 100,
|
||||
value: vm => vm.uploadPercentage,
|
||||
className: {hidden: vm => !vm.isUploading}
|
||||
});
|
||||
children.push(sendStatus, progress);
|
||||
children.push(progress);
|
||||
}
|
||||
return t.div({className: "Timeline_messageBody"}, [
|
||||
t.div({className: "media", style: `max-width: ${vm.width}px`}, children),
|
||||
t.if(vm => vm.error, t => t.p({className: "error"}, vm.error))
|
||||
]);
|
||||
}
|
||||
|
||||
createMenuOptions(vm) {
|
||||
const options = super.createMenuOptions(vm);
|
||||
if (!vm.isPending) {
|
||||
let label;
|
||||
switch (vm.shape) {
|
||||
case "image": label = vm.i18n`Download image`; break;
|
||||
case "video": label = vm.i18n`Download video`; break;
|
||||
default: label = vm.i18n`Download media`; break;
|
||||
}
|
||||
options.push(Menu.option(label, () => vm.downloadMedia()));
|
||||
}
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue