From 6c7806087600349621af98a6fc1df7fb814990db Mon Sep 17 00:00:00 2001 From: jamesjulich <51384945+jamesjulich@users.noreply.github.com> Date: Thu, 9 Sep 2021 00:47:26 -0500 Subject: [PATCH] Add profile editor in settings --- public/res/svg/avatar-clip.svg | 3 + src/app/atoms/image-upload/ImageUpload.jsx | 62 +++++++++++++++++ src/app/atoms/image-upload/ImageUpload.scss | 20 ++++++ .../profile-editor/ProfileEditor.jsx | 66 +++++++++++++++++++ .../profile-editor/ProfileEditor.scss | 24 +++++++ src/app/organisms/settings/Settings.jsx | 21 ++++++ 6 files changed, 196 insertions(+) create mode 100644 public/res/svg/avatar-clip.svg create mode 100644 src/app/atoms/image-upload/ImageUpload.jsx create mode 100644 src/app/atoms/image-upload/ImageUpload.scss create mode 100644 src/app/molecules/profile-editor/ProfileEditor.jsx create mode 100644 src/app/molecules/profile-editor/ProfileEditor.scss diff --git a/public/res/svg/avatar-clip.svg b/public/res/svg/avatar-clip.svg new file mode 100644 index 0000000..ffaa1a2 --- /dev/null +++ b/public/res/svg/avatar-clip.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/app/atoms/image-upload/ImageUpload.jsx b/src/app/atoms/image-upload/ImageUpload.jsx new file mode 100644 index 0000000..1393052 --- /dev/null +++ b/src/app/atoms/image-upload/ImageUpload.jsx @@ -0,0 +1,62 @@ +import React, { useRef } from 'react'; +import PropTypes from 'prop-types'; + +import initMatrix from '../../../client/initMatrix'; + +import GenIC from '../../../../public/res/ic/outlined/settings.svg'; +import Avatar from '../avatar/Avatar'; + +import RawIcon from '../system-icons/RawIcon'; +import './ImageUpload.scss'; + +function ImageUpload({ + text, bgColor, imageSrc, onUpload, +}) { + const uploadImageRef = useRef(null); + + function uploadImage(e) { + const file = e.target.files.item(0); + if (file !== null) { // TODO Add upload progress spinner + initMatrix.matrixClient.uploadContent(file, { onlyContentUri: false }).then((res) => { + if (res.content_uri !== null) { + onUpload({ content_uri: res.content_uri }); + } + }, (err) => { + console.log(err); // TODO Replace with alert banner. + }); + } + } + + return ( + + ); +} + +ImageUpload.defaultProps = { + text: null, + bgColor: 'transparent', + imageSrc: null, + onUpload: null, +}; + +ImageUpload.propTypes = { + text: PropTypes.string, + bgColor: PropTypes.string, + imageSrc: PropTypes.string, + onUpload: PropTypes.func, +}; + +export default ImageUpload; diff --git a/src/app/atoms/image-upload/ImageUpload.scss b/src/app/atoms/image-upload/ImageUpload.scss new file mode 100644 index 0000000..c7118ba --- /dev/null +++ b/src/app/atoms/image-upload/ImageUpload.scss @@ -0,0 +1,20 @@ +.img-upload-container { + display: flex; + flex-direction: row-reverse; + width: 80px; + height: 80px; +} + +.img-upload-container:hover { + cursor: pointer; +} + +.img-upload-mask { + mask: url('../../../../public/res/svg/avatar-clip.svg'); + //width: 80px; +} + +.img-upload-icon { + z-index: 1; + position: absolute; +} \ No newline at end of file diff --git a/src/app/molecules/profile-editor/ProfileEditor.jsx b/src/app/molecules/profile-editor/ProfileEditor.jsx new file mode 100644 index 0000000..818ed93 --- /dev/null +++ b/src/app/molecules/profile-editor/ProfileEditor.jsx @@ -0,0 +1,66 @@ +import React, { useState, useRef } from 'react'; +import PropTypes from 'prop-types'; + +import initMatrix from '../../../client/initMatrix'; +import colorMXID from '../../../util/colorMXID'; + +import Button from '../../atoms/button/Button'; +import ImageUpload from '../../atoms/image-upload/ImageUpload'; +import Input from '../../atoms/input/Input'; +import Text from '../../atoms/text/Text'; + +import './ProfileEditor.scss'; + +// TODO Fix bug that prevents 'Save' button from enabling up until second changed. +function ProfileEditor({ + userId, +}) { + const mx = initMatrix.matrixClient; + const displayNameRef = useRef(null); + const bgColor = colorMXID(userId); + const [imageSrc, updateImgSrc] = useState(mx.mxcUrlToHttp(mx.getUser(mx.getUserId()).avatarUrl)); + const [disabled, setDisabled] = useState(true); + + let username = mx.getUser(mx.getUserId()).displayName; + + function handleUpload(e) { + mx.setAvatarUrl(e.content_uri); + updateImgSrc(mx.mxcUrlToHttp(e.content_uri)); + } + + function saveDisplayName() { + if (displayNameRef.current.value !== null && displayNameRef.current.value !== '') { + mx.setDisplayName(displayNameRef.current.value); + username = displayNameRef.current.value; + setDisabled(true); + } + } + + function onDisplayNameInputChange() { + setDisabled((username === displayNameRef.current.value) || displayNameRef.current.value === '' || displayNameRef.current.value == null); + } + + return ( +
+ +
+ + Display name of  + {mx.getUserId()} + + +
+ + + ); +} + +ProfileEditor.defaultProps = { + userId: null, +}; + +ProfileEditor.propTypes = { + userId: PropTypes.string, +}; + +export default ProfileEditor; diff --git a/src/app/molecules/profile-editor/ProfileEditor.scss b/src/app/molecules/profile-editor/ProfileEditor.scss new file mode 100644 index 0000000..98a453a --- /dev/null +++ b/src/app/molecules/profile-editor/ProfileEditor.scss @@ -0,0 +1,24 @@ +.profile-editor { + display: flex; + align-items: end; +} + +.img-upload-container { + margin-right: var(--sp-normal) +} + +.display-name-input-container { + display: flex; + flex-direction: column; + margin-right: var(--sp-normal); + width: 100%; + max-width: 400px; +} + +.display-name-input-container > .text-b3 { + margin-bottom: var(--sp-ultra-tight) +} + +.profile-editor > .btn-primary { + height: 46px; +} \ No newline at end of file diff --git a/src/app/organisms/settings/Settings.jsx b/src/app/organisms/settings/Settings.jsx index 8914640..91be164 100644 --- a/src/app/organisms/settings/Settings.jsx +++ b/src/app/organisms/settings/Settings.jsx @@ -14,8 +14,10 @@ import SegmentedControls from '../../atoms/segmented-controls/SegmentedControls' import PopupWindow, { PWContentSelector } from '../../molecules/popup-window/PopupWindow'; import SettingTile from '../../molecules/setting-tile/SettingTile'; +import ProfileEditor from '../../molecules/profile-editor/ProfileEditor'; import ImportE2ERoomKeys from '../../molecules/import-e2e-room-keys/ImportE2ERoomKeys'; +import GenIC from '../../../../public/res/ic/outlined/settings.svg'; import SunIC from '../../../../public/res/ic/outlined/sun.svg'; import LockIC from '../../../../public/res/ic/outlined/lock.svg'; import InfoIC from '../../../../public/res/ic/outlined/info.svg'; @@ -23,6 +25,19 @@ import CrossIC from '../../../../public/res/ic/outlined/cross.svg'; import CinnySVG from '../../../../public/res/svg/cinny.svg'; +function GeneralSection() { + return ( +
+ + )} + /> +
+ ); +} + function AppearanceSection() { const [, updateState] = useState({}); @@ -104,6 +119,12 @@ function AboutSection() { function Settings({ isOpen, onRequestClose }) { const settingSections = [{ + name: 'General', + iconSrc: GenIC, + render() { + return ; + }, + }, { name: 'Appearance', iconSrc: SunIC, render() {