diff --git a/src/app/molecules/room-members/RoomMembers.jsx b/src/app/molecules/room-members/RoomMembers.jsx index ac004f46..f931f9dd 100644 --- a/src/app/molecules/room-members/RoomMembers.jsx +++ b/src/app/molecules/room-members/RoomMembers.jsx @@ -9,6 +9,7 @@ import colorMXID from '../../../util/colorMXID'; import { openProfileViewer } from '../../../client/action/navigation'; import { getUsernameOfRoomMember, getPowerLabel } from '../../../util/matrixUtil'; import AsyncSearch from '../../../util/AsyncSearch'; +import { memberByAtoZ, memberByPowerLevel } from '../../../util/sort'; import Text from '../../atoms/text/Text'; import Button from '../../atoms/button/Button'; @@ -19,26 +20,6 @@ import PeopleSelector from '../people-selector/PeopleSelector'; const PER_PAGE_MEMBER = 50; -function AtoZ(m1, m2) { - const aName = m1.name; - const bName = m2.name; - - if (aName.toLowerCase() < bName.toLowerCase()) { - return -1; - } - if (aName.toLowerCase() > bName.toLowerCase()) { - return 1; - } - return 0; -} -function sortByPowerLevel(m1, m2) { - const pl1 = m1.powerLevel; - const pl2 = m2.powerLevel; - - if (pl1 > pl2) return -1; - if (pl1 < pl2) return 1; - return 0; -} function normalizeMembers(members) { const mx = initMatrix.matrixClient; return members.map((member) => ({ @@ -65,7 +46,7 @@ function useMemberOfMembership(roomId, membership) { if (event && event?.getRoomId() !== roomId) return; const memberOfMembership = normalizeMembers( room.getMembersWithMembership(membership) - .sort(AtoZ).sort(sortByPowerLevel), + .sort(memberByAtoZ).sort(memberByPowerLevel), ); setMembers(memberOfMembership); }; diff --git a/src/app/organisms/navigation/Directs.jsx b/src/app/organisms/navigation/Directs.jsx index 61313479..c2a9798b 100644 --- a/src/app/organisms/navigation/Directs.jsx +++ b/src/app/organisms/navigation/Directs.jsx @@ -1,18 +1,38 @@ -import React, { useEffect } from 'react'; +import React, { useState, useEffect } from 'react'; import initMatrix from '../../../client/initMatrix'; import cons from '../../../client/state/cons'; import navigation from '../../../client/state/navigation'; import Postie from '../../../util/Postie'; +import { roomIdByActivity } from '../../../util/sort'; import RoomsCategory from './RoomsCategory'; -import { AtoZ } from './common'; - const drawerPostie = new Postie(); function Directs() { + const mx = initMatrix.matrixClient; const { roomList, notifications } = initMatrix; - const directIds = [...roomList.directs].sort(AtoZ); + const [directIds, setDirectIds] = useState([]); + + useEffect(() => setDirectIds([...roomList.directs].sort(roomIdByActivity)), []); + + useEffect(() => { + const handleTimeline = (event, room, toStartOfTimeline, removed, data) => { + if (!roomList.directs.has(room.roomId)) return; + if (!data.liveEvent) return; + if (directIds[0] === room.roomId) return; + const newDirectIds = [room.roomId]; + directIds.forEach((id) => { + if (id === room.roomId) return; + newDirectIds.push(id); + }); + setDirectIds(newDirectIds); + }; + mx.on('Room.timeline', handleTimeline); + return () => { + mx.removeListener('Room.timeline', handleTimeline); + }; + }, [directIds]); useEffect(() => { const selectorChanged = (selectedRoomId, prevSelectedRoomId) => { diff --git a/src/app/organisms/navigation/Home.jsx b/src/app/organisms/navigation/Home.jsx index 35e43a97..5e26a48b 100644 --- a/src/app/organisms/navigation/Home.jsx +++ b/src/app/organisms/navigation/Home.jsx @@ -5,11 +5,11 @@ import initMatrix from '../../../client/initMatrix'; import cons from '../../../client/state/cons'; import navigation from '../../../client/state/navigation'; import Postie from '../../../util/Postie'; +import { roomIdByActivity, roomIdByAtoZ } from '../../../util/sort'; import RoomsCategory from './RoomsCategory'; import { useCategorizedSpaces } from '../../hooks/useCategorizedSpaces'; -import { AtoZ, RoomToDM } from './common'; const drawerPostie = new Postie(); function Home({ spaceId }) { @@ -34,10 +34,6 @@ function Home({ spaceId }) { roomIds = roomList.getOrphanRooms(); } - spaceIds.sort(AtoZ); - roomIds.sort(AtoZ); - directIds.sort(AtoZ); - if (isCategorized) { categories = roomList.getCategorizedSpaces(spaceIds); categories.delete(spaceId); @@ -73,26 +69,36 @@ function Home({ spaceId }) { return ( <> { !isCategorized && spaceIds.length !== 0 && ( - + )} { roomIds.length !== 0 && ( - + )} { directIds.length !== 0 && ( - + )} - { isCategorized && [...categories].map(([catId, childIds]) => ( - - ))} + { isCategorized && [...categories].map(([catId, childIds]) => { + const rms = []; + const dms = []; + childIds.forEach((id) => { + if (directs.has(id)) dms.push(id); + else rms.push(id); + }); + rms.sort(roomIdByAtoZ); + dms.sort(roomIdByActivity); + return ( + + ); + })} ); } diff --git a/src/app/organisms/navigation/common.js b/src/app/organisms/navigation/common.js deleted file mode 100644 index 3c37e548..00000000 --- a/src/app/organisms/navigation/common.js +++ /dev/null @@ -1,30 +0,0 @@ -import initMatrix from '../../../client/initMatrix'; - -function AtoZ(aId, bId) { - let aName = initMatrix.matrixClient.getRoom(aId).name; - let bName = initMatrix.matrixClient.getRoom(bId).name; - - // remove "#" from the room name - // To ignore it in sorting - aName = aName.replaceAll('#', ''); - bName = bName.replaceAll('#', ''); - - if (aName.toLowerCase() < bName.toLowerCase()) { - return -1; - } - if (aName.toLowerCase() > bName.toLowerCase()) { - return 1; - } - return 0; -} - -const RoomToDM = (aId, bId) => { - const { directs } = initMatrix.roomList; - const aIsDm = directs.has(aId); - const bIsDm = directs.has(bId); - if (aIsDm && !bIsDm) return 1; - if (!aIsDm && bIsDm) return -1; - return 0; -}; - -export { AtoZ, RoomToDM }; diff --git a/src/app/organisms/room/PeopleDrawer.jsx b/src/app/organisms/room/PeopleDrawer.jsx index f00ff890..8f983247 100644 --- a/src/app/organisms/room/PeopleDrawer.jsx +++ b/src/app/organisms/room/PeopleDrawer.jsx @@ -9,6 +9,7 @@ import { getPowerLabel, getUsernameOfRoomMember } from '../../../util/matrixUtil import colorMXID from '../../../util/colorMXID'; import { openInviteUser, openProfileViewer } from '../../../client/action/navigation'; import AsyncSearch from '../../../util/AsyncSearch'; +import { memberByAtoZ, memberByPowerLevel } from '../../../util/sort'; import Text from '../../atoms/text/Text'; import Header, { TitleWrapper } from '../../atoms/header/Header'; @@ -24,26 +25,6 @@ import AddUserIC from '../../../../public/res/ic/outlined/add-user.svg'; import SearchIC from '../../../../public/res/ic/outlined/search.svg'; import CrossIC from '../../../../public/res/ic/outlined/cross.svg'; -function AtoZ(m1, m2) { - const aName = m1.name; - const bName = m2.name; - - if (aName.toLowerCase() < bName.toLowerCase()) { - return -1; - } - if (aName.toLowerCase() > bName.toLowerCase()) { - return 1; - } - return 0; -} -function sortByPowerLevel(m1, m2) { - const pl1 = m1.powerLevel; - const pl2 = m2.powerLevel; - - if (pl1 > pl2) return -1; - if (pl1 < pl2) return 1; - return 0; -} function simplyfiMembers(members) { const mx = initMatrix.matrixClient; return members.map((member) => ({ @@ -111,7 +92,7 @@ function PeopleDrawer({ roomId }) { setMemberList( simplyfiMembers( getMembersWithMembership(membership) - .sort(AtoZ).sort(sortByPowerLevel), + .sort(memberByAtoZ).sort(memberByPowerLevel), ), ); }; diff --git a/src/app/organisms/shortcut-spaces/ShortcutSpaces.jsx b/src/app/organisms/shortcut-spaces/ShortcutSpaces.jsx index c379b6b9..62ec76a3 100644 --- a/src/app/organisms/shortcut-spaces/ShortcutSpaces.jsx +++ b/src/app/organisms/shortcut-spaces/ShortcutSpaces.jsx @@ -6,6 +6,7 @@ import cons from '../../../client/state/cons'; import navigation from '../../../client/state/navigation'; import { createSpaceShortcut, deleteSpaceShortcut } from '../../../client/action/accountData'; import { joinRuleToIconSrc } from '../../../util/matrixUtil'; +import { roomIdByAtoZ } from '../../../util/sort'; import Text from '../../atoms/text/Text'; import Button from '../../atoms/button/Button'; @@ -20,7 +21,6 @@ import PinFilledIC from '../../../../public/res/ic/filled/pin.svg'; import CrossIC from '../../../../public/res/ic/outlined/cross.svg'; import { useSpaceShortcut } from '../../hooks/useSpaceShortcut'; -import { AtoZ } from '../navigation/common'; function ShortcutSpacesContent() { const mx = initMatrix.matrixClient; @@ -29,7 +29,7 @@ function ShortcutSpacesContent() { const [spaceShortcut] = useSpaceShortcut(); const spaceWithoutShortcut = [...spaces].filter( (spaceId) => !spaceShortcut.includes(spaceId), - ).sort(AtoZ); + ).sort(roomIdByAtoZ); const [process, setProcess] = useState(null); const [selected, setSelected] = useState([]); diff --git a/src/util/sort.js b/src/util/sort.js new file mode 100644 index 00000000..72ba3c43 --- /dev/null +++ b/src/util/sort.js @@ -0,0 +1,47 @@ +import initMatrix from '../client/initMatrix'; + +export function roomIdByActivity(id1, id2) { + const room1 = initMatrix.matrixClient.getRoom(id1); + const room2 = initMatrix.matrixClient.getRoom(id2); + + return room2.getLastActiveTimestamp() - room1.getLastActiveTimestamp(); +} + +export function roomIdByAtoZ(aId, bId) { + let aName = initMatrix.matrixClient.getRoom(aId).name; + let bName = initMatrix.matrixClient.getRoom(bId).name; + + // remove "#" from the room name + // To ignore it in sorting + aName = aName.replaceAll('#', ''); + bName = bName.replaceAll('#', ''); + + if (aName.toLowerCase() < bName.toLowerCase()) { + return -1; + } + if (aName.toLowerCase() > bName.toLowerCase()) { + return 1; + } + return 0; +} + +export function memberByAtoZ(m1, m2) { + const aName = m1.name; + const bName = m2.name; + + if (aName.toLowerCase() < bName.toLowerCase()) { + return -1; + } + if (aName.toLowerCase() > bName.toLowerCase()) { + return 1; + } + return 0; +} +export function memberByPowerLevel(m1, m2) { + const pl1 = m1.powerLevel; + const pl2 = m2.powerLevel; + + if (pl1 > pl2) return -1; + if (pl1 < pl2) return 1; + return 0; +}