v0.7.1 bugs fix for last update
This commit is contained in:
@@ -50,40 +50,11 @@ export default function Sidebar({ groups, activeGroupId, onSelectGroup, notifica
|
||||
const { connected } = useSocket();
|
||||
const toast = useToast();
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [contextMenu, setContextMenu] = useState(null); // { groupId, x, y, isPinned }
|
||||
const settings = useAppSettings();
|
||||
const [dark, setDark] = useTheme();
|
||||
const menuRef = useRef(null);
|
||||
const footerBtnRef = useRef(null);
|
||||
|
||||
const handlePin = async (groupId) => {
|
||||
try {
|
||||
await api.pinDM(groupId);
|
||||
onGroupsUpdated();
|
||||
} catch (e) { toast(e.message, 'error'); }
|
||||
setContextMenu(null);
|
||||
};
|
||||
|
||||
const handleUnpin = async (groupId) => {
|
||||
try {
|
||||
await api.unpinDM(groupId);
|
||||
onGroupsUpdated();
|
||||
} catch (e) { toast(e.message, 'error'); }
|
||||
setContextMenu(null);
|
||||
};
|
||||
|
||||
// Close context menu on outside click
|
||||
useEffect(() => {
|
||||
if (!contextMenu) return;
|
||||
const close = () => setContextMenu(null);
|
||||
document.addEventListener('mousedown', close);
|
||||
document.addEventListener('touchstart', close);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', close);
|
||||
document.removeEventListener('touchstart', close);
|
||||
};
|
||||
}, [contextMenu]);
|
||||
|
||||
// Fix 6: swipe right to go back on mobile — handled in ChatWindow, but prevent sidebar swipe exit
|
||||
// Close menu on click outside
|
||||
useEffect(() => {
|
||||
@@ -111,11 +82,8 @@ export default function Sidebar({ groups, activeGroupId, onSelectGroup, notifica
|
||||
];
|
||||
|
||||
const publicFiltered = allGroups.filter(g => g.type === 'public');
|
||||
const pinnedDMs = allGroups
|
||||
.filter(g => g.type === 'private' && g.is_direct && g.pin_order != null)
|
||||
.sort((a, b) => a.pin_order - b.pin_order);
|
||||
const unpinnedDMs = allGroups
|
||||
.filter(g => g.type === 'private' && g.is_direct && g.pin_order == null)
|
||||
const dms = allGroups
|
||||
.filter(g => g.type === 'private' && !!g.is_direct)
|
||||
.sort((a, b) => {
|
||||
if (!a.last_message_at && !b.last_message_at) return 0;
|
||||
if (!a.last_message_at) return 1;
|
||||
@@ -123,8 +91,7 @@ export default function Sidebar({ groups, activeGroupId, onSelectGroup, notifica
|
||||
return new Date(b.last_message_at) - new Date(a.last_message_at);
|
||||
});
|
||||
const privateNonDM = allGroups.filter(g => g.type === 'private' && !g.is_direct);
|
||||
const privateFiltered = [...privateNonDM, ...pinnedDMs, ...unpinnedDMs];
|
||||
const pinnedGroupIds = new Set(pinnedDMs.map(g => g.id));
|
||||
const privateFiltered = [...privateNonDM, ...dms];
|
||||
|
||||
const getNotifCount = (groupId) => notifications.filter(n => n.groupId === groupId).length;
|
||||
|
||||
@@ -135,21 +102,12 @@ export default function Sidebar({ groups, activeGroupId, onSelectGroup, notifica
|
||||
const unreadCount = unreadGroups.get(group.id) || 0;
|
||||
const hasUnread = unreadCount > 0;
|
||||
const isActive = group.id === activeGroupId;
|
||||
const isPinned = pinnedGroupIds.has(group.id);
|
||||
const isOnline = group.is_direct && group.peer_id && onlineUserIds.has(group.peer_id);
|
||||
|
||||
const handleContextMenu = (e) => {
|
||||
if (!group.is_direct) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setContextMenu({ groupId: group.id, x: e.clientX, y: e.clientY, isPinned });
|
||||
};
|
||||
const isOnline = !!group.is_direct && !!group.peer_id && onlineUserIds.has(group.peer_id);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`group-item ${isActive ? 'active' : ''} ${hasUnread ? 'has-unread' : ''}`}
|
||||
onClick={() => onSelectGroup(group.id)}
|
||||
onContextMenu={handleContextMenu}
|
||||
>
|
||||
<div className="group-icon-wrap">
|
||||
{group.is_direct && group.peer_avatar ? (
|
||||
@@ -219,18 +177,7 @@ export default function Sidebar({ groups, activeGroupId, onSelectGroup, notifica
|
||||
{privateFiltered.length > 0 && (
|
||||
<div className="group-section">
|
||||
<div className="section-label">DIRECT MESSAGES</div>
|
||||
{pinnedDMs.length > 0 && (
|
||||
<>
|
||||
<div className="section-sublabel">
|
||||
<svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor" style={{ marginRight: 3 }}><path d="M16 2v4l-3 3v7l-4-4-4 4V9L2 6V2h14zm2 0h2v2h-2V2z"/></svg>
|
||||
PINNED
|
||||
</div>
|
||||
{pinnedDMs.map(g => <GroupItem key={g.id} group={g} />)}
|
||||
{unpinnedDMs.length > 0 && <div className="section-divider" />}
|
||||
</>
|
||||
)}
|
||||
{privateNonDM.map(g => <GroupItem key={g.id} group={g} />)}
|
||||
{unpinnedDMs.map(g => <GroupItem key={g.id} group={g} />)}
|
||||
{privateFiltered.map(g => <GroupItem key={g.id} group={g} />)}
|
||||
</div>
|
||||
)}
|
||||
{allGroups.length === 0 && (
|
||||
@@ -319,26 +266,6 @@ export default function Sidebar({ groups, activeGroupId, onSelectGroup, notifica
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{/* DM pin context menu */}
|
||||
{contextMenu && (
|
||||
<div
|
||||
className="dm-context-menu"
|
||||
style={{ top: contextMenu.y, left: Math.min(contextMenu.x, window.innerWidth - 160) }}
|
||||
onMouseDown={e => e.stopPropagation()}
|
||||
>
|
||||
{contextMenu.isPinned ? (
|
||||
<button onClick={() => handleUnpin(contextMenu.groupId)}>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M16 2v4l-3 3v7l-4-4-4 4V9L2 6V2h14zm2 0h2v2h-2V2z"/></svg>
|
||||
Unpin conversation
|
||||
</button>
|
||||
) : (
|
||||
<button onClick={() => handlePin(contextMenu.groupId)}>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M16 2v4l-3 3v7l-4-4-4 4V9L2 6V2h14zm2 0h2v2h-2V2z"/></svg>
|
||||
Pin conversation
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user