import { Trans, useLingui } from '@lingui/react/macro';
import { ControlledMenu, MenuDivider, MenuItem } from '@szhsin/react-menu';
import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
import { useHotkeys } from 'react-hotkeys-hook';
import { useLongPress } from 'use-long-press';
import { useSnapshot } from 'valtio';
import { api } from '../utils/api';
import niceDateTime from '../utils/nice-date-time';
import openCompose from '../utils/open-compose';
import openOSK from '../utils/open-osk';
import pmem from '../utils/pmem';
import safeBoundingBoxPadding from '../utils/safe-bounding-box-padding';
import showCompose from '../utils/show-compose';
import states from '../utils/states';
import statusPeek from '../utils/status-peek';
import { getCurrentAccountID } from '../utils/store-utils';
import Icon from './icon';
import Loader from './loader';
import MenuLink from './menu-link';
import RelativeTime from './relative-time';
import SubMenu2 from './submenu2';
// Function to fetch the latest posts from the current user
// Use pmem to memoize fetch results for 1 minute
const fetchLatestPostsMemoized = pmem(
async (masto, currentAccountID) => {
const statusesIterator = masto.v1.accounts
.$select(currentAccountID)
.statuses.list({
limit: 3,
exclude_replies: true,
exclude_reblogs: true,
});
const { value } = await statusesIterator.next();
return value || [];
},
{ maxAge: 60000 },
); // 1 minute cache
export default function ComposeButton() {
const { t } = useLingui();
const snapStates = useSnapshot(states);
const { masto } = api();
// Context menu state
const [menuOpen, setMenuOpen] = useState(false);
const [latestPosts, setLatestPosts] = useState([]);
const [loadingPosts, setLoadingPosts] = useState(false);
const buttonRef = useRef(null);
const menuRef = useRef(null);
function handleButton(e) {
if (snapStates.composerState.minimized) {
states.composerState.minimized = false;
openOSK();
return;
}
if (e.shiftKey) {
const newWin = openCompose();
if (!newWin) {
states.showCompose = true;
}
} else {
openOSK();
states.showCompose = true;
}
}
useHotkeys('c, shift+c', handleButton, {
ignoreEventWhen: (e) => {
const hasModal = !!document.querySelector('#modal-container > *');
return hasModal;
},
});
// Setup longpress handler to open context menu
const bindLongPress = useLongPress(
() => {
setMenuOpen(true);
},
{
threshold: 600,
},
);
const fetchLatestPosts = useCallback(async () => {
try {
setLoadingPosts(true);
const currentAccountID = getCurrentAccountID();
if (!currentAccountID) {
return;
}
const posts = await fetchLatestPostsMemoized(masto, currentAccountID);
setLatestPosts(posts);
} catch (error) {
} finally {
setLoadingPosts(false);
}
}, [masto]);
// Function to handle opening the compose window to reply to a post
const handleReplyToPost = useCallback((post) => {
showCompose({
replyToStatus: post,
});
setMenuOpen(false);
}, []);
useEffect(() => {
if (menuOpen) {
fetchLatestPosts();
}
}, [fetchLatestPosts, menuOpen]);
return (
<>
setMenuOpen(false)}
direction="top"
gap={8} // Add gap between menu and button
unmountOnClose
portal={{
target: document.body,
}}
boundingBoxPadding={safeBoundingBoxPadding()}
containerProps={{
style: {
zIndex: 19,
},
onClick: () => {
menuRef.current?.closeMenu?.();
},
}}
submenuOpenDelay={600}
>
{' '}
Scheduled Posts
{' '}
Add to thread
{loadingPosts ? '…' : }
>
}
>
{latestPosts.length > 0 &&
latestPosts.map((post) => {
const createdDate = new Date(post.createdAt);
const isWithinDay =
new Date().getTime() - createdDate.getTime() < 86400000;
return (
);
})}
>
);
}