put redactions in their own view, and allow aborting while still queued
This commit is contained in:
parent
cb622be653
commit
ce7147e463
4 changed files with 79 additions and 16 deletions
|
@ -14,20 +14,31 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {BaseTextTile} from "./BaseTextTile.js";
|
import {BaseMessageTile} from "./BaseMessageTile.js";
|
||||||
|
|
||||||
export class RedactedTile extends BaseTextTile {
|
export class RedactedTile extends BaseMessageTile {
|
||||||
get shape() {
|
get shape() {
|
||||||
return "redacted";
|
return "redacted";
|
||||||
}
|
}
|
||||||
|
|
||||||
_getBodyAsString() {
|
get description() {
|
||||||
const {redactionReason} = this._entry;
|
const {redactionReason} = this._entry;
|
||||||
if (redactionReason) {
|
if (this.isRedacting) {
|
||||||
return this.i18n`This message has been deleted (${redactionReason}).`;
|
return this.i18n`This message is being deleted …`;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return this.i18n`This message has been deleted.`;
|
if (redactionReason) {
|
||||||
|
return this.i18n`This message has been deleted (${redactionReason}).`;
|
||||||
|
} else {
|
||||||
|
return this.i18n`This message has been deleted.`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isRedacting() {
|
||||||
|
return this._entry.isRedacting;
|
||||||
|
}
|
||||||
|
|
||||||
|
abortPendingRedaction() {
|
||||||
|
return this._entry.abortPendingRedaction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,17 @@ import {REDACTION_TYPE} from "../../common.js";
|
||||||
export class BaseEventEntry extends BaseEntry {
|
export class BaseEventEntry extends BaseEntry {
|
||||||
constructor(fragmentIdComparer) {
|
constructor(fragmentIdComparer) {
|
||||||
super(fragmentIdComparer);
|
super(fragmentIdComparer);
|
||||||
this._localRedactCount = 0;
|
this._pendingRedactions = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isRedacting() {
|
||||||
|
return !!this._pendingRedactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isRedacted() {
|
get isRedacted() {
|
||||||
return this._localRedactCount > 0;
|
return this.isRedacting;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,8 +39,11 @@ export class BaseEventEntry extends BaseEntry {
|
||||||
*/
|
*/
|
||||||
addLocalRelation(entry) {
|
addLocalRelation(entry) {
|
||||||
if (entry.eventType === REDACTION_TYPE) {
|
if (entry.eventType === REDACTION_TYPE) {
|
||||||
this._localRedactCount += 1;
|
if (!this._pendingRedactions) {
|
||||||
if (this._localRedactCount === 1) {
|
this._pendingRedactions = [];
|
||||||
|
}
|
||||||
|
this._pendingRedactions.push(entry);
|
||||||
|
if (this._pendingRedactions.length === 1) {
|
||||||
return "isRedacted";
|
return "isRedacted";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,11 +54,25 @@ export class BaseEventEntry extends BaseEntry {
|
||||||
@return [string] returns the name of the field that has changed, if any
|
@return [string] returns the name of the field that has changed, if any
|
||||||
*/
|
*/
|
||||||
removeLocalRelation(entry) {
|
removeLocalRelation(entry) {
|
||||||
if (entry.eventType === REDACTION_TYPE) {
|
if (entry.eventType === REDACTION_TYPE && this._pendingRedactions) {
|
||||||
this._localRedactCount -= 1;
|
const countBefore = this._pendingRedactions.length;
|
||||||
if (this._localRedactCount === 0) {
|
this._pendingRedactions = this._pendingRedactions.filter(e => e !== entry);
|
||||||
return "isRedacted";
|
if (this._pendingRedactions.length === 0) {
|
||||||
|
this._pendingRedactions = null;
|
||||||
|
if (countBefore !== 0) {
|
||||||
|
return "isRedacted";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async abortPendingRedaction() {
|
||||||
|
if (this._pendingRedactions) {
|
||||||
|
for (const pee of this._pendingRedactions) {
|
||||||
|
await pee.pendingEvent.abort();
|
||||||
|
}
|
||||||
|
// removing the pending events will call removeLocalRelation,
|
||||||
|
// so don't clear _pendingRedactions here
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -22,6 +22,7 @@ import {VideoView} from "./timeline/VideoView.js";
|
||||||
import {FileView} from "./timeline/FileView.js";
|
import {FileView} from "./timeline/FileView.js";
|
||||||
import {MissingAttachmentView} from "./timeline/MissingAttachmentView.js";
|
import {MissingAttachmentView} from "./timeline/MissingAttachmentView.js";
|
||||||
import {AnnouncementView} from "./timeline/AnnouncementView.js";
|
import {AnnouncementView} from "./timeline/AnnouncementView.js";
|
||||||
|
import {RedactedView} from "./timeline/RedactedView.js";
|
||||||
|
|
||||||
function viewClassForEntry(entry) {
|
function viewClassForEntry(entry) {
|
||||||
switch (entry.shape) {
|
switch (entry.shape) {
|
||||||
|
@ -29,12 +30,13 @@ function viewClassForEntry(entry) {
|
||||||
case "announcement": return AnnouncementView;
|
case "announcement": return AnnouncementView;
|
||||||
case "message":
|
case "message":
|
||||||
case "message-status":
|
case "message-status":
|
||||||
case "redacted":
|
|
||||||
return TextMessageView;
|
return TextMessageView;
|
||||||
case "image": return ImageView;
|
case "image": return ImageView;
|
||||||
case "video": return VideoView;
|
case "video": return VideoView;
|
||||||
case "file": return FileView;
|
case "file": return FileView;
|
||||||
case "missing-attachment": return MissingAttachmentView;
|
case "missing-attachment": return MissingAttachmentView;
|
||||||
|
case "redacted":
|
||||||
|
return RedactedView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
src/platform/web/ui/session/room/timeline/RedactedView.js
Normal file
27
src/platform/web/ui/session/room/timeline/RedactedView.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {TemplateView} from "../../../general/TemplateView.js";
|
||||||
|
import {renderMessage} from "./common.js";
|
||||||
|
|
||||||
|
export class RedactedView extends TemplateView {
|
||||||
|
render(t, vm) {
|
||||||
|
const cancelButton = t.if(vm => vm.isRedacting, t => t.button({onClick: () => vm.abortPendingRedaction()}, "Cancel"));
|
||||||
|
return renderMessage(t, vm,
|
||||||
|
[t.p([vm => vm.description, " ", cancelButton, t.time({className: {hidden: !vm.date}}, vm.date + " " + vm.time)])]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue