From 12ae94cd60fc3f6ea6818a0daf01f46cc9b6dd7f Mon Sep 17 00:00:00 2001 From: Ajay Bura <32841439+ajbura@users.noreply.github.com> Date: Fri, 28 Mar 2025 20:16:01 +1100 Subject: [PATCH] Remove old settings components (#2296) --- src/app/molecules/image-pack/ImagePack.jsx | 511 ------------------ src/app/molecules/image-pack/ImagePack.scss | 47 -- .../molecules/image-pack/ImagePackItem.jsx | 76 --- .../molecules/image-pack/ImagePackItem.scss | 43 -- .../molecules/image-pack/ImagePackProfile.jsx | 125 ----- .../image-pack/ImagePackProfile.scss | 37 -- .../molecules/image-pack/ImagePackUpload.jsx | 73 --- .../molecules/image-pack/ImagePackUpload.scss | 43 -- .../image-pack/ImagePackUsageSelector.jsx | 41 -- .../molecules/room-aliases/RoomAliases.jsx | 359 ------------ .../molecules/room-aliases/RoomAliases.scss | 84 --- src/app/molecules/room-emojis/RoomEmojis.jsx | 131 ----- src/app/molecules/room-emojis/RoomEmojis.scss | 29 - .../room-encryption/RoomEncryption.jsx | 61 --- .../room-encryption/RoomEncryption.scss | 5 - .../RoomHistoryVisibility.jsx | 96 ---- .../RoomHistoryVisibility.scss | 25 - src/app/molecules/room-intro/RoomIntro.jsx | 42 -- src/app/molecules/room-intro/RoomIntro.scss | 26 - .../molecules/room-members/RoomMembers.jsx | 185 ------- .../molecules/room-members/RoomMembers.scss | 39 -- .../room-notification/RoomNotification.jsx | 153 ------ .../room-notification/RoomNotification.scss | 19 - .../room-permissions/RoomPermissions.jsx | 284 ---------- .../room-permissions/RoomPermissions.scss | 11 - .../molecules/room-profile/RoomProfile.jsx | 237 -------- .../molecules/room-profile/RoomProfile.scss | 53 -- .../room-visibility/RoomVisibility.jsx | 122 ----- .../room-visibility/RoomVisibility.scss | 19 - src/app/organisms/pw/Windows.jsx | 18 +- src/app/organisms/room/RoomSettings.jsx | 200 ------- src/app/organisms/room/RoomSettings.scss | 40 -- .../space-settings/SpaceSettings.jsx | 166 ------ .../space-settings/SpaceSettings.scss | 37 -- src/client/action/navigation.js | 15 - src/client/state/cons.js | 20 - src/client/state/navigation.js | 10 - 37 files changed, 6 insertions(+), 3476 deletions(-) delete mode 100644 src/app/molecules/image-pack/ImagePack.jsx delete mode 100644 src/app/molecules/image-pack/ImagePack.scss delete mode 100644 src/app/molecules/image-pack/ImagePackItem.jsx delete mode 100644 src/app/molecules/image-pack/ImagePackItem.scss delete mode 100644 src/app/molecules/image-pack/ImagePackProfile.jsx delete mode 100644 src/app/molecules/image-pack/ImagePackProfile.scss delete mode 100644 src/app/molecules/image-pack/ImagePackUpload.jsx delete mode 100644 src/app/molecules/image-pack/ImagePackUpload.scss delete mode 100644 src/app/molecules/image-pack/ImagePackUsageSelector.jsx delete mode 100644 src/app/molecules/room-aliases/RoomAliases.jsx delete mode 100644 src/app/molecules/room-aliases/RoomAliases.scss delete mode 100644 src/app/molecules/room-emojis/RoomEmojis.jsx delete mode 100644 src/app/molecules/room-emojis/RoomEmojis.scss delete mode 100644 src/app/molecules/room-encryption/RoomEncryption.jsx delete mode 100644 src/app/molecules/room-encryption/RoomEncryption.scss delete mode 100644 src/app/molecules/room-history-visibility/RoomHistoryVisibility.jsx delete mode 100644 src/app/molecules/room-history-visibility/RoomHistoryVisibility.scss delete mode 100644 src/app/molecules/room-intro/RoomIntro.jsx delete mode 100644 src/app/molecules/room-intro/RoomIntro.scss delete mode 100644 src/app/molecules/room-members/RoomMembers.jsx delete mode 100644 src/app/molecules/room-members/RoomMembers.scss delete mode 100644 src/app/molecules/room-notification/RoomNotification.jsx delete mode 100644 src/app/molecules/room-notification/RoomNotification.scss delete mode 100644 src/app/molecules/room-permissions/RoomPermissions.jsx delete mode 100644 src/app/molecules/room-permissions/RoomPermissions.scss delete mode 100644 src/app/molecules/room-profile/RoomProfile.jsx delete mode 100644 src/app/molecules/room-profile/RoomProfile.scss delete mode 100644 src/app/molecules/room-visibility/RoomVisibility.jsx delete mode 100644 src/app/molecules/room-visibility/RoomVisibility.scss delete mode 100644 src/app/organisms/room/RoomSettings.jsx delete mode 100644 src/app/organisms/room/RoomSettings.scss delete mode 100644 src/app/organisms/space-settings/SpaceSettings.jsx delete mode 100644 src/app/organisms/space-settings/SpaceSettings.scss diff --git a/src/app/molecules/image-pack/ImagePack.jsx b/src/app/molecules/image-pack/ImagePack.jsx deleted file mode 100644 index 93d1d90..0000000 --- a/src/app/molecules/image-pack/ImagePack.jsx +++ /dev/null @@ -1,511 +0,0 @@ -import React, { useState, useMemo, useReducer, useEffect } from 'react'; -import PropTypes from 'prop-types'; -import { EventTimeline } from 'matrix-js-sdk'; -import './ImagePack.scss'; - -import { openReusableDialog } from '../../../client/action/navigation'; -import { suffixRename } from '../../../util/common'; - -import Button from '../../atoms/button/Button'; -import Text from '../../atoms/text/Text'; -import Input from '../../atoms/input/Input'; -import Checkbox from '../../atoms/button/Checkbox'; -import { MenuHeader } from '../../atoms/context-menu/ContextMenu'; - -import { ImagePack as ImagePackBuilder } from '../../organisms/emoji-board/custom-emoji'; -import { confirmDialog } from '../confirm-dialog/ConfirmDialog'; -import ImagePackProfile from './ImagePackProfile'; -import ImagePackItem from './ImagePackItem'; -import ImagePackUpload from './ImagePackUpload'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; -import { useMediaAuthentication } from '../../hooks/useMediaAuthentication'; -import { getStateEvent } from '../../utils/room'; - -const renameImagePackItem = (shortcode) => - new Promise((resolve) => { - let isCompleted = false; - - openReusableDialog( - - Rename - , - (requestClose) => ( -
-
{ - e.preventDefault(); - const sc = e.target.shortcode.value; - if (sc.trim() === '') return; - isCompleted = true; - resolve(sc.trim()); - requestClose(); - }} - > - -
- - -
- ), - () => { - if (!isCompleted) resolve(null); - } - ); - }); - -function getUsage(usage) { - if (usage.includes('emoticon') && usage.includes('sticker')) return 'both'; - if (usage.includes('emoticon')) return 'emoticon'; - if (usage.includes('sticker')) return 'sticker'; - - return 'both'; -} - -function isGlobalPack(mx, roomId, stateKey) { - const globalContent = mx.getAccountData('im.ponies.emote_rooms')?.getContent(); - if (typeof globalContent !== 'object') return false; - - const { rooms } = globalContent; - if (typeof rooms !== 'object') return false; - - return rooms[roomId]?.[stateKey] !== undefined; -} - -function useRoomImagePack(roomId, stateKey) { - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - - const pack = useMemo(() => { - const packEvent = getStateEvent(room, 'im.ponies.room_emotes', stateKey); - return ImagePackBuilder.parsePack(packEvent.getId(), packEvent.getContent()); - }, [room, stateKey]); - - const sendPackContent = (content) => { - mx.sendStateEvent(roomId, 'im.ponies.room_emotes', content, stateKey); - }; - - return { - pack, - sendPackContent, - }; -} - -function useUserImagePack() { - const mx = useMatrixClient(); - const pack = useMemo(() => { - const packEvent = mx.getAccountData('im.ponies.user_emotes'); - return ImagePackBuilder.parsePack( - mx.getUserId(), - packEvent?.getContent() ?? { - pack: { display_name: 'Personal' }, - images: {}, - } - ); - }, [mx]); - - const sendPackContent = (content) => { - mx.setAccountData('im.ponies.user_emotes', content); - }; - - return { - pack, - sendPackContent, - }; -} - -function useImagePackHandles(pack, sendPackContent) { - const [, forceUpdate] = useReducer((count) => count + 1, 0); - - const getNewKey = (key) => { - if (typeof key !== 'string') return undefined; - let newKey = key?.replace(/\s/g, '_'); - if (pack.getImages().get(newKey)) { - newKey = suffixRename(newKey, (suffixedKey) => pack.getImages().get(suffixedKey)); - } - return newKey; - }; - - const handleAvatarChange = (url) => { - pack.setAvatarUrl(url); - sendPackContent(pack.getContent()); - forceUpdate(); - }; - const handleEditProfile = (name, attribution) => { - pack.setDisplayName(name); - pack.setAttribution(attribution); - sendPackContent(pack.getContent()); - forceUpdate(); - }; - const handleUsageChange = (newUsage) => { - const usage = []; - if (newUsage === 'emoticon' || newUsage === 'both') usage.push('emoticon'); - if (newUsage === 'sticker' || newUsage === 'both') usage.push('sticker'); - pack.setUsage(usage); - pack.getImages().forEach((img) => pack.setImageUsage(img.shortcode, undefined)); - - sendPackContent(pack.getContent()); - forceUpdate(); - }; - - const handleRenameItem = async (key) => { - const newKey = getNewKey(await renameImagePackItem(key)); - - if (!newKey || newKey === key) return; - pack.updateImageKey(key, newKey); - - sendPackContent(pack.getContent()); - forceUpdate(); - }; - const handleDeleteItem = async (key) => { - const isConfirmed = await confirmDialog( - 'Delete', - `Are you sure that you want to delete "${key}"?`, - 'Delete', - 'danger' - ); - if (!isConfirmed) return; - pack.removeImage(key); - - sendPackContent(pack.getContent()); - forceUpdate(); - }; - const handleUsageItem = (key, newUsage) => { - const usage = []; - if (newUsage === 'emoticon' || newUsage === 'both') usage.push('emoticon'); - if (newUsage === 'sticker' || newUsage === 'both') usage.push('sticker'); - pack.setImageUsage(key, usage); - - sendPackContent(pack.getContent()); - forceUpdate(); - }; - const handleAddItem = (key, url) => { - const newKey = getNewKey(key); - if (!newKey || !url) return; - - pack.addImage(newKey, { - url, - }); - - sendPackContent(pack.getContent()); - forceUpdate(); - }; - - return { - handleAvatarChange, - handleEditProfile, - handleUsageChange, - handleRenameItem, - handleDeleteItem, - handleUsageItem, - handleAddItem, - }; -} - -function addGlobalImagePack(mx, roomId, stateKey) { - const content = mx.getAccountData('im.ponies.emote_rooms')?.getContent() ?? {}; - if (!content.rooms) content.rooms = {}; - if (!content.rooms[roomId]) content.rooms[roomId] = {}; - content.rooms[roomId][stateKey] = {}; - return mx.setAccountData('im.ponies.emote_rooms', content); -} -function removeGlobalImagePack(mx, roomId, stateKey) { - const content = mx.getAccountData('im.ponies.emote_rooms')?.getContent() ?? {}; - if (!content.rooms) return Promise.resolve(); - if (!content.rooms[roomId]) return Promise.resolve(); - delete content.rooms[roomId][stateKey]; - if (Object.keys(content.rooms[roomId]).length === 0) { - delete content.rooms[roomId]; - } - return mx.setAccountData('im.ponies.emote_rooms', content); -} - -function ImagePack({ roomId, stateKey, handlePackDelete }) { - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - const [viewMore, setViewMore] = useState(false); - const [isGlobal, setIsGlobal] = useState(isGlobalPack(mx, roomId, stateKey)); - const useAuthentication = useMediaAuthentication(); - - const { pack, sendPackContent } = useRoomImagePack(roomId, stateKey); - - const { - handleAvatarChange, - handleEditProfile, - handleUsageChange, - handleRenameItem, - handleDeleteItem, - handleUsageItem, - handleAddItem, - } = useImagePackHandles(pack, sendPackContent); - - const handleGlobalChange = (isG) => { - setIsGlobal(isG); - if (isG) addGlobalImagePack(mx, roomId, stateKey); - else removeGlobalImagePack(mx, roomId, stateKey); - }; - - const myPowerlevel = room.getMember(mx.getUserId())?.powerLevel || 0; - const canChange = room - .getLiveTimeline() - .getState(EventTimeline.FORWARDS) - ?.hasSufficientPowerLevelFor('state_default', myPowerlevel); - - const handleDeletePack = async () => { - const isConfirmed = await confirmDialog( - 'Delete Pack', - `Are you sure that you want to delete "${pack.displayName}"?`, - 'Delete', - 'danger' - ); - if (!isConfirmed) return; - handlePackDelete(stateKey); - }; - - const images = [...pack.images].slice(0, viewMore ? pack.images.size : 2); - - return ( -
- - {canChange && } - {images.length === 0 ? null : ( -
-
- Image - Shortcode - Usage -
- {images.map(([shortcode, image]) => ( - - ))} -
- )} - {(pack.images.size > 2 || handlePackDelete) && ( -
- {pack.images.size > 2 && ( - - )} - {handlePackDelete && ( - - )} -
- )} -
- -
- Use globally - Add this pack to your account to use in all rooms. -
-
-
- ); -} - -ImagePack.defaultProps = { - handlePackDelete: null, -}; -ImagePack.propTypes = { - roomId: PropTypes.string.isRequired, - stateKey: PropTypes.string.isRequired, - handlePackDelete: PropTypes.func, -}; - -function ImagePackUser() { - const mx = useMatrixClient(); - const [viewMore, setViewMore] = useState(false); - const useAuthentication = useMediaAuthentication(); - - const { pack, sendPackContent } = useUserImagePack(); - - const { - handleAvatarChange, - handleEditProfile, - handleUsageChange, - handleRenameItem, - handleDeleteItem, - handleUsageItem, - handleAddItem, - } = useImagePackHandles(pack, sendPackContent); - - const images = [...pack.images].slice(0, viewMore ? pack.images.size : 2); - - return ( -
- - - {images.length === 0 ? null : ( -
-
- Image - Shortcode - Usage -
- {images.map(([shortcode, image]) => ( - - ))} -
- )} - {pack.images.size > 2 && ( -
- -
- )} -
- ); -} - -function useGlobalImagePack() { - const [, forceUpdate] = useReducer((count) => count + 1, 0); - const mx = useMatrixClient(); - - const roomIdToStateKeys = new Map(); - const globalContent = mx.getAccountData('im.ponies.emote_rooms')?.getContent() ?? { rooms: {} }; - const { rooms } = globalContent; - - Object.keys(rooms).forEach((roomId) => { - if (typeof rooms[roomId] !== 'object') return; - const room = mx.getRoom(roomId); - const stateKeys = Object.keys(rooms[roomId]); - if (!room || stateKeys.length === 0) return; - roomIdToStateKeys.set(roomId, stateKeys); - }); - - useEffect(() => { - const handleEvent = (event) => { - if (event.getType() === 'im.ponies.emote_rooms') forceUpdate(); - }; - mx.addListener('accountData', handleEvent); - return () => { - mx.removeListener('accountData', handleEvent); - }; - }, [mx]); - - return roomIdToStateKeys; -} - -function ImagePackGlobal() { - const mx = useMatrixClient(); - const roomIdToStateKeys = useGlobalImagePack(); - - const handleChange = (roomId, stateKey) => { - removeGlobalImagePack(mx, roomId, stateKey); - }; - - return ( -
- Global packs -
- {roomIdToStateKeys.size > 0 ? ( - [...roomIdToStateKeys].map(([roomId, stateKeys]) => { - const room = mx.getRoom(roomId); - return stateKeys.map((stateKey) => { - const data = getStateEvent(room, 'im.ponies.room_emotes', stateKey); - const pack = ImagePackBuilder.parsePack(data?.getId(), data?.getContent()); - if (!pack) return null; - return ( -
- handleChange(roomId, stateKey)} - isActive - /> -
- {pack.displayName ?? 'Unknown'} - {room.name} -
-
- ); - }); - }) - ) : ( -
- No global packs -
- )} -
-
- ); -} - -export default ImagePack; - -export { ImagePackUser, ImagePackGlobal }; diff --git a/src/app/molecules/image-pack/ImagePack.scss b/src/app/molecules/image-pack/ImagePack.scss deleted file mode 100644 index 91d6a18..0000000 --- a/src/app/molecules/image-pack/ImagePack.scss +++ /dev/null @@ -1,47 +0,0 @@ -@use '../../partials/flex'; - -.image-pack { - &-item { - border-top: 1px solid var(--bg-surface-border); - } - - &__header { - padding: var(--sp-extra-tight) var(--sp-normal); - display: flex; - align-items: center; - gap: var(--sp-normal); - - & > *:nth-child(2) { - @extend .cp-fx__item-one; - } - } - - &__footer { - padding: var(--sp-normal); - display: flex; - justify-content: space-between; - gap: var(--sp-tight); - } - - &__global { - padding: var(--sp-normal); - padding-top: var(--sp-tight); - display: flex; - align-items: center; - gap: var(--sp-normal); - } -} - -.image-pack-global { - &__empty { - text-align: center; - padding: var(--sp-extra-loose) var(--sp-normal); - } - & .image-pack__global { - padding: 0 var(--sp-normal); - padding-bottom: var(--sp-normal); - &:first-child { - padding-top: var(--sp-normal); - } - } -} diff --git a/src/app/molecules/image-pack/ImagePackItem.jsx b/src/app/molecules/image-pack/ImagePackItem.jsx deleted file mode 100644 index 2743679..0000000 --- a/src/app/molecules/image-pack/ImagePackItem.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import './ImagePackItem.scss'; - -import { openReusableContextMenu } from '../../../client/action/navigation'; -import { getEventCords } from '../../../util/common'; - -import Avatar from '../../atoms/avatar/Avatar'; -import Text from '../../atoms/text/Text'; -import Button from '../../atoms/button/Button'; -import RawIcon from '../../atoms/system-icons/RawIcon'; -import IconButton from '../../atoms/button/IconButton'; -import ImagePackUsageSelector from './ImagePackUsageSelector'; - -import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg'; -import PencilIC from '../../../../public/res/ic/outlined/pencil.svg'; -import BinIC from '../../../../public/res/ic/outlined/bin.svg'; - -function ImagePackItem({ - url, shortcode, usage, onUsageChange, onDelete, onRename, -}) { - const handleUsageSelect = (event) => { - openReusableContextMenu( - 'bottom', - getEventCords(event, '.btn-surface'), - (closeMenu) => ( - { - onUsageChange(shortcode, newUsage); - closeMenu(); - }} - /> - ), - ); - }; - - return ( -
- -
- {shortcode} -
-
-
- {onRename && onRename(shortcode)} />} - {onDelete && onDelete(shortcode)} />} -
- -
-
- ); -} - -ImagePackItem.defaultProps = { - onUsageChange: null, - onDelete: null, - onRename: null, -}; -ImagePackItem.propTypes = { - url: PropTypes.string.isRequired, - shortcode: PropTypes.string.isRequired, - usage: PropTypes.oneOf(['emoticon', 'sticker', 'both']).isRequired, - onUsageChange: PropTypes.func, - onDelete: PropTypes.func, - onRename: PropTypes.func, -}; - -export default ImagePackItem; diff --git a/src/app/molecules/image-pack/ImagePackItem.scss b/src/app/molecules/image-pack/ImagePackItem.scss deleted file mode 100644 index ab1be3a..0000000 --- a/src/app/molecules/image-pack/ImagePackItem.scss +++ /dev/null @@ -1,43 +0,0 @@ -@use '../../partials/flex'; -@use '../../partials/dir'; - -.image-pack-item { - margin: 0 var(--sp-normal); - padding: var(--sp-tight) 0; - display: flex; - align-items: center; - gap: var(--sp-normal); - - & .avatar-container img { - object-fit: contain; - border-radius: 0; - } - - &__content { - @extend .cp-fx__item-one; - } - - &__usage { - display: flex; - gap: var(--sp-ultra-tight); - & button { - padding: 6px; - } - & > button.btn-surface { - padding: 6px var(--sp-tight); - min-width: 0; - @include dir.side(margin, var(--sp-ultra-tight), 0); - } - } - - &__btn { - display: none; - } - &:hover, - &:focus-within { - .image-pack-item__btn { - display: flex; - gap: var(--sp-ultra-tight); - } - } -} \ No newline at end of file diff --git a/src/app/molecules/image-pack/ImagePackProfile.jsx b/src/app/molecules/image-pack/ImagePackProfile.jsx deleted file mode 100644 index b639936..0000000 --- a/src/app/molecules/image-pack/ImagePackProfile.jsx +++ /dev/null @@ -1,125 +0,0 @@ -import React, { useState } from 'react'; -import PropTypes from 'prop-types'; -import './ImagePackProfile.scss'; - -import { openReusableContextMenu } from '../../../client/action/navigation'; -import { getEventCords } from '../../../util/common'; - -import Text from '../../atoms/text/Text'; -import Avatar from '../../atoms/avatar/Avatar'; -import Button from '../../atoms/button/Button'; -import IconButton from '../../atoms/button/IconButton'; -import Input from '../../atoms/input/Input'; -import ImageUpload from '../image-upload/ImageUpload'; -import ImagePackUsageSelector from './ImagePackUsageSelector'; - -import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg'; -import PencilIC from '../../../../public/res/ic/outlined/pencil.svg'; - -function ImagePackProfile({ - avatarUrl, displayName, attribution, usage, - onUsageChange, onAvatarChange, onEditProfile, -}) { - const [isEdit, setIsEdit] = useState(false); - - const handleSubmit = (e) => { - e.preventDefault(); - - const { nameInput, attributionInput } = e.target; - const name = nameInput.value.trim() || undefined; - const att = attributionInput.value.trim() || undefined; - - onEditProfile(name, att); - setIsEdit(false); - }; - - const handleUsageSelect = (event) => { - openReusableContextMenu( - 'bottom', - getEventCords(event, '.btn-surface'), - (closeMenu) => ( - { - onUsageChange(newUsage); - closeMenu(); - }} - /> - ), - ); - }; - - return ( -
- { - onAvatarChange - ? ( - onAvatarChange(undefined)} - /> - ) - : - } -
- { - isEdit - ? ( -
- - -
- - -
-
- ) : ( - <> -
- {displayName} - {onEditProfile && setIsEdit(true)} src={PencilIC} tooltip="Edit" />} -
- {attribution && {attribution}} - - ) - } -
-
- Pack usage - -
-
- ); -} - -ImagePackProfile.defaultProps = { - avatarUrl: null, - attribution: null, - onUsageChange: null, - onAvatarChange: null, - onEditProfile: null, -}; -ImagePackProfile.propTypes = { - avatarUrl: PropTypes.string, - displayName: PropTypes.string.isRequired, - attribution: PropTypes.string, - usage: PropTypes.oneOf(['emoticon', 'sticker', 'both']).isRequired, - onUsageChange: PropTypes.func, - onAvatarChange: PropTypes.func, - onEditProfile: PropTypes.func, -}; - -export default ImagePackProfile; diff --git a/src/app/molecules/image-pack/ImagePackProfile.scss b/src/app/molecules/image-pack/ImagePackProfile.scss deleted file mode 100644 index d21212f..0000000 --- a/src/app/molecules/image-pack/ImagePackProfile.scss +++ /dev/null @@ -1,37 +0,0 @@ -@use '../../partials/flex'; - -.image-pack-profile { - padding: var(--sp-normal); - display: flex; - align-items: flex-start; - gap: var(--sp-tight); - - &__content { - @extend .cp-fx__item-one; - - & > div:first-child { - display: flex; - align-items: center; - gap: var(--sp-extra-tight); - - & .ic-btn { - padding: var(--sp-ultra-tight); - } - } - & > form { - display: flex; - flex-direction: column; - gap: var(--sp-extra-tight); - & > div:last-child { - margin: var(--sp-extra-tight) 0; - display: flex; - gap: var(--sp-tight); - } - } - } - &__usage { - & > *:first-child { - margin-bottom: var(--sp-ultra-tight); - } - } -} \ No newline at end of file diff --git a/src/app/molecules/image-pack/ImagePackUpload.jsx b/src/app/molecules/image-pack/ImagePackUpload.jsx deleted file mode 100644 index cdf2e13..0000000 --- a/src/app/molecules/image-pack/ImagePackUpload.jsx +++ /dev/null @@ -1,73 +0,0 @@ -import React, { useState, useRef } from 'react'; -import PropTypes from 'prop-types'; -import './ImagePackUpload.scss'; - -import { scaleDownImage } from '../../../util/common'; - -import Text from '../../atoms/text/Text'; -import Button from '../../atoms/button/Button'; -import Input from '../../atoms/input/Input'; -import IconButton from '../../atoms/button/IconButton'; -import CirclePlusIC from '../../../../public/res/ic/outlined/circle-plus.svg'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; - -function ImagePackUpload({ onUpload }) { - const mx = useMatrixClient(); - const inputRef = useRef(null); - const shortcodeRef = useRef(null); - const [imgFile, setImgFile] = useState(null); - const [progress, setProgress] = useState(false); - - const handleSubmit = async (evt) => { - evt.preventDefault(); - if (!imgFile) return; - const { shortcodeInput } = evt.target; - const shortcode = shortcodeInput.value.trim(); - if (shortcode === '') return; - - setProgress(true); - const image = await scaleDownImage(imgFile, 512, 512); - const { content_uri: url } = await mx.uploadContent(image); - - onUpload(shortcode, url); - setProgress(false); - setImgFile(null); - shortcodeRef.current.value = ''; - }; - - const handleFileChange = (evt) => { - const img = evt.target.files[0]; - if (!img) return; - setImgFile(img); - shortcodeRef.current.value = img.name.slice(0, img.name.indexOf('.')); - shortcodeRef.current.focus(); - }; - const handleRemove = () => { - setImgFile(null); - inputRef.current.value = null; - shortcodeRef.current.value = ''; - }; - - return ( -
- - { - imgFile - ? ( -
- - {imgFile.name} -
- ) - : - } - - -
- ); -} -ImagePackUpload.propTypes = { - onUpload: PropTypes.func.isRequired, -}; - -export default ImagePackUpload; diff --git a/src/app/molecules/image-pack/ImagePackUpload.scss b/src/app/molecules/image-pack/ImagePackUpload.scss deleted file mode 100644 index 75b57ed..0000000 --- a/src/app/molecules/image-pack/ImagePackUpload.scss +++ /dev/null @@ -1,43 +0,0 @@ -@use '../../partials/dir'; -@use '../../partials/text'; - -.image-pack-upload { - padding: var(--sp-normal); - padding-top: 0; - display: flex; - gap: var(--sp-tight); - - & > .input-container { - flex-grow: 1; - input { - padding: 9px var(--sp-normal); - } - } - &__file { - display: inline-flex; - align-items: center; - background: var(--bg-surface-low); - border-radius: var(--bo-radius); - box-shadow: var(--bs-surface-border); - - & button { - --parent-height: 40px; - width: var(--parent-height); - height: 100%; - display: flex; - justify-content: center; - align-items: center; - } - - & .ic-raw { - background-color: var(--bg-caution); - transform: rotate(45deg); - } - - & .text { - @extend .cp-txt__ellipsis; - @include dir.side(margin, var(--sp-ultra-tight), var(--sp-normal)); - max-width: 86px; - } - } -} \ No newline at end of file diff --git a/src/app/molecules/image-pack/ImagePackUsageSelector.jsx b/src/app/molecules/image-pack/ImagePackUsageSelector.jsx deleted file mode 100644 index 279b381..0000000 --- a/src/app/molecules/image-pack/ImagePackUsageSelector.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu'; -import CheckIC from '../../../../public/res/ic/outlined/check.svg'; - -function ImagePackUsageSelector({ usage, onSelect }) { - return ( -
- Usage - onSelect('emoticon')} - > - Emoji - - onSelect('sticker')} - > - Sticker - - onSelect('both')} - > - Both - -
- ); -} - -ImagePackUsageSelector.propTypes = { - usage: PropTypes.oneOf(['emoticon', 'sticker', 'both']).isRequired, - onSelect: PropTypes.func.isRequired, -}; - -export default ImagePackUsageSelector; diff --git a/src/app/molecules/room-aliases/RoomAliases.jsx b/src/app/molecules/room-aliases/RoomAliases.jsx deleted file mode 100644 index a96fbb8..0000000 --- a/src/app/molecules/room-aliases/RoomAliases.jsx +++ /dev/null @@ -1,359 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import PropTypes from 'prop-types'; -import './RoomAliases.scss'; -import { EventTimeline } from 'matrix-js-sdk'; - -import cons from '../../../client/state/cons'; -import { Debounce } from '../../../util/common'; -import { isRoomAliasAvailable } from '../../../util/matrixUtil'; - -import Text from '../../atoms/text/Text'; -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 { MenuHeader } from '../../atoms/context-menu/ContextMenu'; -import SettingTile from '../setting-tile/SettingTile'; - -import { useStore } from '../../hooks/useStore'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; - -function useValidate(hsString) { - const mx = useMatrixClient(); - const [debounce] = useState(new Debounce()); - const [validate, setValidate] = useState({ alias: null, status: cons.status.PRE_FLIGHT }); - - const setValidateToDefault = () => { - setValidate({ - alias: null, - status: cons.status.PRE_FLIGHT, - }); - }; - - const checkValueOK = (value) => { - if (value.trim() === '') { - setValidateToDefault(); - return false; - } - if (!value.match(/^[a-zA-Z0-9_-]+$/)) { - setValidate({ - alias: null, - status: cons.status.ERROR, - msg: 'Invalid character: only letter, numbers and _- are allowed.', - }); - return false; - } - return true; - }; - - const handleAliasChange = (e) => { - const input = e.target; - if (validate.status !== cons.status.PRE_FLIGHT) { - setValidateToDefault(); - } - if (checkValueOK(input.value) === false) return; - - debounce._(async () => { - const { value } = input; - const alias = `#${value}:${hsString}`; - if (checkValueOK(value) === false) return; - - setValidate({ - alias, - status: cons.status.IN_FLIGHT, - msg: `validating ${alias}...`, - }); - - const isValid = await isRoomAliasAvailable(mx, alias); - setValidate(() => { - if (e.target.value !== value) { - return { alias: null, status: cons.status.PRE_FLIGHT }; - } - return { - alias, - status: isValid ? cons.status.SUCCESS : cons.status.ERROR, - msg: isValid ? `${alias} is available.` : `${alias} is already in use.`, - }; - }); - }, 600)(); - }; - - return [validate, setValidateToDefault, handleAliasChange]; -} - -function getAliases(mx, roomId) { - const room = mx.getRoom(roomId); - - const main = room.getCanonicalAlias(); - const published = room.getAltAliases(); - if (main && !published.includes(main)) published.splice(0, 0, main); - - return { - main, - published: [...new Set(published)], - local: [], - }; -} - -function RoomAliases({ roomId }) { - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - const userId = mx.getUserId(); - const hsString = userId.slice(userId.indexOf(':') + 1); - - const isMountedStore = useStore(); - const [isPublic, setIsPublic] = useState(false); - const [isLocalVisible, setIsLocalVisible] = useState(false); - const [aliases, setAliases] = useState(getAliases(mx, roomId)); - const [selectedAlias, setSelectedAlias] = useState(null); - const [deleteAlias, setDeleteAlias] = useState(null); - const [validate, setValidateToDefault, handleAliasChange] = useValidate(hsString); - - const canPublishAlias = room.getLiveTimeline().getState(EventTimeline.FORWARDS)?.maySendStateEvent('m.room.canonical_alias', userId); - - useEffect(() => { - isMountedStore.setItem(true) - }, []); - - useEffect(() => { - let isUnmounted = false; - - const loadLocalAliases = async () => { - let local = []; - try { - const result = await mx.getLocalAliases(roomId); - local = result.aliases.filter((alias) => !aliases.published.includes(alias)); - } catch { - local = []; - } - aliases.local = [...new Set(local.reverse())]; - - if (isUnmounted) return; - setAliases({ ...aliases }); - }; - const loadVisibility = async () => { - const result = await mx.getRoomDirectoryVisibility(roomId); - if (isUnmounted) return; - setIsPublic(result.visibility === 'public'); - }; - loadLocalAliases(); - loadVisibility(); - return () => { - isUnmounted = true; - }; - }, [mx, roomId]); - - const toggleDirectoryVisibility = () => { - mx.setRoomDirectoryVisibility(roomId, isPublic ? 'private' : 'public'); - setIsPublic(!isPublic); - }; - - const handleAliasSubmit = async (e) => { - e.preventDefault(); - if (validate.status === cons.status.ERROR) return; - if (!validate.alias) return; - - const { alias } = validate; - const aliasInput = e.target.elements['alias-input']; - aliasInput.value = ''; - setValidateToDefault(); - - try { - aliases.local.push(alias); - setAliases({ ...aliases }); - await mx.createAlias(alias, roomId); - } catch { - if (isMountedStore.getItem()) { - const lIndex = alias.local.indexOf(alias); - if (lIndex === -1) return; - aliases.local.splice(lIndex, 1); - setAliases({ ...aliases }); - } - } - }; - - const handleAliasSelect = (alias) => { - setSelectedAlias(alias === selectedAlias ? null : alias); - }; - - const handlePublishAlias = (alias) => { - const { main, published } = aliases; - let { local } = aliases; - - if (!published.includes(aliases)) { - published.push(alias); - local = local.filter((al) => al !== alias); - mx.sendStateEvent(roomId, 'm.room.canonical_alias', { - alias: main, - alt_aliases: published.filter((al) => al !== main), - }); - setAliases({ main, published, local }); - setSelectedAlias(null); - } - }; - - const handleUnPublishAlias = (alias) => { - let { main, published } = aliases; - const { local } = aliases; - - if (published.includes(alias) || main === alias) { - if (main === alias) main = null; - published = published.filter((al) => al !== alias); - local.push(alias); - mx.sendStateEvent(roomId, 'm.room.canonical_alias', { - alias: main, - alt_aliases: published.filter((al) => al !== main), - }); - setAliases({ main, published, local }); - setSelectedAlias(null); - } - }; - - const handleSetMainAlias = (alias) => { - let { main, local } = aliases; - const { published } = aliases; - - if (main !== alias) { - main = alias; - if (!published.includes(alias)) published.splice(0, 0, alias); - local = local.filter((al) => al !== alias); - mx.sendStateEvent(roomId, 'm.room.canonical_alias', { - alias: main, - alt_aliases: published.filter((al) => al !== main), - }); - setAliases({ main, published, local }); - setSelectedAlias(null); - } - }; - - const handleDeleteAlias = async (alias) => { - try { - setDeleteAlias({ alias, status: cons.status.IN_FLIGHT, msg: 'deleting...' }); - await mx.deleteAlias(alias); - let { main, published, local } = aliases; - if (published.includes(alias)) { - handleUnPublishAlias(alias); - if (main === alias) main = null; - published = published.filter((al) => al !== alias); - } - - local = local.filter((al) => al !== alias); - setAliases({ main, published, local }); - setDeleteAlias(null); - setSelectedAlias(null); - } catch (err) { - setDeleteAlias({ alias, status: cons.status.ERROR, msg: err.message }); - } - }; - - const renderAliasBtns = (alias) => { - const isPublished = aliases.published.includes(alias); - const isMain = aliases.main === alias; - if (deleteAlias?.alias === alias) { - const isError = deleteAlias.status === cons.status.ERROR; - return ( -
- - {deleteAlias.msg} - -
- ); - } - - return ( -
- {canPublishAlias && !isMain && } - {!isPublished && canPublishAlias && } - {isPublished && canPublishAlias && } - -
- ); - }; - - const renderAlias = (alias) => { - const isActive = selectedAlias === alias; - const disabled = !canPublishAlias && aliases.published.includes(alias); - const isMain = aliases.main === alias; - - return ( - -
- handleAliasSelect(alias)} /> - - {alias} - {isMain && Main} - -
- {isActive && renderAliasBtns(alias)} -
- ); - }; - - let inputState = 'normal'; - if (validate.status === cons.status.ERROR) inputState = 'error'; - if (validate.status === cons.status.SUCCESS) inputState = 'success'; - return ( -
- {`Publish this ${room.isSpaceRoom() ? 'space' : 'room'} to the ${hsString}'s public room directory?`}} - options={( - - )} - /> - -
- Published addresses - {(aliases.published.length === 0) && No published addresses} - {(aliases.published.length > 0 && !aliases.main) && No Main address (select one from below)} - {aliases.published.map(renderAlias)} - - {`Published addresses can be used by anyone on any server to join your ${room.isSpaceRoom() ? 'space' : 'room'}. To publish an address, it needs to be set as a local address first.`} - -
- { isLocalVisible && ( -
- Local addresses - {(aliases.local.length === 0) && No local addresses} - {aliases.local.map(renderAlias)} - - {`Set local addresses for this ${room.isSpaceRoom() ? 'space' : 'room'} so users can find this ${room.isSpaceRoom() ? 'space' : 'room'} through your homeserver.`} - - - Add local address -
-
- -
- -
-
- {validate.status === cons.status.SUCCESS && {validate.msg}} - {validate.status === cons.status.ERROR && {validate.msg}} -
-
- )} -
- -
-
- ); -} - -RoomAliases.propTypes = { - roomId: PropTypes.string.isRequired, -}; - -export default RoomAliases; diff --git a/src/app/molecules/room-aliases/RoomAliases.scss b/src/app/molecules/room-aliases/RoomAliases.scss deleted file mode 100644 index b0df614..0000000 --- a/src/app/molecules/room-aliases/RoomAliases.scss +++ /dev/null @@ -1,84 +0,0 @@ -@use '../../partials/flex'; -@use '../../partials/dir'; -@use '../../partials/text'; - -.room-aliases { - &__message, - & .setting-tile { - margin: var(--sp-tight) var(--sp-normal); - } - & .setting-tile { - margin-bottom: var(--sp-loose); - } - - &__alias-item { - padding: var(--sp-extra-tight) var(--sp-normal); - @extend .cp-fx__row--s-c; - &.checkbox { - @include dir.side(margin, 0 , var(--sp-tight)); - } - & .text { - @extend .cp-fx__item-one; - @extend .cp-txt__ellipsis; - color: var(--tc-surface-high); - span { - margin: 0 var(--sp-extra-tight); - padding: 0 var(--sp-ultra-tight); - color: var(--bg-surface); - background-color: var(--tc-surface-low); - border-radius: 4px; - } - } - } - &__item-btns { - @include dir.side(margin, 48px, 0); - & button { - padding: var(--sp-ultra-tight) var(--sp-tight); - margin-bottom: var(--sp-tight); - @include dir.side(margin, 0, var(--sp-tight)); - } - } - - &__content { - margin-bottom: var(--sp-normal); - - & .checkbox { - @include dir.side(margin, 0, var(--sp-tight)); - min-width: 20px; - } - & > button { - margin: 0 var(--sp-normal); - } - } - - &__form { - padding: var(--sp-normal); - padding-top: 0; - display: flex; - &-label { - padding: var(--sp-normal) var(--sp-normal) var(--sp-ultra-tight); - } - } - - &__input-wrapper { - display: flex; - @extend .cp-fx__item-one; - @include dir.side(margin, 0, var(--sp-tight)); - - & .input-container { - @extend .cp-fx__item-one; - } - } - - &__input-status { - padding: 0 var(--sp-normal); - } - &__valid { - color: var(--tc-positive-high); - padding-bottom: var(--sp-normal); - } - &__invalid { - color: var(--tc-danger-high); - padding-bottom: var(--sp-normal); - } -} \ No newline at end of file diff --git a/src/app/molecules/room-emojis/RoomEmojis.jsx b/src/app/molecules/room-emojis/RoomEmojis.jsx deleted file mode 100644 index c45a9af..0000000 --- a/src/app/molecules/room-emojis/RoomEmojis.jsx +++ /dev/null @@ -1,131 +0,0 @@ -import React, { useReducer, useEffect } from 'react'; -import PropTypes from 'prop-types'; -import './RoomEmojis.scss'; -import { EventTimeline } from 'matrix-js-sdk'; - -import { suffixRename } from '../../../util/common'; - -import { MenuHeader } from '../../atoms/context-menu/ContextMenu'; -import Text from '../../atoms/text/Text'; -import Input from '../../atoms/input/Input'; -import Button from '../../atoms/button/Button'; -import ImagePack from '../image-pack/ImagePack'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; -import { getStateEvent, getStateEvents } from '../../utils/room'; - -function useRoomPacks(room) { - const mx = useMatrixClient(); - const [, forceUpdate] = useReducer((count) => count + 1, 0); - - const packEvents = getStateEvents(room, 'im.ponies.room_emotes'); - const unUsablePacks = []; - const usablePacks = packEvents.filter((mEvent) => { - if (typeof mEvent.getContent()?.images !== 'object') { - unUsablePacks.push(mEvent); - return false; - } - return true; - }); - - useEffect(() => { - const handleEvent = (event, state, prevEvent) => { - if (event.getRoomId() !== room.roomId) return; - if (event.getType() !== 'im.ponies.room_emotes') return; - if (!prevEvent?.getContent()?.images || !event.getContent().images) { - forceUpdate(); - } - }; - - mx.on('RoomState.events', handleEvent); - return () => { - mx.removeListener('RoomState.events', handleEvent); - }; - }, [room, mx]); - - const isStateKeyAvailable = (key) => !getStateEvent(room, 'im.ponies.room_emotes', key); - - const createPack = async (name) => { - const packContent = { - pack: { display_name: name }, - images: {}, - }; - let stateKey = ''; - if (unUsablePacks.length > 0) { - const mEvent = unUsablePacks[0]; - stateKey = mEvent.getStateKey(); - } else { - stateKey = packContent.pack.display_name.replace(/\s/g, '-'); - if (!isStateKeyAvailable(stateKey)) { - stateKey = suffixRename( - stateKey, - isStateKeyAvailable, - ); - } - } - await mx.sendStateEvent(room.roomId, 'im.ponies.room_emotes', packContent, stateKey); - }; - - const deletePack = async (stateKey) => { - await mx.sendStateEvent(room.roomId, 'im.ponies.room_emotes', {}, stateKey); - }; - - return { - usablePacks, - createPack, - deletePack, - }; -} - -function RoomEmojis({ roomId }) { - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - - const { usablePacks, createPack, deletePack } = useRoomPacks(room); - - const canChange = room.getLiveTimeline().getState(EventTimeline.FORWARDS)?.maySendStateEvent('im.ponies.room_emote', mx.getUserId()); - - const handlePackCreate = (e) => { - e.preventDefault(); - const { nameInput } = e.target; - const name = nameInput.value.trim(); - if (name === '') return; - nameInput.value = ''; - - createPack(name); - }; - - return ( -
- { canChange && ( -
- Create Pack -
- - -
-
- )} - { - usablePacks.length > 0 - ? usablePacks.reverse().map((mEvent) => ( - - )) : ( -
- No emoji or sticker pack. -
- ) - } -
- ); -} - -RoomEmojis.propTypes = { - roomId: PropTypes.string.isRequired, -}; - -export default RoomEmojis; diff --git a/src/app/molecules/room-emojis/RoomEmojis.scss b/src/app/molecules/room-emojis/RoomEmojis.scss deleted file mode 100644 index 7ba2b49..0000000 --- a/src/app/molecules/room-emojis/RoomEmojis.scss +++ /dev/null @@ -1,29 +0,0 @@ -.room-emojis { - .image-pack, - .room-emojis__add-pack, - .room-emojis__empty { - margin: var(--sp-normal) 0; - background-color: var(--bg-surface); - border-radius: var(--bo-radius); - box-shadow: var(--bs-surface-border); - overflow: hidden; - - & > .context-menu__header:first-child { - margin-top: 2px; - } - } - &__add-pack { - & form { - margin: var(--sp-normal); - display: flex; - gap: var(--sp-normal); - & .input-container { - flex-grow: 1; - } - } - } - &__empty { - padding: var(--sp-extra-loose) var(--sp-normal); - text-align: center; - } -} \ No newline at end of file diff --git a/src/app/molecules/room-encryption/RoomEncryption.jsx b/src/app/molecules/room-encryption/RoomEncryption.jsx deleted file mode 100644 index 6db87a8..0000000 --- a/src/app/molecules/room-encryption/RoomEncryption.jsx +++ /dev/null @@ -1,61 +0,0 @@ -import React, { useState } from 'react'; -import PropTypes from 'prop-types'; -import './RoomEncryption.scss'; -import { EventTimeline } from 'matrix-js-sdk'; - -import Text from '../../atoms/text/Text'; -import Toggle from '../../atoms/button/Toggle'; -import SettingTile from '../setting-tile/SettingTile'; - -import { confirmDialog } from '../confirm-dialog/ConfirmDialog'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; -import { getStateEvents } from '../../utils/room'; - -function RoomEncryption({ roomId }) { - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - const encryptionEvents = getStateEvents(room, 'm.room.encryption'); - const [isEncrypted, setIsEncrypted] = useState(encryptionEvents.length > 0); - const canEnableEncryption = room.getLiveTimeline().getState(EventTimeline.FORWARDS).maySendStateEvent('m.room.encryption', mx.getUserId()); - - const handleEncryptionEnable = async () => { - const joinRule = room.getJoinRule(); - const confirmMsg1 = 'It is not recommended to add encryption in public room. Anyone can find and join public rooms, so anyone can read messages in them.'; - const confirmMsg2 = 'Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly'; - - const isConfirmed1 = (joinRule === 'public') - ? await confirmDialog('Enable encryption', confirmMsg1, 'Continue', 'caution') - : true; - if (!isConfirmed1) return; - if (await confirmDialog('Enable encryption', confirmMsg2, 'Enable', 'caution')) { - setIsEncrypted(true); - mx.sendStateEvent(roomId, 'm.room.encryption', { - algorithm: 'm.megolm.v1.aes-sha2', - }); - } - }; - - return ( -
- Once enabled, encryption cannot be disabled. - )} - options={( - - )} - /> -
- ); -} - -RoomEncryption.propTypes = { - roomId: PropTypes.string.isRequired, -}; - -export default RoomEncryption; diff --git a/src/app/molecules/room-encryption/RoomEncryption.scss b/src/app/molecules/room-encryption/RoomEncryption.scss deleted file mode 100644 index 1c521f4..0000000 --- a/src/app/molecules/room-encryption/RoomEncryption.scss +++ /dev/null @@ -1,5 +0,0 @@ -.room-encryption { - & .setting-tile { - margin: var(--sp-normal); - } -} \ No newline at end of file diff --git a/src/app/molecules/room-history-visibility/RoomHistoryVisibility.jsx b/src/app/molecules/room-history-visibility/RoomHistoryVisibility.jsx deleted file mode 100644 index c897cb3..0000000 --- a/src/app/molecules/room-history-visibility/RoomHistoryVisibility.jsx +++ /dev/null @@ -1,96 +0,0 @@ -import React, { useState, useEffect, useCallback } from 'react'; -import PropTypes from 'prop-types'; -import './RoomHistoryVisibility.scss'; - - -import Text from '../../atoms/text/Text'; -import RadioButton from '../../atoms/button/RadioButton'; -import { MenuItem } from '../../atoms/context-menu/ContextMenu'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; - -const visibility = { - WORLD_READABLE: 'world_readable', - SHARED: 'shared', - INVITED: 'invited', - JOINED: 'joined', -}; - -const items = [{ - iconSrc: null, - text: 'Anyone (including guests)', - type: visibility.WORLD_READABLE, -}, { - iconSrc: null, - text: 'Members (all messages)', - type: visibility.SHARED, -}, { - iconSrc: null, - text: 'Members (messages after invite)', - type: visibility.INVITED, -}, { - iconSrc: null, - text: 'Members (messages after join)', - type: visibility.JOINED, -}]; - - -function useVisibility(roomId) { - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - - const [activeType, setActiveType] = useState(room.getHistoryVisibility()); - useEffect(() => { - setActiveType(room.getHistoryVisibility()); - }, [room]); - - const setVisibility = useCallback((item) => { - if (item.type === activeType.type) return; - setActiveType(item.type); - mx.sendStateEvent( - roomId, 'm.room.history_visibility', - { - history_visibility: item.type, - }, - ); - }, [mx, activeType, roomId]); - - return [activeType, setVisibility]; -} - -function RoomHistoryVisibility({ roomId }) { - const [activeType, setVisibility] = useVisibility(roomId); - const mx = useMatrixClient(); - 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 history visibility will only apply to future messages. The visibility of existing history will have no effect. -
- ); -} - -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 deleted file mode 100644 index b9e0a2c..0000000 --- a/src/app/molecules/room-history-visibility/RoomHistoryVisibility.scss +++ /dev/null @@ -1,25 +0,0 @@ -@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/molecules/room-intro/RoomIntro.jsx b/src/app/molecules/room-intro/RoomIntro.jsx deleted file mode 100644 index 2ec46cb..0000000 --- a/src/app/molecules/room-intro/RoomIntro.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import './RoomIntro.scss'; - -import colorMXID from '../../../util/colorMXID'; - -import Text from '../../atoms/text/Text'; -import Avatar from '../../atoms/avatar/Avatar'; - -function RoomIntro({ - roomId, avatarSrc, name, heading, desc, time, -}) { - return ( -
- -
- {heading} - {desc} - { time !== null && {time}} -
-
- ); -} - -RoomIntro.defaultProps = { - avatarSrc: null, - time: null, -}; - -RoomIntro.propTypes = { - roomId: PropTypes.string.isRequired, - avatarSrc: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.bool, - ]), - name: PropTypes.string.isRequired, - heading: PropTypes.node.isRequired, - desc: PropTypes.node.isRequired, - time: PropTypes.node, -}; - -export default RoomIntro; diff --git a/src/app/molecules/room-intro/RoomIntro.scss b/src/app/molecules/room-intro/RoomIntro.scss deleted file mode 100644 index 7e80249..0000000 --- a/src/app/molecules/room-intro/RoomIntro.scss +++ /dev/null @@ -1,26 +0,0 @@ -@use '../../partials/dir'; - -.room-intro { - margin-top: calc(2 * var(--sp-extra-loose)); - margin-bottom: var(--sp-extra-loose); - --left-pad: calc(var(--sp-normal) + var(--av-small) + var(--sp-tight)); - @include dir.side(padding, var(--left-pad), var(--sp-extra-tight)); - - .room-intro__content { - margin-top: var(--sp-extra-loose); - width: calc(100% - 88px); - } - &__name { - color: var(--tc-surface-high); - } - &__desc { - color: var(--tc-surface-normal); - margin: var(--sp-tight) 0 var(--sp-extra-tight); - & a { - word-break: break-all; - } - } - &__time { - color: var(--tc-surface-low); - } -} \ No newline at end of file diff --git a/src/app/molecules/room-members/RoomMembers.jsx b/src/app/molecules/room-members/RoomMembers.jsx deleted file mode 100644 index a3928fb..0000000 --- a/src/app/molecules/room-members/RoomMembers.jsx +++ /dev/null @@ -1,185 +0,0 @@ -import React, { - useState, useEffect, useCallback, -} from 'react'; -import PropTypes from 'prop-types'; -import './RoomMembers.scss'; - -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'; -import Input from '../../atoms/input/Input'; -import { MenuHeader } from '../../atoms/context-menu/ContextMenu'; -import SegmentedControls from '../../atoms/segmented-controls/SegmentedControls'; -import PeopleSelector from '../people-selector/PeopleSelector'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; - -const PER_PAGE_MEMBER = 50; - -function normalizeMembers(mx, members) { - return members.map((member) => ({ - userId: member.userId, - name: getUsernameOfRoomMember(member), - username: member.userId.slice(1, member.userId.indexOf(':')), - avatarSrc: member.getAvatarUrl(mx.baseUrl, 24, 24, 'crop'), - peopleRole: getPowerLabel(member.powerLevel), - powerLevel: members.powerLevel, - })); -} - -function useMemberOfMembership(roomId, membership) { - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - const [members, setMembers] = useState([]); - - useEffect(() => { - let isMounted = true; - let isLoadingMembers = false; - - const updateMemberList = (event) => { - if (isLoadingMembers) return; - if (event && event?.getRoomId() !== roomId) return; - const memberOfMembership = normalizeMembers( - mx, - room.getMembersWithMembership(membership) - .sort(memberByAtoZ).sort(memberByPowerLevel), - ); - setMembers(memberOfMembership); - }; - - updateMemberList(); - isLoadingMembers = true; - room.loadMembersIfNeeded().then(() => { - isLoadingMembers = false; - if (!isMounted) return; - updateMemberList(); - }); - - mx.on('RoomMember.membership', updateMemberList); - mx.on('RoomMember.powerLevel', updateMemberList); - return () => { - isMounted = false; - mx.removeListener('RoomMember.membership', updateMemberList); - mx.removeListener('RoomMember.powerLevel', updateMemberList); - }; - }, [mx, membership]); - - return [members]; -} - -function useSearchMembers(members) { - const [searchMembers, setSearchMembers] = useState(null); - const [asyncSearch] = useState(new AsyncSearch()); - - const reSearch = useCallback(() => { - if (searchMembers) { - asyncSearch.search(searchMembers.term); - } - }, [searchMembers, asyncSearch]); - - useEffect(() => { - asyncSearch.setup(members, { - keys: ['name', 'username', 'userId'], - limit: PER_PAGE_MEMBER, - }); - reSearch(); - }, [members, asyncSearch]); - - useEffect(() => { - const handleSearchData = (data, term) => setSearchMembers({ data, term }); - asyncSearch.on(asyncSearch.RESULT_SENT, handleSearchData); - return () => { - asyncSearch.removeListener(asyncSearch.RESULT_SENT, handleSearchData); - }; - }, [asyncSearch]); - - const handleSearch = (e) => { - const term = e.target.value; - if (term === '' || term === undefined) { - setSearchMembers(null); - } else asyncSearch.search(term); - }; - - return [searchMembers, handleSearch]; -} - -function RoomMembers({ roomId }) { - const [itemCount, setItemCount] = useState(PER_PAGE_MEMBER); - const [membership, setMembership] = useState('join'); - const [members] = useMemberOfMembership(roomId, membership); - const [searchMembers, handleSearch] = useSearchMembers(members); - - useEffect(() => { - setItemCount(PER_PAGE_MEMBER); - }, [searchMembers]); - - const loadMorePeople = () => { - setItemCount(itemCount + PER_PAGE_MEMBER); - }; - - const mList = searchMembers ? searchMembers.data : members.slice(0, itemCount); - return ( -
- Search member - -
- {`${searchMembers ? `Found — ${mList.length}` : members.length} members`} - { - const getSegmentIndex = { join: 0, invite: 1, ban: 2 }; - return getSegmentIndex[membership]; - })() - } - segments={[{ text: 'Joined' }, { text: 'Invited' }, { text: 'Banned' }]} - onSelect={(index) => { - const memberships = ['join', 'invite', 'ban']; - setMembership(memberships[index]); - }} - /> -
-
- {mList.map((member) => ( - openProfileViewer(member.userId, roomId)} - avatarSrc={member.avatarSrc} - name={member.name} - color={colorMXID(member.userId)} - peopleRole={member.peopleRole} - /> - ))} - { - (searchMembers?.data.length === 0 || members.length === 0) - && ( -
- - {searchMembers ? `No results found for "${searchMembers.term}"` : 'No members to display'} - -
- ) - } - { - mList.length !== 0 - && members.length > itemCount - && searchMembers === null - && - } -
-
- ); -} - -RoomMembers.propTypes = { - roomId: PropTypes.string.isRequired, -}; - -export default RoomMembers; diff --git a/src/app/molecules/room-members/RoomMembers.scss b/src/app/molecules/room-members/RoomMembers.scss deleted file mode 100644 index 4715508..0000000 --- a/src/app/molecules/room-members/RoomMembers.scss +++ /dev/null @@ -1,39 +0,0 @@ -@use '../../partials/flex'; -@use '../../partials/dir'; - -.room-members { - & .input-container { - margin: var(--sp-normal); - } - - &__header { - display: flex; - align-items: flex-start; - & .context-menu__header { - @extend .cp-fx__item-one; - margin-top: 14px; - border-top: 1px solid var(--bg-surface-border); - border-bottom: none; - } - & .segmented-controls { - @include dir.side(margin, 0, var(--sp-normal)); - & > button { - padding: var(--sp-ultra-tight) 0; - } - } - } - &__list { - - & .people-selector__container:last-child { - margin-bottom: var(--sp-extra-tight); - } - & > .btn-surface { - width: calc(100% - 32px); - margin: var(--sp-normal); - } - } - - &__status { - margin: var(--sp-normal); - } -} \ No newline at end of file diff --git a/src/app/molecules/room-notification/RoomNotification.jsx b/src/app/molecules/room-notification/RoomNotification.jsx deleted file mode 100644 index db97070..0000000 --- a/src/app/molecules/room-notification/RoomNotification.jsx +++ /dev/null @@ -1,153 +0,0 @@ -import React, { useState, useEffect, useCallback } from 'react'; -import PropTypes from 'prop-types'; -import './RoomNotification.scss'; - -import cons from '../../../client/state/cons'; - -import Text from '../../atoms/text/Text'; -import RadioButton from '../../atoms/button/RadioButton'; -import { MenuItem } from '../../atoms/context-menu/ContextMenu'; - -import BellIC from '../../../../public/res/ic/outlined/bell.svg'; -import BellRingIC from '../../../../public/res/ic/outlined/bell-ring.svg'; -import BellPingIC from '../../../../public/res/ic/outlined/bell-ping.svg'; -import BellOffIC from '../../../../public/res/ic/outlined/bell-off.svg'; -import { getNotificationType } from '../../utils/room'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; - -const items = [ - { - iconSrc: BellIC, - text: 'Global', - type: cons.notifs.DEFAULT, - }, - { - iconSrc: BellRingIC, - text: 'All messages', - type: cons.notifs.ALL_MESSAGES, - }, - { - iconSrc: BellPingIC, - text: 'Mentions & Keywords', - type: cons.notifs.MENTIONS_AND_KEYWORDS, - }, - { - iconSrc: BellOffIC, - text: 'Mute', - type: cons.notifs.MUTE, - }, -]; - -function setRoomNotifType(mx, roomId, newType) { - let roomPushRule; - try { - roomPushRule = mx.getRoomPushRule('global', roomId); - } catch { - roomPushRule = undefined; - } - const promises = []; - - if (newType === cons.notifs.MUTE) { - if (roomPushRule) { - promises.push(mx.deletePushRule('global', 'room', roomPushRule.rule_id)); - } - promises.push( - mx.addPushRule('global', 'override', roomId, { - conditions: [ - { - kind: 'event_match', - key: 'room_id', - pattern: roomId, - }, - ], - actions: ['dont_notify'], - }) - ); - return promises; - } - - const oldState = getNotificationType(mx, roomId); - if (oldState === cons.notifs.MUTE) { - promises.push(mx.deletePushRule('global', 'override', roomId)); - } - - if (newType === cons.notifs.DEFAULT) { - if (roomPushRule) { - promises.push(mx.deletePushRule('global', 'room', roomPushRule.rule_id)); - } - return Promise.all(promises); - } - - if (newType === cons.notifs.MENTIONS_AND_KEYWORDS) { - promises.push( - mx.addPushRule('global', 'room', roomId, { - actions: ['dont_notify'], - }) - ); - promises.push(mx.setPushRuleEnabled('global', 'room', roomId, true)); - return Promise.all(promises); - } - - // cons.notifs.ALL_MESSAGES - promises.push( - mx.addPushRule('global', 'room', roomId, { - actions: [ - 'notify', - { - set_tweak: 'sound', - value: 'default', - }, - ], - }) - ); - - promises.push(mx.setPushRuleEnabled('global', 'room', roomId, true)); - - return Promise.all(promises); -} - -function useNotifications(roomId) { - const mx = useMatrixClient(); - const [activeType, setActiveType] = useState(getNotificationType(mx, roomId)); - useEffect(() => { - setActiveType(getNotificationType(mx, roomId)); - }, [mx, roomId]); - - const setNotification = useCallback( - (item) => { - if (item.type === activeType.type) return; - setActiveType(item.type); - setRoomNotifType(mx, roomId, item.type); - }, - [mx, activeType, roomId] - ); - return [activeType, setNotification]; -} - -function RoomNotification({ roomId }) { - const [activeType, setNotification] = useNotifications(roomId); - - return ( -
- {items.map((item) => ( - setNotification(item)} - > - - {item.text} - - - - ))} -
- ); -} - -RoomNotification.propTypes = { - roomId: PropTypes.string.isRequired, -}; - -export default RoomNotification; diff --git a/src/app/molecules/room-notification/RoomNotification.scss b/src/app/molecules/room-notification/RoomNotification.scss deleted file mode 100644 index a831b34..0000000 --- a/src/app/molecules/room-notification/RoomNotification.scss +++ /dev/null @@ -1,19 +0,0 @@ -@use '../../partials/flex'; -@use '../../partials/dir'; -@use '../../partials/text'; - -.room-notification { - & .context-menu__item .text { - @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); - } - } -} \ No newline at end of file diff --git a/src/app/molecules/room-permissions/RoomPermissions.jsx b/src/app/molecules/room-permissions/RoomPermissions.jsx deleted file mode 100644 index 7629558..0000000 --- a/src/app/molecules/room-permissions/RoomPermissions.jsx +++ /dev/null @@ -1,284 +0,0 @@ -import React, { useEffect } from 'react'; -import PropTypes from 'prop-types'; -import './RoomPermissions.scss'; -import { EventTimeline } from 'matrix-js-sdk'; - -import { getPowerLabel } from '../../../util/matrixUtil'; -import { openReusableContextMenu } from '../../../client/action/navigation'; -import { getEventCords } from '../../../util/common'; - -import Text from '../../atoms/text/Text'; -import Button from '../../atoms/button/Button'; -import { MenuHeader } from '../../atoms/context-menu/ContextMenu'; -import PowerLevelSelector from '../power-level-selector/PowerLevelSelector'; -import SettingTile from '../setting-tile/SettingTile'; - -import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg'; - -import { useForceUpdate } from '../../hooks/useForceUpdate'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; -import { getStateEvent } from '../../utils/room'; - -const permissionsInfo = { - users_default: { - name: 'Default role', - description: 'Set default role for all members.', - default: 0, - }, - events_default: { - name: 'Send messages', - description: 'Set minimum power level to send messages in room.', - default: 0, - }, - 'm.reaction': { - parent: 'events', - name: 'Send reactions', - description: 'Set minimum power level to send reactions in room.', - default: 0, - }, - redact: { - name: 'Delete messages sent by others', - description: 'Set minimum power level to delete messages in room.', - default: 50, - }, - notifications: { - name: 'Ping room', - description: 'Set minimum power level to ping room.', - default: { - room: 50, - }, - }, - 'm.space.child': { - parent: 'events', - name: 'Manage rooms in space', - description: 'Set minimum power level to manage rooms in space.', - default: 50, - }, - invite: { - name: 'Invite', - description: 'Set minimum power level to invite members.', - default: 50, - }, - kick: { - name: 'Kick', - description: 'Set minimum power level to kick members.', - default: 50, - }, - ban: { - name: 'Ban', - description: 'Set minimum power level to ban members.', - default: 50, - }, - 'm.room.avatar': { - parent: 'events', - name: 'Change avatar', - description: 'Set minimum power level to change room/space avatar.', - default: 50, - }, - 'm.room.name': { - parent: 'events', - name: 'Change name', - description: 'Set minimum power level to change room/space name.', - default: 50, - }, - 'm.room.topic': { - parent: 'events', - name: 'Change topic', - description: 'Set minimum power level to change room/space topic.', - default: 50, - }, - state_default: { - name: 'Change settings', - description: 'Set minimum power level to change settings.', - default: 50, - }, - 'm.room.canonical_alias': { - parent: 'events', - name: 'Change published address', - description: 'Set minimum power level to publish and set main address.', - default: 50, - }, - 'm.room.power_levels': { - parent: 'events', - name: 'Change permissions', - description: 'Set minimum power level to change permissions.', - default: 50, - }, - 'm.room.encryption': { - parent: 'events', - name: 'Enable room encryption', - description: 'Set minimum power level to enable room encryption.', - default: 50, - }, - 'm.room.history_visibility': { - parent: 'events', - name: 'Change history visibility', - description: 'Set minimum power level to change room messages history visibility.', - default: 50, - }, - 'm.room.tombstone': { - parent: 'events', - name: 'Upgrade room', - description: 'Set minimum power level to upgrade room.', - default: 50, - }, - 'm.room.pinned_events': { - parent: 'events', - name: 'Pin messages', - description: 'Set minimum power level to pin messages in room.', - default: 50, - }, - 'm.room.server_acl': { - parent: 'events', - name: 'Change server ACLs', - description: 'Set minimum power level to change server ACLs.', - default: 50, - }, - 'im.vector.modular.widgets': { - parent: 'events', - name: 'Modify widgets', - description: 'Set minimum power level to modify room widgets.', - default: 50, - }, -}; - -const roomPermsGroups = { - 'General Permissions': ['users_default', 'events_default', 'm.reaction', 'redact', 'notifications'], - 'Manage members permissions': ['invite', 'kick', 'ban'], - 'Room profile permissions': ['m.room.avatar', 'm.room.name', 'm.room.topic'], - 'Settings permissions': ['state_default', 'm.room.canonical_alias', 'm.room.power_levels', 'm.room.encryption', 'm.room.history_visibility'], - 'Other permissions': ['m.room.tombstone', 'm.room.pinned_events', 'm.room.server_acl', 'im.vector.modular.widgets'], -}; - -const spacePermsGroups = { - 'General Permissions': ['users_default', 'm.space.child'], - 'Manage members permissions': ['invite', 'kick', 'ban'], - 'Space profile permissions': ['m.room.avatar', 'm.room.name', 'm.room.topic'], - 'Settings permissions': ['state_default', 'm.room.canonical_alias', 'm.room.power_levels'], -}; - -function useRoomStateUpdate(roomId) { - const [, forceUpdate] = useForceUpdate(); - const mx = useMatrixClient(); - - useEffect(() => { - const handleStateEvent = (event) => { - if (event.getRoomId() !== roomId) return; - forceUpdate(); - }; - - mx.on('RoomState.events', handleStateEvent); - return () => { - mx.removeListener('RoomState.events', handleStateEvent); - }; - }, [mx, roomId]); -} - -function RoomPermissions({ roomId }) { - useRoomStateUpdate(roomId); - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - const pLEvent = getStateEvent(room, 'm.room.power_levels'); - const permissions = pLEvent.getContent(); - const canChangePermission = room.getLiveTimeline().getState(EventTimeline.FORWARDS)?.maySendStateEvent('m.room.power_levels', mx.getUserId()); - const myPowerLevel = room.getMember(mx.getUserId())?.powerLevel ?? 100; - - const handlePowerSelector = (e, permKey, parentKey, powerLevel) => { - const handlePowerLevelChange = (newPowerLevel) => { - if (powerLevel === newPowerLevel) return; - - const newPermissions = { ...permissions }; - if (parentKey) { - newPermissions[parentKey] = { - ...permissions[parentKey], - [permKey]: newPowerLevel, - }; - } else if (permKey === 'notifications') { - newPermissions[permKey] = { - ...permissions[permKey], - room: newPowerLevel, - }; - } else { - newPermissions[permKey] = newPowerLevel; - } - - mx.sendStateEvent(roomId, 'm.room.power_levels', newPermissions); - }; - - openReusableContextMenu( - 'bottom', - getEventCords(e, '.btn-surface'), - (closeMenu) => ( - { - closeMenu(); - handlePowerLevelChange(pl); - }} - /> - ), - ); - }; - - const permsGroups = room.isSpaceRoom() ? spacePermsGroups : roomPermsGroups; - return ( -
- { - Object.keys(permsGroups).map((groupKey) => { - const groupedPermKeys = permsGroups[groupKey]; - return ( -
- {groupKey} - { - groupedPermKeys.map((permKey) => { - const permInfo = permissionsInfo[permKey]; - - let powerLevel = 0; - let permValue = permInfo.parent - ? permissions[permInfo.parent]?.[permKey] - : permissions[permKey]; - - if (permValue === undefined) permValue = permInfo.default; - - if (typeof permValue === 'number') { - powerLevel = permValue; - } else if (permKey === 'notifications') { - powerLevel = permValue.room ?? 50; - } - return ( - {permInfo.description}} - options={( - - )} - /> - ); - }) - } -
- ); - }) - } -
- ); -} - -RoomPermissions.propTypes = { - roomId: PropTypes.string.isRequired, -}; - -export default RoomPermissions; diff --git a/src/app/molecules/room-permissions/RoomPermissions.scss b/src/app/molecules/room-permissions/RoomPermissions.scss deleted file mode 100644 index 81b22ca..0000000 --- a/src/app/molecules/room-permissions/RoomPermissions.scss +++ /dev/null @@ -1,11 +0,0 @@ -.room-permissions { - & .setting-tile { - margin: 0 var(--sp-normal); - margin-top: var(--sp-tight); - padding-bottom: var(--sp-tight); - border-bottom: 1px solid var(--bg-surface-border); - &:last-child { - border-bottom: none; - } - } -} \ No newline at end of file diff --git a/src/app/molecules/room-profile/RoomProfile.jsx b/src/app/molecules/room-profile/RoomProfile.jsx deleted file mode 100644 index da8ce75..0000000 --- a/src/app/molecules/room-profile/RoomProfile.jsx +++ /dev/null @@ -1,237 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import PropTypes from 'prop-types'; -import { useAtomValue } from 'jotai'; -import Linkify from 'linkify-react'; -import './RoomProfile.scss'; - -import cons from '../../../client/state/cons'; -import colorMXID from '../../../util/colorMXID'; - -import Text from '../../atoms/text/Text'; -import Avatar from '../../atoms/avatar/Avatar'; -import Button from '../../atoms/button/Button'; -import Input from '../../atoms/input/Input'; -import IconButton from '../../atoms/button/IconButton'; -import ImageUpload from '../image-upload/ImageUpload'; - -import PencilIC from '../../../../public/res/ic/outlined/pencil.svg'; - -import { useStore } from '../../hooks/useStore'; -import { useForceUpdate } from '../../hooks/useForceUpdate'; -import { confirmDialog } from '../confirm-dialog/ConfirmDialog'; -import { mDirectAtom } from '../../state/mDirectList'; -import { LINKIFY_OPTS } from '../../plugins/react-custom-html-parser'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; - -function RoomProfile({ roomId }) { - const isMountStore = useStore(); - const [isEditing, setIsEditing] = useState(false); - const [, forceUpdate] = useForceUpdate(); - const [status, setStatus] = useState({ - msg: null, - type: cons.status.PRE_FLIGHT, - }); - - const mx = useMatrixClient(); - const mDirects = useAtomValue(mDirectAtom); - const isDM = mDirects.has(roomId); - let avatarSrc = mx.getRoom(roomId).getAvatarUrl(mx.baseUrl, 36, 36, 'crop'); - avatarSrc = isDM - ? mx.getRoom(roomId).getAvatarFallbackMember()?.getAvatarUrl(mx.baseUrl, 36, 36, 'crop') - : avatarSrc; - const room = mx.getRoom(roomId); - const { currentState } = room; - const roomName = room.name; - const roomTopic = currentState.getStateEvents('m.room.topic')[0]?.getContent().topic; - - const userId = mx.getUserId(); - - const canChangeAvatar = currentState.maySendStateEvent('m.room.avatar', userId); - const canChangeName = currentState.maySendStateEvent('m.room.name', userId); - const canChangeTopic = currentState.maySendStateEvent('m.room.topic', userId); - - useEffect(() => { - isMountStore.setItem(true); - const handleStateEvent = (mEvent) => { - if (mEvent.event.room_id !== roomId) return; - forceUpdate(); - }; - - mx.on('RoomState.events', handleStateEvent); - return () => { - mx.removeListener('RoomState.events', handleStateEvent); - isMountStore.setItem(false); - setStatus({ - msg: null, - type: cons.status.PRE_FLIGHT, - }); - setIsEditing(false); - }; - }, [mx, roomId]); - - const handleOnSubmit = async (e) => { - e.preventDefault(); - const { target } = e; - const roomNameInput = target.elements['room-name']; - const roomTopicInput = target.elements['room-topic']; - - try { - if (canChangeName) { - const newName = roomNameInput.value; - if (newName !== roomName && roomName.trim() !== '') { - setStatus({ - msg: 'Saving room name...', - type: cons.status.IN_FLIGHT, - }); - await mx.setRoomName(roomId, newName); - } - } - if (canChangeTopic) { - const newTopic = roomTopicInput.value; - if (newTopic !== roomTopic) { - if (isMountStore.getItem()) { - setStatus({ - msg: 'Saving room topic...', - type: cons.status.IN_FLIGHT, - }); - } - await mx.setRoomTopic(roomId, newTopic); - } - } - if (!isMountStore.getItem()) return; - setStatus({ - msg: 'Saved successfully', - type: cons.status.SUCCESS, - }); - } catch (err) { - if (!isMountStore.getItem()) return; - setStatus({ - msg: err.message || 'Unable to save.', - type: cons.status.ERROR, - }); - } - }; - - const handleCancelEditing = () => { - setStatus({ - msg: null, - type: cons.status.PRE_FLIGHT, - }); - setIsEditing(false); - }; - - const handleAvatarUpload = async (url) => { - if (url === null) { - const isConfirmed = await confirmDialog( - 'Remove avatar', - 'Are you sure that you want to remove room avatar?', - 'Remove', - 'caution' - ); - if (isConfirmed) { - await mx.sendStateEvent(roomId, 'm.room.avatar', { url }, ''); - } - } else await mx.sendStateEvent(roomId, 'm.room.avatar', { url }, ''); - }; - - const renderEditNameAndTopic = () => ( -
- {canChangeName && ( - - )} - {canChangeTopic && ( - - )} - {(!canChangeName || !canChangeTopic) && ( - {`You have permission to change ${ - room.isSpaceRoom() ? 'space' : 'room' - } ${canChangeName ? 'name' : 'topic'} only.`} - )} - {status.type === cons.status.IN_FLIGHT && {status.msg}} - {status.type === cons.status.SUCCESS && ( - - {status.msg} - - )} - {status.type === cons.status.ERROR && ( - - {status.msg} - - )} - {status.type !== cons.status.IN_FLIGHT && ( -
- - -
- )} -
- ); - - const renderNameAndTopic = () => ( -
-
- - {roomName} - - {(canChangeName || canChangeTopic) && ( - setIsEditing(true)} - /> - )} -
- {room.getCanonicalAlias() || room.roomId} - {roomTopic && ( - - {roomTopic} - - )} -
- ); - - return ( -
-
- {!canChangeAvatar && ( - - )} - {canChangeAvatar && ( - handleAvatarUpload(null)} - /> - )} - {!isEditing && renderNameAndTopic()} - {isEditing && renderEditNameAndTopic()} -
-
- ); -} - -RoomProfile.propTypes = { - roomId: PropTypes.string.isRequired, -}; - -export default RoomProfile; diff --git a/src/app/molecules/room-profile/RoomProfile.scss b/src/app/molecules/room-profile/RoomProfile.scss deleted file mode 100644 index 43d7014..0000000 --- a/src/app/molecules/room-profile/RoomProfile.scss +++ /dev/null @@ -1,53 +0,0 @@ -@use '../../partials/flex'; -@use '../../partials/dir'; - -.room-profile { - - &__content { - @extend .cp-fx__row; - & .avatar-container { - min-width: var(--av-large); - } - } - - &__display { - align-self: flex-end; - @include dir.side(margin, var(--sp-loose), 0); - - & > div:first-child { - @extend .cp-fx__row--s-c; - & > .text { - @include dir.side(margin, 0, var(--sp-extra-tight)); - } - } - - & > *:not(:first-child) { - margin-top: var(--sp-ultra-tight); - white-space: pre-wrap; - word-break: break-word; - } - } - - &__edit-form { - @extend .cp-fx__item-one; - @include dir.side(margin, var(--sp-loose), 0); - - & .input-container { - margin-bottom: var(--sp-extra-tight); - } - - & > .text { - margin-bottom: var(--sp-tight); - } - - & > *:last-child { - @extend .cp-fx__item-one; - @extend .cp-fx__row; - margin-top: var(--sp-tight); - - .btn-primary { - @include dir.side(margin, 0, var(--sp-tight)); - } - } - } -} \ No newline at end of file diff --git a/src/app/molecules/room-visibility/RoomVisibility.jsx b/src/app/molecules/room-visibility/RoomVisibility.jsx deleted file mode 100644 index f9bb815..0000000 --- a/src/app/molecules/room-visibility/RoomVisibility.jsx +++ /dev/null @@ -1,122 +0,0 @@ -import React, { useState, useEffect, useCallback } from 'react'; -import PropTypes from 'prop-types'; -import './RoomVisibility.scss'; -import { EventTimeline } from 'matrix-js-sdk'; - -import Text from '../../atoms/text/Text'; -import RadioButton from '../../atoms/button/RadioButton'; -import { MenuItem } from '../../atoms/context-menu/ContextMenu'; - -import HashIC from '../../../../public/res/ic/outlined/hash.svg'; -import HashLockIC from '../../../../public/res/ic/outlined/hash-lock.svg'; -import HashGlobeIC from '../../../../public/res/ic/outlined/hash-globe.svg'; -import SpaceIC from '../../../../public/res/ic/outlined/space.svg'; -import SpaceLockIC from '../../../../public/res/ic/outlined/space-lock.svg'; -import SpaceGlobeIC from '../../../../public/res/ic/outlined/space-globe.svg'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; - -const visibility = { - INVITE: 'invite', - RESTRICTED: 'restricted', - PUBLIC: 'public', -}; - -function setJoinRule(mx, roomId, type) { - let allow; - if (type === visibility.RESTRICTED) { - const { currentState } = mx.getRoom(roomId); - const mEvent = currentState.getStateEvents('m.space.parent')[0]; - if (!mEvent) return Promise.resolve(undefined); - - allow = [{ - room_id: mEvent.getStateKey(), - type: 'm.room_membership', - }]; - } - - return mx.sendStateEvent( - roomId, - 'm.room.join_rules', - { - join_rule: type, - allow, - }, - ); -} - -function useVisibility(roomId) { - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - - const [activeType, setActiveType] = useState(room.getJoinRule()); - useEffect(() => { - setActiveType(room.getJoinRule()); - }, [room]); - - const setNotification = useCallback((item) => { - if (item.type === activeType.type) return; - setActiveType(item.type); - setJoinRule(mx, roomId, item.type); - }, [mx, activeType, roomId]); - - return [activeType, setNotification]; -} - -function RoomVisibility({ roomId }) { - const [activeType, setVisibility] = useVisibility(roomId); - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - const isSpace = room.isSpaceRoom(); - const { currentState } = room; - - const noSpaceParent = currentState.getStateEvents('m.space.parent').length === 0; - const mCreate = currentState.getStateEvents('m.room.create')[0]?.getContent(); - const roomVersion = Number(mCreate?.room_version ?? 0); - - const myPowerlevel = room.getMember(mx.getUserId())?.powerLevel || 0; - const canChange = room.getLiveTimeline().getState(EventTimeline.FORWARDS)?.hasSufficientPowerLevelFor('state_default', myPowerlevel); - - const items = [{ - iconSrc: isSpace ? SpaceLockIC : HashLockIC, - text: 'Private (invite only)', - type: visibility.INVITE, - unsupported: false, - }, { - iconSrc: isSpace ? SpaceIC : HashIC, - text: roomVersion < 8 ? 'Restricted (unsupported: required room upgrade)' : 'Restricted (space member can join)', - type: visibility.RESTRICTED, - unsupported: roomVersion < 8 || noSpaceParent, - }, { - iconSrc: isSpace ? SpaceGlobeIC : HashGlobeIC, - text: 'Public (anyone can join)', - type: visibility.PUBLIC, - unsupported: false, - }]; - - return ( -
- { - items.map((item) => ( - setVisibility(item)} - disabled={(!canChange || item.unsupported)} - > - - {item.text} - - - - )) - } -
- ); -} - -RoomVisibility.propTypes = { - roomId: PropTypes.string.isRequired, -}; - -export default RoomVisibility; diff --git a/src/app/molecules/room-visibility/RoomVisibility.scss b/src/app/molecules/room-visibility/RoomVisibility.scss deleted file mode 100644 index b3ad966..0000000 --- a/src/app/molecules/room-visibility/RoomVisibility.scss +++ /dev/null @@ -1,19 +0,0 @@ -@use '../../partials/flex'; -@use '../../partials/dir'; -@use '../../partials/text'; - -.room-visibility { - & .context-menu__item .text { - @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); - } - } -} \ No newline at end of file diff --git a/src/app/organisms/pw/Windows.jsx b/src/app/organisms/pw/Windows.jsx index b3fd0b3..77452d1 100644 --- a/src/app/organisms/pw/Windows.jsx +++ b/src/app/organisms/pw/Windows.jsx @@ -4,8 +4,6 @@ import cons from '../../../client/state/cons'; import navigation from '../../../client/state/navigation'; import InviteUser from '../invite-user/InviteUser'; -import SpaceSettings from '../space-settings/SpaceSettings'; -import RoomSettings from '../room/RoomSettings'; function Windows() { const [inviteUser, changeInviteUser] = useState({ @@ -30,16 +28,12 @@ function Windows() { }, []); return ( - <> - changeInviteUser({ isOpen: false, roomId: undefined })} - /> - - - + changeInviteUser({ isOpen: false, roomId: undefined })} + /> ); } diff --git a/src/app/organisms/room/RoomSettings.jsx b/src/app/organisms/room/RoomSettings.jsx deleted file mode 100644 index 69f977b..0000000 --- a/src/app/organisms/room/RoomSettings.jsx +++ /dev/null @@ -1,200 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import PropTypes from 'prop-types'; -import './RoomSettings.scss'; - -import cons from '../../../client/state/cons'; -import navigation from '../../../client/state/navigation'; - -import Text from '../../atoms/text/Text'; -import Tabs from '../../atoms/tabs/Tabs'; -import { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu'; -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 RoomEncryption from '../../molecules/room-encryption/RoomEncryption'; -import RoomPermissions from '../../molecules/room-permissions/RoomPermissions'; -import RoomMembers from '../../molecules/room-members/RoomMembers'; -import RoomEmojis from '../../molecules/room-emojis/RoomEmojis'; - -import UserIC from '../../../../public/res/ic/outlined/user.svg'; -import SettingsIC from '../../../../public/res/ic/outlined/settings.svg'; -import EmojiIC from '../../../../public/res/ic/outlined/emoji.svg'; -import ShieldUserIC from '../../../../public/res/ic/outlined/shield-user.svg'; -import LockIC from '../../../../public/res/ic/outlined/lock.svg'; -import LeaveArrowIC from '../../../../public/res/ic/outlined/leave-arrow.svg'; -import CrossIC from '../../../../public/res/ic/outlined/cross.svg'; - -import { confirmDialog } from '../../molecules/confirm-dialog/ConfirmDialog'; -import PopupWindow from '../../molecules/popup-window/PopupWindow'; -import IconButton from '../../atoms/button/IconButton'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; - -const tabText = { - GENERAL: 'General', - MEMBERS: 'Members', - EMOJIS: 'Emojis', - PERMISSIONS: 'Permissions', - SECURITY: 'Security', -}; - -const tabItems = [ - { - iconSrc: SettingsIC, - text: tabText.GENERAL, - disabled: false, - }, - { - iconSrc: UserIC, - text: tabText.MEMBERS, - disabled: false, - }, - { - iconSrc: EmojiIC, - text: tabText.EMOJIS, - disabled: false, - }, - { - iconSrc: ShieldUserIC, - text: tabText.PERMISSIONS, - disabled: false, - }, - { - iconSrc: LockIC, - text: tabText.SECURITY, - disabled: false, - }, -]; - -function GeneralSettings({ roomId }) { - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - - return ( - <> -
- Options - { - const isConfirmed = await confirmDialog( - 'Leave room', - `Are you sure that you want to leave "${room.name}" room?`, - 'Leave', - 'danger' - ); - if (!isConfirmed) return; - mx.leave(roomId); - }} - iconSrc={LeaveArrowIC} - > - Leave - -
-
- Notification (Changing this will only affect you) - -
-
- Room visibility (who can join) - -
-
- Room addresses - -
- - ); -} - -GeneralSettings.propTypes = { - roomId: PropTypes.string.isRequired, -}; - -function SecuritySettings({ roomId }) { - return ( - <> -
- Encryption - -
-
- Message history visibility - -
- - ); -} -SecuritySettings.propTypes = { - roomId: PropTypes.string.isRequired, -}; - -function useWindowToggle(setSelectedTab) { - const [window, setWindow] = useState(null); - - useEffect(() => { - const openRoomSettings = (roomId, tab) => { - setWindow({ roomId, tabText }); - const tabItem = tabItems.find((item) => item.text === tab); - if (tabItem) setSelectedTab(tabItem); - }; - navigation.on(cons.events.navigation.ROOM_SETTINGS_TOGGLED, openRoomSettings); - return () => { - navigation.removeListener(cons.events.navigation.ROOM_SETTINGS_TOGGLED, openRoomSettings); - }; - }, [setSelectedTab]); - - const requestClose = () => setWindow(null); - - return [window, requestClose]; -} - -function RoomSettings() { - const [selectedTab, setSelectedTab] = useState(tabItems[0]); - const [window, requestClose] = useWindowToggle(setSelectedTab); - const isOpen = window !== null; - const roomId = window?.roomId; - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - - const handleTabChange = (tabItem) => { - setSelectedTab(tabItem); - }; - - return ( - - {isOpen && room.name} - — room settings - - } - contentOptions={} - onRequestClose={requestClose} - > - {isOpen && ( -
- - tab.text === selectedTab.text)} - onSelect={handleTabChange} - /> -
- {selectedTab.text === tabText.GENERAL && } - {selectedTab.text === tabText.MEMBERS && } - {selectedTab.text === tabText.EMOJIS && } - {selectedTab.text === tabText.PERMISSIONS && } - {selectedTab.text === tabText.SECURITY && } -
-
- )} -
- ); -} - -export default RoomSettings; -export { tabText }; diff --git a/src/app/organisms/room/RoomSettings.scss b/src/app/organisms/room/RoomSettings.scss deleted file mode 100644 index fd3af50..0000000 --- a/src/app/organisms/room/RoomSettings.scss +++ /dev/null @@ -1,40 +0,0 @@ -@use '../../partials/dir'; -@use '../../partials/flex'; - -.room-settings { - & .pw { - background-color: var(--bg-surface-low); - } - - & .room-profile { - padding: var(--sp-loose) var(--sp-extra-loose); - } - - & .tabs__content { - padding: 0 var(--sp-normal); - } - - &__cards-wrapper { - padding: 0 var(--sp-normal); - @include dir.side(padding, var(--sp-normal), var(--sp-extra-tight)); - } -} - -.room-settings__card { - margin: var(--sp-normal) 0; - background-color: var(--bg-surface); - border-radius: var(--bo-radius); - box-shadow: var(--bs-surface-border); - overflow: hidden; - - & > .context-menu__header:first-child { - margin-top: 2px; - } -} - -.room-settings .room-permissions__card, -.room-settings .room-search__form, -.room-settings .room-search__result-item, -.room-settings .room-members { - @extend .room-settings__card; -} diff --git a/src/app/organisms/space-settings/SpaceSettings.jsx b/src/app/organisms/space-settings/SpaceSettings.jsx deleted file mode 100644 index 9f2069d..0000000 --- a/src/app/organisms/space-settings/SpaceSettings.jsx +++ /dev/null @@ -1,166 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import PropTypes from 'prop-types'; -import './SpaceSettings.scss'; - -import cons from '../../../client/state/cons'; -import navigation from '../../../client/state/navigation'; - -import Text from '../../atoms/text/Text'; -import IconButton from '../../atoms/button/IconButton'; -import Tabs from '../../atoms/tabs/Tabs'; -import { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu'; -import PopupWindow from '../../molecules/popup-window/PopupWindow'; -import RoomProfile from '../../molecules/room-profile/RoomProfile'; -import RoomVisibility from '../../molecules/room-visibility/RoomVisibility'; -import RoomAliases from '../../molecules/room-aliases/RoomAliases'; -import RoomPermissions from '../../molecules/room-permissions/RoomPermissions'; -import RoomMembers from '../../molecules/room-members/RoomMembers'; -import RoomEmojis from '../../molecules/room-emojis/RoomEmojis'; - -import UserIC from '../../../../public/res/ic/outlined/user.svg'; -import CrossIC from '../../../../public/res/ic/outlined/cross.svg'; -import SettingsIC from '../../../../public/res/ic/outlined/settings.svg'; -import ShieldUserIC from '../../../../public/res/ic/outlined/shield-user.svg'; -import LeaveArrowIC from '../../../../public/res/ic/outlined/leave-arrow.svg'; -import EmojiIC from '../../../../public/res/ic/outlined/emoji.svg'; - -import { confirmDialog } from '../../molecules/confirm-dialog/ConfirmDialog'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; - -const tabText = { - GENERAL: 'General', - MEMBERS: 'Members', - EMOJIS: 'Emojis', - PERMISSIONS: 'Permissions', -}; - -const tabItems = [ - { - iconSrc: SettingsIC, - text: tabText.GENERAL, - disabled: false, - }, - { - iconSrc: UserIC, - text: tabText.MEMBERS, - disabled: false, - }, - { - iconSrc: EmojiIC, - text: tabText.EMOJIS, - disabled: false, - }, - { - iconSrc: ShieldUserIC, - text: tabText.PERMISSIONS, - disabled: false, - }, -]; - -function GeneralSettings({ roomId }) { - const mx = useMatrixClient(); - const roomName = mx.getRoom(roomId)?.name; - - return ( - <> -
- Options - { - const isConfirmed = await confirmDialog( - 'Leave space', - `Are you sure that you want to leave "${roomName}" space?`, - 'Leave', - 'danger' - ); - if (isConfirmed) mx.leave(roomId); - }} - iconSrc={LeaveArrowIC} - > - Leave - -
-
- Space visibility (who can join) - -
-
- Space addresses - -
- - ); -} - -GeneralSettings.propTypes = { - roomId: PropTypes.string.isRequired, -}; - -function useWindowToggle(setSelectedTab) { - const [window, setWindow] = useState(null); - - useEffect(() => { - const openSpaceSettings = (roomId, tab) => { - setWindow({ roomId, tabText }); - const tabItem = tabItems.find((item) => item.text === tab); - if (tabItem) setSelectedTab(tabItem); - }; - navigation.on(cons.events.navigation.SPACE_SETTINGS_OPENED, openSpaceSettings); - return () => { - navigation.removeListener(cons.events.navigation.SPACE_SETTINGS_OPENED, openSpaceSettings); - }; - }, []); - - const requestClose = () => setWindow(null); - - return [window, requestClose]; -} - -function SpaceSettings() { - const [selectedTab, setSelectedTab] = useState(tabItems[0]); - const [window, requestClose] = useWindowToggle(setSelectedTab); - const isOpen = window !== null; - const roomId = window?.roomId; - - const mx = useMatrixClient(); - const room = mx.getRoom(roomId); - - const handleTabChange = (tabItem) => { - setSelectedTab(tabItem); - }; - - return ( - - {isOpen && room.name} - — space settings - - } - contentOptions={} - onRequestClose={requestClose} - > - {isOpen && ( -
- - tab.text === selectedTab.text)} - onSelect={handleTabChange} - /> -
- {selectedTab.text === tabText.GENERAL && } - {selectedTab.text === tabText.MEMBERS && } - {selectedTab.text === tabText.EMOJIS && } - {selectedTab.text === tabText.PERMISSIONS && } -
-
- )} -
- ); -} - -export default SpaceSettings; diff --git a/src/app/organisms/space-settings/SpaceSettings.scss b/src/app/organisms/space-settings/SpaceSettings.scss deleted file mode 100644 index 987f23b..0000000 --- a/src/app/organisms/space-settings/SpaceSettings.scss +++ /dev/null @@ -1,37 +0,0 @@ -@use '../../partials/dir.scss'; - -.space-settings { - & .pw { - background-color: var(--bg-surface-low); - } - - & .room-profile { - padding: var(--sp-loose) var(--sp-extra-loose); - } - - & .tabs__content { - padding: 0 var(--sp-normal); - } - - &__cards-wrapper { - padding: 0 var(--sp-normal); - @include dir.side(padding, var(--sp-normal), var(--sp-extra-tight)); - } -} - -.space-settings__card { - margin: var(--sp-normal) 0; - background-color: var(--bg-surface); - border-radius: var(--bo-radius); - box-shadow: var(--bs-surface-border); - overflow: hidden; - - & > .context-menu__header:first-child { - margin-top: 2px; - } -} - -.space-settings .room-permissions__card, -.space-settings .room-members { - @extend .space-settings__card; -} \ No newline at end of file diff --git a/src/client/action/navigation.js b/src/client/action/navigation.js index 3e6339d..b7c5ae3 100644 --- a/src/client/action/navigation.js +++ b/src/client/action/navigation.js @@ -1,13 +1,6 @@ import appDispatcher from '../dispatcher'; import cons from '../state/cons'; -export function openSpaceSettings(roomId, tabText) { - appDispatcher.dispatch({ - type: cons.actions.navigation.OPEN_SPACE_SETTINGS, - roomId, - tabText, - }); -} export function openSpaceAddExisting(roomId, spaces = false) { appDispatcher.dispatch({ @@ -17,14 +10,6 @@ export function openSpaceAddExisting(roomId, spaces = false) { }); } -export function toggleRoomSettings(roomId, tabText) { - appDispatcher.dispatch({ - type: cons.actions.navigation.TOGGLE_ROOM_SETTINGS, - roomId, - tabText - }); -} - export function openCreateRoom(isSpace = false, parentId = null) { appDispatcher.dispatch({ diff --git a/src/client/state/cons.js b/src/client/state/cons.js index d214ebb..7f31695 100644 --- a/src/client/state/cons.js +++ b/src/client/state/cons.js @@ -6,22 +6,6 @@ const cons = { USER_ID: 'cinny_user_id', BASE_URL: 'cinny_hs_base_url', }, - DEVICE_DISPLAY_NAME: 'Cinny Web', - IN_CINNY_SPACES: 'in.cinny.spaces', - supportEventTypes: [ - 'm.room.create', - 'm.room.message', - 'm.room.encrypted', - 'm.room.member', - 'm.sticker', - ], - supportReceiptTypes: ['m.read', 'm.read.private'], - notifs: { - DEFAULT: 'default', - ALL_MESSAGES: 'all_messages', - MENTIONS_AND_KEYWORDS: 'mentions_and_keywords', - MUTE: 'mute', - }, status: { PRE_FLIGHT: 'pre-flight', IN_FLIGHT: 'in-flight', @@ -30,9 +14,7 @@ const cons = { }, actions: { navigation: { - OPEN_SPACE_SETTINGS: 'OPEN_SPACE_SETTINGS', OPEN_SPACE_ADDEXISTING: 'OPEN_SPACE_ADDEXISTING', - TOGGLE_ROOM_SETTINGS: 'TOGGLE_ROOM_SETTINGS', OPEN_CREATE_ROOM: 'OPEN_CREATE_ROOM', OPEN_JOIN_ALIAS: 'OPEN_JOIN_ALIAS', OPEN_INVITE_USER: 'OPEN_INVITE_USER', @@ -44,9 +26,7 @@ const cons = { }, events: { navigation: { - SPACE_SETTINGS_OPENED: 'SPACE_SETTINGS_OPENED', SPACE_ADDEXISTING_OPENED: 'SPACE_ADDEXISTING_OPENED', - ROOM_SETTINGS_TOGGLED: 'ROOM_SETTINGS_TOGGLED', CREATE_ROOM_OPENED: 'CREATE_ROOM_OPENED', JOIN_ALIAS_OPENED: 'JOIN_ALIAS_OPENED', INVITE_USER_OPENED: 'INVITE_USER_OPENED', diff --git a/src/client/state/navigation.js b/src/client/state/navigation.js index 1228d9c..743d019 100644 --- a/src/client/state/navigation.js +++ b/src/client/state/navigation.js @@ -19,19 +19,9 @@ class Navigation extends EventEmitter { navigate(action) { const actions = { - [cons.actions.navigation.OPEN_SPACE_SETTINGS]: () => { - this.emit(cons.events.navigation.SPACE_SETTINGS_OPENED, action.roomId, action.tabText); - }, [cons.actions.navigation.OPEN_SPACE_ADDEXISTING]: () => { this.emit(cons.events.navigation.SPACE_ADDEXISTING_OPENED, action.roomId, action.spaces); }, - [cons.actions.navigation.TOGGLE_ROOM_SETTINGS]: () => { - this.emit( - cons.events.navigation.ROOM_SETTINGS_TOGGLED, - action.roomId, - action.tabText - ); - }, [cons.actions.navigation.OPEN_CREATE_ROOM]: () => { this.emit( cons.events.navigation.CREATE_ROOM_OPENED,