open menu when clicking ... button on message with delete/cancel option
This commit is contained in:
parent
63e948fc80
commit
2b0fa22c8a
6 changed files with 70 additions and 7 deletions
|
@ -49,12 +49,13 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.Timeline_message:hover, .Timeline_message.selected {
|
.Timeline_message:hover, .Timeline_message.selected, .Timeline_message.menuOpen {
|
||||||
background-color: rgba(141, 151, 165, 0.1);
|
background-color: rgba(141, 151, 165, 0.1);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Timeline_message:hover > .Timeline_messageOptions {
|
.Timeline_message:hover > .Timeline_messageOptions,
|
||||||
|
.Timeline_message.menuOpen > .Timeline_messageOptions {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,13 +30,14 @@ const VerticalAxis = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Popup {
|
export class Popup {
|
||||||
constructor(view) {
|
constructor(view, closeCallback = null) {
|
||||||
this._view = view;
|
this._view = view;
|
||||||
this._target = null;
|
this._target = null;
|
||||||
this._arrangement = null;
|
this._arrangement = null;
|
||||||
this._scroller = null;
|
this._scroller = null;
|
||||||
this._fakeRoot = null;
|
this._fakeRoot = null;
|
||||||
this._trackingTemplateView = null;
|
this._trackingTemplateView = null;
|
||||||
|
this._closeCallback = closeCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
trackInTemplateView(templateView) {
|
trackInTemplateView(templateView) {
|
||||||
|
@ -82,6 +83,9 @@ export class Popup {
|
||||||
document.body.removeEventListener("click", this, false);
|
document.body.removeEventListener("click", this, false);
|
||||||
this._popup.remove();
|
this._popup.remove();
|
||||||
this._view = null;
|
this._view = null;
|
||||||
|
if (this._closeCallback) {
|
||||||
|
this._closeCallback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ export class TimelineList extends ListView {
|
||||||
const options = {
|
const options = {
|
||||||
className: "Timeline bottom-aligned-scroll",
|
className: "Timeline bottom-aligned-scroll",
|
||||||
list: viewModel.tiles,
|
list: viewModel.tiles,
|
||||||
|
onItemClick: (tileView, evt) => tileView.onClick(evt),
|
||||||
}
|
}
|
||||||
super(options, entry => {
|
super(options, entry => {
|
||||||
const View = viewClassForEntry(entry);
|
const View = viewClassForEntry(entry);
|
||||||
|
|
|
@ -20,4 +20,7 @@ export class AnnouncementView extends TemplateView {
|
||||||
render(t) {
|
render(t) {
|
||||||
return t.li({className: "AnnouncementView"}, t.div(vm => vm.announcement));
|
return t.li({className: "AnnouncementView"}, t.div(vm => vm.announcement));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is called by the parent ListView, which just has 1 listener for the whole list */
|
||||||
|
onClick() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,15 @@ limitations under the License.
|
||||||
|
|
||||||
import {renderStaticAvatar} from "../../../avatar.js";
|
import {renderStaticAvatar} from "../../../avatar.js";
|
||||||
import {TemplateView} from "../../../general/TemplateView.js";
|
import {TemplateView} from "../../../general/TemplateView.js";
|
||||||
|
import {Popup} from "../../../general/Popup.js";
|
||||||
|
import {Menu} from "../../../general/Menu.js";
|
||||||
|
|
||||||
export class BaseMessageView extends TemplateView {
|
export class BaseMessageView extends TemplateView {
|
||||||
|
constructor(value) {
|
||||||
|
super(value);
|
||||||
|
this._menuPopup = null;
|
||||||
|
}
|
||||||
|
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
const classes = {
|
const classes = {
|
||||||
"Timeline_message": true,
|
"Timeline_message": true,
|
||||||
|
@ -36,7 +43,46 @@ export class BaseMessageView extends TemplateView {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMessageBody() {
|
/* This is called by the parent ListView, which just has 1 listener for the whole list */
|
||||||
|
onClick(evt) {
|
||||||
|
if (evt.target.className === "Timeline_messageOptions") {
|
||||||
|
this._toggleMenu(evt.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_toggleMenu(button) {
|
||||||
|
if (this._menuPopup && this._menuPopup.isOpen) {
|
||||||
|
this._menuPopup.close();
|
||||||
|
} else {
|
||||||
|
const options = this.createMenuOptions(this.value);
|
||||||
|
if (!options.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.root().classList.add("menuOpen");
|
||||||
|
this._menuPopup = new Popup(new Menu(options), () => this.root().classList.remove("menuOpen"));
|
||||||
|
this._menuPopup.trackInTemplateView(this);
|
||||||
|
this._menuPopup.showRelativeTo(button, {
|
||||||
|
horizontal: {
|
||||||
|
relativeTo: "end",
|
||||||
|
align: "start",
|
||||||
|
after: 0
|
||||||
|
},
|
||||||
|
vertical: {
|
||||||
|
relativeTo: "start",
|
||||||
|
align: "end",
|
||||||
|
before: -24
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createMenuOptions(vm) {
|
||||||
|
const options = [];
|
||||||
|
if (vm.shape !== "redacted") {
|
||||||
|
options.push(Menu.option(vm.i18n`Delete`, () => vm.redact()));
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMessageBody() {}
|
||||||
|
}
|
||||||
|
|
|
@ -15,10 +15,18 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {BaseMessageView} from "./BaseMessageView.js";
|
import {BaseMessageView} from "./BaseMessageView.js";
|
||||||
|
import {Menu} from "../../../general/Menu.js";
|
||||||
|
|
||||||
export class RedactedView extends BaseMessageView {
|
export class RedactedView extends BaseMessageView {
|
||||||
renderMessageBody(t, vm) {
|
renderMessageBody(t, vm) {
|
||||||
const cancelButton = t.if(vm => vm.isRedacting, t => t.button({onClick: () => vm.abortPendingRedaction()}, "Cancel"));
|
return t.p({className: "Timeline_messageBody statusMessage"}, vm => vm.description);
|
||||||
return t.p({className: "Timeline_messageBody statusMessage"}, [vm => vm.description, " ", cancelButton]);
|
}
|
||||||
|
|
||||||
|
createMenuOptions(vm) {
|
||||||
|
const options = super.createMenuOptions(vm);
|
||||||
|
if (vm.isRedacting) {
|
||||||
|
options.push(Menu.option(vm.i18n`Cancel`, () => vm.abortPendingRedaction()));
|
||||||
|
}
|
||||||
|
return options;
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in a new issue