forked from mystiq/hydrogen-web
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);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.Timeline_message:hover > .Timeline_messageOptions {
|
||||
.Timeline_message:hover > .Timeline_messageOptions,
|
||||
.Timeline_message.menuOpen > .Timeline_messageOptions {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,13 +30,14 @@ const VerticalAxis = {
|
|||
};
|
||||
|
||||
export class Popup {
|
||||
constructor(view) {
|
||||
constructor(view, closeCallback = null) {
|
||||
this._view = view;
|
||||
this._target = null;
|
||||
this._arrangement = null;
|
||||
this._scroller = null;
|
||||
this._fakeRoot = null;
|
||||
this._trackingTemplateView = null;
|
||||
this._closeCallback = closeCallback;
|
||||
}
|
||||
|
||||
trackInTemplateView(templateView) {
|
||||
|
@ -82,6 +83,9 @@ export class Popup {
|
|||
document.body.removeEventListener("click", this, false);
|
||||
this._popup.remove();
|
||||
this._view = null;
|
||||
if (this._closeCallback) {
|
||||
this._closeCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ export class TimelineList extends ListView {
|
|||
const options = {
|
||||
className: "Timeline bottom-aligned-scroll",
|
||||
list: viewModel.tiles,
|
||||
onItemClick: (tileView, evt) => tileView.onClick(evt),
|
||||
}
|
||||
super(options, entry => {
|
||||
const View = viewClassForEntry(entry);
|
||||
|
|
|
@ -20,4 +20,7 @@ export class AnnouncementView extends TemplateView {
|
|||
render(t) {
|
||||
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 {TemplateView} from "../../../general/TemplateView.js";
|
||||
import {Popup} from "../../../general/Popup.js";
|
||||
import {Menu} from "../../../general/Menu.js";
|
||||
|
||||
export class BaseMessageView extends TemplateView {
|
||||
constructor(value) {
|
||||
super(value);
|
||||
this._menuPopup = null;
|
||||
}
|
||||
|
||||
render(t, vm) {
|
||||
const classes = {
|
||||
"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 {Menu} from "../../../general/Menu.js";
|
||||
|
||||
export class RedactedView extends BaseMessageView {
|
||||
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, " ", cancelButton]);
|
||||
return t.p({className: "Timeline_messageBody statusMessage"}, vm => vm.description);
|
||||
}
|
||||
|
||||
createMenuOptions(vm) {
|
||||
const options = super.createMenuOptions(vm);
|
||||
if (vm.isRedacting) {
|
||||
options.push(Menu.option(vm.i18n`Cancel`, () => vm.abortPendingRedaction()));
|
||||
}
|
||||
return options;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue