diff --git a/src/app/molecules/room-aliases/RoomAliases.jsx b/src/app/molecules/room-aliases/RoomAliases.jsx index f8896eb..2093ab7 100644 --- a/src/app/molecules/room-aliases/RoomAliases.jsx +++ b/src/app/molecules/room-aliases/RoomAliases.jsx @@ -12,8 +12,8 @@ import Button from '../../atoms/button/Button'; import Input from '../../atoms/input/Input'; import Checkbox from '../../atoms/button/Checkbox'; import Toggle from '../../atoms/button/Toggle'; -import { MenuItem, MenuHeader } from '../../atoms/context-menu/ContextMenu'; -import SettingTile from '../../molecules/setting-tile/SettingTile'; +import { MenuHeader } from '../../atoms/context-menu/ContextMenu'; +import SettingTile from '../setting-tile/SettingTile'; import { useStore } from '../../hooks/useStore'; diff --git a/src/app/molecules/room-history-visibility/RoomHistoryVisibility.jsx b/src/app/molecules/room-history-visibility/RoomHistoryVisibility.jsx new file mode 100644 index 0000000..766f765 --- /dev/null +++ b/src/app/molecules/room-history-visibility/RoomHistoryVisibility.jsx @@ -0,0 +1,99 @@ +import React, { useState, useEffect, useCallback } from 'react'; +import PropTypes from 'prop-types'; +import './RoomHistoryVisibility.scss'; + +import initMatrix from '../../../client/initMatrix'; + +import Text from '../../atoms/text/Text'; +import RadioButton from '../../atoms/button/RadioButton'; +import { MenuItem } from '../../atoms/context-menu/ContextMenu'; + +const visibility = { + WORLD_READABLE: 'world_readable', + SHARED: 'shared', + INVITED: 'invited', + JOINED: 'joined', +}; + +const items = [{ + iconSrc: null, + text: 'World readable (anyone can read)', + type: visibility.WORLD_READABLE, +}, { + iconSrc: null, + text: 'Member shared (since the point in time of selecting this option)', + type: visibility.SHARED, +}, { + iconSrc: null, + text: 'Member invited (since they were invited)', + type: visibility.INVITED, +}, { + iconSrc: null, + text: 'Member joined (since they joined)', + type: visibility.JOINED, +}]; + +function setHistoryVisibility(roomId, type) { + const mx = initMatrix.matrixClient; + + return mx.sendStateEvent( + roomId, 'm.room.history_visibility', + { + history_visibility: type, + }, + ); +} + +function useVisibility(roomId) { + const mx = initMatrix.matrixClient; + const room = mx.getRoom(roomId); + + const [activeType, setActiveType] = useState(room.getHistoryVisibility()); + useEffect(() => setActiveType(room.getHistoryVisibility()), [roomId]); + + const setVisibility = useCallback((item) => { + if (item.type === activeType.type) return; + setActiveType(item.type); + setHistoryVisibility(roomId, item.type); + }, [activeType, roomId]); + + return [activeType, setVisibility]; +} + +function RoomHistoryVisibility({ roomId }) { + const [activeType, setVisibility] = useVisibility(roomId); + const mx = initMatrix.matrixClient; + const userId = mx.getUserId(); + const room = mx.getRoom(roomId); + const { currentState } = room; + + const canChange = currentState.maySendStateEvent('m.room.history_visibility', userId); + + return ( +
+ { + items.map((item) => ( + setVisibility(item)} + disabled={(!canChange)} + > + + {item.text} + + + + )) + } + Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged. +
+ ); +} + +RoomHistoryVisibility.propTypes = { + roomId: PropTypes.string.isRequired, +}; + +export default RoomHistoryVisibility; diff --git a/src/app/molecules/room-history-visibility/RoomHistoryVisibility.scss b/src/app/molecules/room-history-visibility/RoomHistoryVisibility.scss new file mode 100644 index 0000000..b9e0a2c --- /dev/null +++ b/src/app/molecules/room-history-visibility/RoomHistoryVisibility.scss @@ -0,0 +1,25 @@ +@use '../../partials/flex'; +@use '../../partials/dir'; +@use '../../partials/text'; + +.room-history-visibility { + & .context-menu__item .text { + margin: 0 !important; + @extend .cp-fx__item-one; + @extend .cp-fx__row--s-c; + + & span:first-child { + @extend .cp-fx__item-one; + @extend .cp-txt__ellipsis; + } + + & .radio-btn { + @include dir.side(margin, var(--sp-tight), 0); + } + } + + & > .text { + margin: var(--sp-normal); + margin-top: var(--sp-ultra-tight); + } +} \ No newline at end of file diff --git a/src/app/organisms/room/RoomSettings.jsx b/src/app/organisms/room/RoomSettings.jsx index 8c7323b..91fd11e 100644 --- a/src/app/organisms/room/RoomSettings.jsx +++ b/src/app/organisms/room/RoomSettings.jsx @@ -17,6 +17,7 @@ import RoomProfile from '../../molecules/room-profile/RoomProfile'; import RoomNotification from '../../molecules/room-notification/RoomNotification'; import RoomVisibility from '../../molecules/room-visibility/RoomVisibility'; import RoomAliases from '../../molecules/room-aliases/RoomAliases'; +import RoomHistoryVisibility from '../../molecules/room-history-visibility/RoomHistoryVisibility'; import SettingsIC from '../../../../public/res/ic/outlined/settings.svg'; import SearchIC from '../../../../public/res/ic/outlined/search.svg'; @@ -28,25 +29,33 @@ import LeaveArrowIC from '../../../../public/res/ic/outlined/leave-arrow.svg'; import { useForceUpdate } from '../../hooks/useForceUpdate'; +const tabText = { + GENERAL: 'General', + SEARCH: 'Search', + PERMISSIONS: 'Permissions', + SECURITY: 'Security', + ADVANCED: 'Advanced', +}; + const tabItems = [{ iconSrc: SettingsIC, - text: 'General', + text: tabText.GENERAL, disabled: false, }, { iconSrc: SearchIC, - text: 'Search', + text: tabText.SEARCH, disabled: false, }, { iconSrc: ShieldUserIC, - text: 'Permissions', + text: tabText.PERMISSIONS, disabled: false, }, { iconSrc: LockIC, - text: 'Security', + text: tabText.SECURITY, disabled: false, }, { iconSrc: InfoIC, - text: 'Advanced', + text: tabText.ADVANCED, disabled: false, }]; @@ -87,6 +96,20 @@ GeneralSettings.propTypes = { roomId: PropTypes.string.isRequired, }; +function SecuritySettings({ roomId }) { + return ( + <> +
+ Message history visibility (Who can read history) + +
+ + ); +} +SecuritySettings.propTypes = { + roomId: PropTypes.string.isRequired, +}; + function RoomSettings({ roomId }) { const [, forceUpdate] = useForceUpdate(); const [selectedTab, setSelectedTab] = useState(tabItems[0]); @@ -127,7 +150,8 @@ function RoomSettings({ roomId }) { onSelect={handleTabChange} />
- {selectedTab.text === tabItems[0].text && } + {selectedTab.text === tabText.GENERAL && } + {selectedTab.text === tabText.SECURITY && }