From 7430aa7aab7f9652c38672ab11539ace9503dfbd Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Sat, 25 Jun 2022 20:14:32 +0200 Subject: [PATCH 1/2] allow download media in media view model --- .../room/timeline/tiles/BaseMediaTile.js | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/domain/session/room/timeline/tiles/BaseMediaTile.js b/src/domain/session/room/timeline/tiles/BaseMediaTile.js index 0ba5b9a9..aa53661c 100644 --- a/src/domain/session/room/timeline/tiles/BaseMediaTile.js +++ b/src/domain/session/room/timeline/tiles/BaseMediaTile.js @@ -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 ""; } } From 3369bda2f09857c53a51171d402893d7c37e2646 Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Sat, 25 Jun 2022 20:14:55 +0200 Subject: [PATCH 2/2] offer menu options to download media also always show status (before sendStatus), not just when isPending as we are recycling it to show download status as well --- .../web/ui/css/themes/element/timeline.css | 4 +-- .../ui/session/room/timeline/BaseMediaView.js | 30 ++++++++++++++----- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/platform/web/ui/css/themes/element/timeline.css b/src/platform/web/ui/css/themes/element/timeline.css index bac4b4a5..43c57d19 100644 --- a/src/platform/web/ui/css/themes/element/timeline.css +++ b/src/platform/web/ui/css/themes/element/timeline.css @@ -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; diff --git a/src/platform/web/ui/session/room/timeline/BaseMediaView.js b/src/platform/web/ui/session/room/timeline/BaseMediaView.js index c52fbaed..16b5de14 100644 --- a/src/platform/web/ui/session/room/timeline/BaseMediaView.js +++ b/src/platform/web/ui/session/room/timeline/BaseMediaView.js @@ -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), ]; + const status = t.div({ + className: { + status: true, + hidden: vm => !vm.status + }, + }, vm => vm.status); + children.push(status); if (vm.isPending) { - const sendStatus = t.div({ - className: { - sendStatus: true, - hidden: vm => !vm.sendStatus - }, - }, vm => vm.sendStatus); 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; + } }