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) => (
+
+ ))
+ }
+ 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 && }