diff --git a/web/src/ui/timeline/TimelineEvent.tsx b/web/src/ui/timeline/TimelineEvent.tsx
index 54c0726..760428e 100644
--- a/web/src/ui/timeline/TimelineEvent.tsx
+++ b/web/src/ui/timeline/TimelineEvent.tsx
@@ -27,7 +27,7 @@ import ReadReceipts from "./ReadReceipts.tsx"
import { ReplyIDBody } from "./ReplyBody.tsx"
import URLPreviews from "./URLPreviews.tsx"
import { ContentErrorBoundary, HiddenEvent, getBodyType, isSmallEvent } from "./content"
-import { EventFullMenu, EventHoverMenu, getModalStyleFromMouse } from "./menu"
+import { EventFixedMenu, EventFullMenu, EventHoverMenu, getModalStyleFromMouse } from "./menu"
import ErrorIcon from "@/icons/error.svg?react"
import PendingIcon from "@/icons/pending.svg?react"
import SentIcon from "@/icons/sent.svg?react"
@@ -98,6 +98,19 @@ const TimelineEvent = ({ evt, prevEvt, disableMenu, smallReplies }: TimelineEven
/>,
})
}
+ const onClick = (mouseEvt: React.MouseEvent) => {
+ const targetElem = mouseEvt.target as HTMLElement
+ if (
+ targetElem.tagName === "A"
+ || targetElem.tagName === "IMG"
+ ) {
+ return
+ }
+ mouseEvt.preventDefault()
+ openModal({
+ content: ,
+ })
+ }
const memberEvt = useRoomMember(client, roomCtx.store, evt.sender)
const memberEvtContent = memberEvt?.content as MemberEventContent | undefined
const BodyType = getBodyType(evt)
@@ -175,11 +188,12 @@ const TimelineEvent = ({ evt, prevEvt, disableMenu, smallReplies }: TimelineEven
data-event-id={evt.event_id}
className={wrapperClassNames.join(" ")}
onContextMenu={onContextMenu}
+ onClick={!disableMenu && isMobileDevice ? onClick : undefined}
>
{!disableMenu && !isMobileDevice &&
-
+
}
{replyAboveMessage}
{renderAvatar && void
}
-export const EventHoverMenu = ({ evt, setForceOpen }: EventHoverMenuProps) => {
- const elements = usePrimaryItems(use(ClientContext)!, useRoomContext(), evt, true, undefined, setForceOpen)
+export const EventHoverMenu = ({ evt, roomCtx, setForceOpen }: EventHoverMenuProps) => {
+ const elements = usePrimaryItems(use(ClientContext)!, roomCtx, evt, true, false, undefined, setForceOpen)
return
{elements}
}
@@ -43,7 +44,7 @@ export const EventExtraMenu = ({ evt, roomCtx, style }: EventContextMenuProps) =
export const EventFullMenu = ({ evt, roomCtx, style }: EventContextMenuProps) => {
const client = use(ClientContext)!
- const primary = usePrimaryItems(client, roomCtx, evt, false, style, undefined)
+ const primary = usePrimaryItems(client, roomCtx, evt, false, false, style, undefined)
const secondary = useSecondaryItems(client, roomCtx, evt)
return
{primary}
@@ -51,3 +52,13 @@ export const EventFullMenu = ({ evt, roomCtx, style }: EventContextMenuProps) =>
{secondary}
}
+
+export const EventFixedMenu = ({ evt, roomCtx }: Omit
) => {
+ const client = use(ClientContext)!
+ const primary = usePrimaryItems(client, roomCtx, evt, false, true, undefined, undefined)
+ const secondary = useSecondaryItems(client, roomCtx, evt, false)
+ return
+ {primary}
+ {secondary}
+
+}
diff --git a/web/src/ui/timeline/menu/index.css b/web/src/ui/timeline/menu/index.css
index 9005345..da720c7 100644
--- a/web/src/ui/timeline/menu/index.css
+++ b/web/src/ui/timeline/menu/index.css
@@ -2,13 +2,9 @@ div.event-hover-menu {
position: absolute;
right: .5rem;
top: -1.5rem;
- background-color: var(--background-color);
border: 1px solid var(--border-color);
border-radius: .5rem;
- display: flex;
- gap: .25rem;
padding: .125rem;
- z-index: 1;
> button {
width: 2rem;
@@ -16,6 +12,28 @@ div.event-hover-menu {
}
}
+div.event-hover-menu, div.event-fixed-menu {
+ display: flex;
+ gap: .25rem;
+ background-color: var(--background-color);
+ z-index: 1;
+}
+
+div.event-fixed-menu {
+ position: fixed;
+ inset: 0 0 auto;
+ height: 3rem;
+ padding: .25rem;
+ border-bottom: 1px solid var(--border-color);
+ justify-content: right;
+ flex-direction: row-reverse;
+
+ > button {
+ width: 3rem;
+ height: 3rem;
+ }
+}
+
div.event-context-menu {
position: fixed;
background-color: var(--background-color);
diff --git a/web/src/ui/timeline/menu/index.ts b/web/src/ui/timeline/menu/index.ts
index fc25eb0..4f89140 100644
--- a/web/src/ui/timeline/menu/index.ts
+++ b/web/src/ui/timeline/menu/index.ts
@@ -13,5 +13,5 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-export { EventExtraMenu, EventFullMenu, EventHoverMenu } from "./EventMenu.tsx"
+export { EventExtraMenu, EventFixedMenu, EventFullMenu, EventHoverMenu } from "./EventMenu.tsx"
export { getModalStyleFromMouse } from "./util.ts"
diff --git a/web/src/ui/timeline/menu/usePrimaryItems.tsx b/web/src/ui/timeline/menu/usePrimaryItems.tsx
index 1ebb0a9..d1f374c 100644
--- a/web/src/ui/timeline/menu/usePrimaryItems.tsx
+++ b/web/src/ui/timeline/menu/usePrimaryItems.tsx
@@ -37,9 +37,11 @@ export const usePrimaryItems = (
roomCtx: RoomContextData,
evt: MemDBEvent,
isHover: boolean,
+ isFixed: boolean,
style?: CSSProperties,
setForceOpen?: (forceOpen: boolean) => void,
) => {
+ const names = !isHover && !isFixed
const closeModal = !isHover ? use(ModalCloseContext) : noop
const openModal = use(ModalContext)
@@ -108,11 +110,11 @@ export const usePrimaryItems = (
return <>
{didFail && }
{canReact && }
{canSend && }
{canEdit && }
{isHover && }
>
diff --git a/web/src/ui/timeline/menu/useSecondaryItems.tsx b/web/src/ui/timeline/menu/useSecondaryItems.tsx
index f577aca..134d4f7 100644
--- a/web/src/ui/timeline/menu/useSecondaryItems.tsx
+++ b/web/src/ui/timeline/menu/useSecondaryItems.tsx
@@ -32,6 +32,7 @@ export const useSecondaryItems = (
client: Client,
roomCtx: RoomContextData,
evt: MemDBEvent,
+ names = true,
) => {
const closeModal = use(ModalCloseContext)
const openModal = use(ModalContext)
@@ -102,20 +103,22 @@ export const useSecondaryItems = (
&& (evt.sender === client.userID || ownPL >= redactOtherPL)
return <>
-
+
{ownPL >= pinPL && (pins.includes(evt.event_id)
?
: )}
-
+
{canRedact && }
+ >{names && "Remove"}}
>
}