import cons from '../../client/state/cons';
export function useSpaceShortcut() {
- const { roomList } = initMatrix;
- const [spaceShortcut, setSpaceShortcut] = useState([...roomList.spaceShortcut]);
+ const { accountData } = initMatrix;
+ const [spaceShortcut, setSpaceShortcut] = useState([...accountData.spaceShortcut]);
useEffect(() => {
const onSpaceShortcutUpdated = () => {
- setSpaceShortcut([...roomList.spaceShortcut]);
+ setSpaceShortcut([...accountData.spaceShortcut]);
};
- roomList.on(cons.events.roomList.SPACE_SHORTCUT_UPDATED, onSpaceShortcutUpdated);
+ accountData.on(cons.events.accountData.SPACE_SHORTCUT_UPDATED, onSpaceShortcutUpdated);
return () => {
- roomList.removeListener(cons.events.roomList.SPACE_SHORTCUT_UPDATED, onSpaceShortcutUpdated);
+ accountData.removeListener(
+ cons.events.accountData.SPACE_SHORTCUT_UPDATED,
+ onSpaceShortcutUpdated,
+ );
};
}, []);
import initMatrix from '../../../client/initMatrix';
import { openSpaceSettings, openSpaceManage, openInviteUser } from '../../../client/action/navigation';
-import { leave, createSpaceShortcut, deleteSpaceShortcut } from '../../../client/action/room';
+import { leave } from '../../../client/action/room';
+import { createSpaceShortcut, deleteSpaceShortcut } from '../../../client/action/accountData';
import { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu';
+import CategoryIC from '../../../../public/res/ic/outlined/category.svg';
+import CategoryFilledIC from '../../../../public/res/ic/filled/category.svg';
import AddUserIC from '../../../../public/res/ic/outlined/add-user.svg';
import SettingsIC from '../../../../public/res/ic/outlined/settings.svg';
import HashSearchIC from '../../../../public/res/ic/outlined/hash-search.svg';
const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId);
const canInvite = room?.canInvite(mx.getUserId());
- const isPinned = initMatrix.roomList.spaceShortcut.has(roomId);
+ const isPinned = initMatrix.accountData.spaceShortcut.has(roomId);
const handleInviteClick = () => {
openInviteUser(roomId);
else createSpaceShortcut(roomId);
afterOptionSelect();
};
-
+ const handleCategorizeClick = () => {
+ alert('categorize');
+ afterOptionSelect();
+ };
const handleSettingsClick = () => {
openSpaceSettings(roomId);
afterOptionSelect();
return (
<div style={{ maxWidth: 'calc(var(--navigation-drawer-width) - var(--sp-normal))' }}>
<MenuHeader>{twemojify(`Options for ${initMatrix.matrixClient.getRoom(roomId)?.name}`)}</MenuHeader>
+ <MenuItem
+ onClick={handleCategorizeClick}
+ iconSrc={CategoryIC}
+ >
+ Categorize subspaces
+ </MenuItem>
<MenuItem
onClick={handlePinClick}
iconSrc={isPinned ? PinFilledIC : PinIC}
}
function SideBar() {
- const { roomList, notifications } = initMatrix;
+ const { roomList, accountData, notifications } = initMatrix;
const mx = initMatrix.matrixClient;
const [selectedTab] = useSelectedTab();
let noti = null;
orphans.forEach((roomId) => {
- if (roomList.spaceShortcut.has(roomId)) return;
+ if (accountData.spaceShortcut.has(roomId)) return;
if (!notifications.hasNoti(roomId)) return;
if (noti === null) noti = { total: 0, highlight: 0 };
const childNoti = notifications.getNoti(roomId);
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
-import { leave, createSpaceShortcut, deleteSpaceShortcut } from '../../../client/action/room';
+import { leave } from '../../../client/action/room';
+import { createSpaceShortcut, deleteSpaceShortcut } from '../../../client/action/accountData';
import Text from '../../atoms/text/Text';
import IconButton from '../../atoms/button/IconButton';
}];
function GeneralSettings({ roomId }) {
- const isPinned = initMatrix.roomList.spaceShortcut.has(roomId);
+ const isPinned = initMatrix.accountData.spaceShortcut.has(roomId);
const [, forceUpdate] = useForceUpdate();
return (
--- /dev/null
+import appDispatcher from '../dispatcher';
+import cons from '../state/cons';
+
+export function createSpaceShortcut(roomId) {
+ appDispatcher.dispatch({
+ type: cons.actions.accountData.CREATE_SPACE_SHORTCUT,
+ roomId,
+ });
+}
+
+export function deleteSpaceShortcut(roomId) {
+ appDispatcher.dispatch({
+ type: cons.actions.accountData.DELETE_SPACE_SHORTCUT,
+ roomId,
+ });
+}
return result;
}
-function createSpaceShortcut(roomId) {
- appDispatcher.dispatch({
- type: cons.actions.room.CREATE_SPACE_SHORTCUT,
- roomId,
- });
-}
-
-function deleteSpaceShortcut(roomId) {
- appDispatcher.dispatch({
- type: cons.actions.room.DELETE_SPACE_SHORTCUT,
- roomId,
- });
-}
-
export {
join, leave,
createDM, createRoom,
invite, kick, ban, unban,
setPowerLevel,
- createSpaceShortcut, deleteSpaceShortcut,
};
import { secret } from './state/auth';
import RoomList from './state/RoomList';
+import AccountData from './state/AccountData';
import RoomsInput from './state/RoomsInput';
import Notifications from './state/Notifications';
import { initHotkeys } from './event/hotkeys';
global.initMatrix = this;
if (prevState === null) {
this.roomList = new RoomList(this.matrixClient);
+ this.accountData = new AccountData(this.roomList);
this.roomsInput = new RoomsInput(this.matrixClient);
this.notifications = new Notifications(this.roomList);
initHotkeys();
--- /dev/null
+import EventEmitter from 'events';
+import appDispatcher from '../dispatcher';
+import cons from './cons';
+
+class AccountData extends EventEmitter {
+ constructor(roomList) {
+ super();
+
+ this.matrixClient = roomList.matrixClient;
+ this.roomList = roomList;
+ this.spaces = roomList.spaces;
+
+ this.spaceShortcut = new Set();
+ this._populateSpaceShortcut();
+ this._listenEvents();
+
+ appDispatcher.register(this.roomActions.bind(this));
+ }
+
+ _populateSpaceShortcut() {
+ this.spaceShortcut.clear();
+ const spacesContent = this.matrixClient.getAccountData(cons.IN_CINNY_SPACES)?.getContent();
+
+ if (!spacesContent) return;
+ if (spacesContent?.shortcut === undefined) return;
+
+ spacesContent.shortcut.forEach((shortcut) => {
+ if (this.spaces.has(shortcut)) this.spaceShortcut.add(shortcut);
+ });
+ if (spacesContent.shortcut.length !== this.spaceShortcut.size) {
+ // update shortcut list from account data if shortcut space doesn't exist.
+ // TODO: we can wait for sync to complete or else we may end up removing valid space id
+ this._updateSpaceShortcutData([...this.spaceShortcut]);
+ }
+ }
+
+ _updateSpaceShortcutData(shortcutList) {
+ const spaceContent = this.matrixClient.getAccountData(cons.IN_CINNY_SPACES)?.getContent() || {};
+ spaceContent.shortcut = shortcutList;
+ this.matrixClient.setAccountData(cons.IN_CINNY_SPACES, spaceContent);
+ }
+
+ roomActions(action) {
+ const actions = {
+ [cons.actions.accountData.CREATE_SPACE_SHORTCUT]: () => {
+ if (this.spaceShortcut.has(action.roomId)) return;
+ this.spaceShortcut.add(action.roomId);
+ this._updateSpaceShortcutData([...this.spaceShortcut]);
+ this.emit(cons.events.accountData.SPACE_SHORTCUT_UPDATED, action.roomId);
+ },
+ [cons.actions.accountData.DELETE_SPACE_SHORTCUT]: () => {
+ if (!this.spaceShortcut.has(action.roomId)) return;
+ this.spaceShortcut.delete(action.roomId);
+ this._updateSpaceShortcutData([...this.spaceShortcut]);
+ this.emit(cons.events.accountData.SPACE_SHORTCUT_UPDATED, action.roomId);
+ },
+ };
+ actions[action.type]?.();
+ }
+
+ _listenEvents() {
+ this.matrixClient.on('accountData', (event) => {
+ if (event.getType() !== cons.IN_CINNY_SPACES) return;
+ this._populateSpaceShortcut();
+ this.emit(cons.events.accountData.SPACE_SHORTCUT_UPDATED);
+ });
+
+ this.roomList.on(cons.events.roomList.ROOM_LEAVED, (roomId) => {
+ if (this.spaceShortcut.has(roomId)) {
+ // if deleted space has shortcut remove it.
+ this.spaceShortcut.delete(roomId);
+ this._updateSpaceShortcutData([...this.spaceShortcut]);
+ this.emit(cons.events.accountData.SPACE_SHORTCUT_UPDATED, roomId);
+ }
+ });
+ }
+}
+
+export default AccountData;
// No matter if you have joined those children rooms or not.
this.roomIdToParents = new Map();
- this.spaceShortcut = new Set();
-
this.inviteDirects = new Set();
this.inviteSpaces = new Set();
this.inviteRooms = new Set();
this.processingRooms = new Map();
this._populateRooms();
- this._populateSpaceShortcut();
this._listenEvents();
appDispatcher.register(this.roomActions.bind(this));
}
- _updateSpaceShortcutData(shortcutList) {
- const spaceContent = this.matrixClient.getAccountData(cons['in.cinny.spaces'])?.getContent() || {};
- spaceContent.shortcut = shortcutList;
- this.matrixClient.setAccountData(cons['in.cinny.spaces'], spaceContent);
- }
-
isOrphan(roomId) {
return !this.roomIdToParents.has(roomId);
}
spaceChildren?.forEach((childRoomId) => {
this.removeFromRoomIdToParents(childRoomId, roomId);
});
-
- if (this.spaceShortcut.has(roomId)) {
- // if delete space has shortcut remove it.
- this.spaceShortcut.delete(roomId);
- this._updateSpaceShortcutData([...this.spaceShortcut]);
- }
}
roomActions(action) {
});
}
},
- [cons.actions.room.CREATE_SPACE_SHORTCUT]: () => {
- if (this.spaceShortcut.has(action.roomId)) return;
- this.spaceShortcut.add(action.roomId);
- this._updateSpaceShortcutData([...this.spaceShortcut]);
- this.emit(cons.events.roomList.SPACE_SHORTCUT_UPDATED, action.roomId);
- },
- [cons.actions.room.DELETE_SPACE_SHORTCUT]: () => {
- if (!this.spaceShortcut.has(action.roomId)) return;
- this.spaceShortcut.delete(action.roomId);
- this._updateSpaceShortcutData([...this.spaceShortcut]);
- this.emit(cons.events.roomList.SPACE_SHORTCUT_UPDATED, action.roomId);
- },
};
actions[action.type]?.();
}
return mDirectsId;
}
- _populateSpaceShortcut() {
- this.spaceShortcut.clear();
- const spacesContent = this.matrixClient.getAccountData(cons['in.cinny.spaces'])?.getContent();
-
- if (spacesContent && Array.isArray(spacesContent?.shortcut)) {
- spacesContent.shortcut.forEach((shortcut) => {
- if (this.spaces.has(shortcut)) this.spaceShortcut.add(shortcut);
- });
- if (spacesContent.shortcut.length !== this.spaceShortcut.size) {
- // update shortcut list from account data if shortcut space doesn't exist.
- this._updateSpaceShortcutData([...this.spaceShortcut]);
- }
- }
- }
-
_populateRooms() {
this.directs.clear();
this.roomIdToParents.clear();
_listenEvents() {
// Update roomList when m.direct changes
this.matrixClient.on('accountData', (event) => {
- if (event.getType() === cons['in.cinny.spaces']) {
- this._populateSpaceShortcut();
- this.emit(cons.events.roomList.SPACE_SHORTCUT_UPDATED);
- return;
- }
-
if (event.getType() !== 'm.direct') return;
const latestMDirects = this.getMDirects();
BASE_URL: 'cinny_hs_base_url',
},
DEVICE_DISPLAY_NAME: 'Cinny Web',
- 'in.cinny.spaces': 'in.cinny.spaces',
+ IN_CINNY_SPACES: 'in.cinny.spaces',
tabs: {
HOME: 'home',
DIRECTS: 'dm',
JOIN: 'JOIN',
LEAVE: 'LEAVE',
CREATE: 'CREATE',
+ },
+ accountData: {
CREATE_SPACE_SHORTCUT: 'CREATE_SPACE_SHORTCUT',
DELETE_SPACE_SHORTCUT: 'DELETE_SPACE_SHORTCUT',
},
ROOM_JOINED: 'ROOM_JOINED',
ROOM_LEAVED: 'ROOM_LEAVED',
ROOM_CREATED: 'ROOM_CREATED',
- SPACE_SHORTCUT_UPDATED: 'SPACE_SHORTCUT_UPDATED',
ROOM_PROFILE_UPDATED: 'ROOM_PROFILE_UPDATED',
},
+ accountData: {
+ SPACE_SHORTCUT_UPDATED: 'SPACE_SHORTCUT_UPDATED',
+ },
notifications: {
NOTI_CHANGED: 'NOTI_CHANGED',
FULL_READ: 'FULL_READ',