progress bar for upload, add cancel button, no lightbox while uploading
This commit is contained in:
parent
6f94ca1a4a
commit
47147f2d46
4 changed files with 56 additions and 19 deletions
|
@ -46,6 +46,11 @@ export class SimpleTile extends ViewModel {
|
||||||
get isPending() {
|
get isPending() {
|
||||||
return this._entry.isPending;
|
return this._entry.isPending;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abortSending() {
|
||||||
|
this._entry.pendingEvent?.abort();
|
||||||
|
}
|
||||||
|
|
||||||
// TilesCollection contract below
|
// TilesCollection contract below
|
||||||
setUpdateEmit(emitUpdate) {
|
setUpdateEmit(emitUpdate) {
|
||||||
this.updateOptions({emitChange: paramName => {
|
this.updateOptions({emitChange: paramName => {
|
||||||
|
|
|
@ -557,11 +557,17 @@ ul.Timeline > li.messageStatus .message-container > p {
|
||||||
|
|
||||||
.message-container .picture {
|
.message-container .picture {
|
||||||
display: grid;
|
display: grid;
|
||||||
text-decoration: none;
|
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.message-container .picture > a {
|
||||||
|
text-decoration: none;
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
/* .spacer grows with an inline padding-top to the size of the image,
|
/* .spacer grows with an inline padding-top to the size of the image,
|
||||||
so the timeline doesn't jump when the image loads */
|
so the timeline doesn't jump when the image loads */
|
||||||
.message-container .picture > * {
|
.message-container .picture > * {
|
||||||
|
@ -569,24 +575,41 @@ so the timeline doesn't jump when the image loads */
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-container .picture > img {
|
.message-container .picture img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
/* for IE11 to still scale even though the spacer is too tall */
|
/* for IE11 to still scale even though the spacer is too tall */
|
||||||
align-self: start;
|
align-self: start;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
/* stretch the image (to the spacer) on platforms
|
/* stretch the image (to the spacer) on platforms
|
||||||
where we can trust the spacer to always have the correct height,
|
where we can trust the spacer to always have the correct height,
|
||||||
otherwise the image starts with height 0 and with loading=lazy
|
otherwise the image starts with height 0 and with loading=lazy
|
||||||
only loads when the top comes into view*/
|
only loads when the top comes into view*/
|
||||||
.hydrogen:not(.legacy) .message-container .picture > img {
|
.hydrogen:not(.legacy) .message-container .picture img {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-container .picture > .sendStatus {
|
||||||
|
align-self: end;
|
||||||
|
justify-self: start;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-container .picture > progress {
|
||||||
|
align-self: center;
|
||||||
|
justify-self: center;
|
||||||
|
width: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
.message-container .picture > time {
|
.message-container .picture > time {
|
||||||
align-self: end;
|
align-self: end;
|
||||||
justify-self: end;
|
justify-self: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-container .picture > time,
|
||||||
|
.message-container .picture > .sendStatus {
|
||||||
color: #2e2f32;
|
color: #2e2f32;
|
||||||
display: block;
|
display: block;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
|
|
|
@ -94,7 +94,7 @@ export const TAG_NAMES = {
|
||||||
[HTML_NS]: [
|
[HTML_NS]: [
|
||||||
"br", "a", "ol", "ul", "li", "div", "h1", "h2", "h3", "h4", "h5", "h6",
|
"br", "a", "ol", "ul", "li", "div", "h1", "h2", "h3", "h4", "h5", "h6",
|
||||||
"p", "strong", "em", "span", "img", "section", "main", "article", "aside",
|
"p", "strong", "em", "span", "img", "section", "main", "article", "aside",
|
||||||
"pre", "button", "time", "input", "textarea", "label", "form"],
|
"pre", "button", "time", "input", "textarea", "label", "form", "progress"],
|
||||||
[SVG_NS]: ["svg", "circle"]
|
[SVG_NS]: ["svg", "circle"]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ limitations under the License.
|
||||||
|
|
||||||
import {TemplateView} from "../../../general/TemplateView.js";
|
import {TemplateView} from "../../../general/TemplateView.js";
|
||||||
import {renderMessage} from "./common.js";
|
import {renderMessage} from "./common.js";
|
||||||
import {spinner} from "../../../common.js";
|
|
||||||
|
|
||||||
export class ImageView extends TemplateView {
|
export class ImageView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
|
@ -32,26 +31,36 @@ export class ImageView extends TemplateView {
|
||||||
// can slow down rendering, and was bleeding through the lightbox.
|
// can slow down rendering, and was bleeding through the lightbox.
|
||||||
spacerStyle = `height: ${vm.thumbnailHeight}px`;
|
spacerStyle = `height: ${vm.thumbnailHeight}px`;
|
||||||
}
|
}
|
||||||
const children = [
|
const img = t.img({
|
||||||
t.div({className: "spacer", style: spacerStyle}),
|
|
||||||
t.img({
|
|
||||||
loading: "lazy",
|
loading: "lazy",
|
||||||
src: vm => vm.thumbnailUrl,
|
src: vm => vm.thumbnailUrl,
|
||||||
alt: vm => vm.label,
|
alt: vm => vm.label,
|
||||||
title: vm => vm.label,
|
title: vm => vm.label,
|
||||||
style: `max-width: ${vm.thumbnailWidth}px; max-height: ${vm.thumbnailHeight}px;`
|
style: `max-width: ${vm.thumbnailWidth}px; max-height: ${vm.thumbnailHeight}px;`
|
||||||
}),
|
});
|
||||||
|
const children = [
|
||||||
|
vm.isPending ? img : t.a({href: vm.lightboxUrl}, img),
|
||||||
|
t.div({className: "spacer", style: spacerStyle}),
|
||||||
t.time(vm.date + " " + vm.time),
|
t.time(vm.date + " " + vm.time),
|
||||||
];
|
];
|
||||||
if (vm.isUploading) {
|
if (vm.isPending) {
|
||||||
const uploadStatus = t.div({className: "uploadStatus"}, [
|
const cancel = t.button({onClick: () => vm.abortSending(), className: "link"}, vm.i18n`Cancel`);
|
||||||
spinner(t),
|
const sendStatus = t.div({
|
||||||
vm => vm.uploadStatus
|
className: {
|
||||||
]);
|
sendStatus: true,
|
||||||
children.push(uploadStatus);
|
hidden: vm => !vm.sendStatus
|
||||||
|
},
|
||||||
|
}, [vm => vm.sendStatus, " ", cancel]);
|
||||||
|
const progress = t.progress({
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
value: vm => vm.uploadPercentage,
|
||||||
|
className: {hidden: vm => !vm.isUploading}
|
||||||
|
});
|
||||||
|
children.push(sendStatus, progress);
|
||||||
}
|
}
|
||||||
return renderMessage(t, vm, [
|
return renderMessage(t, vm, [
|
||||||
t.a({href: vm.lightboxUrl, className: "picture", style: `max-width: ${vm.thumbnailWidth}px`}, children),
|
t.div({className: "picture", style: `max-width: ${vm.thumbnailWidth}px`}, children),
|
||||||
t.if(vm => vm.error, t.createTemplate((t, vm) => t.p({className: "error"}, vm.error)))
|
t.if(vm => vm.error, t.createTemplate((t, vm) => t.p({className: "error"}, vm.error)))
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue