From ccd127de44f267bde9286e195919ba135bc4a823 Mon Sep 17 00:00:00 2001 From: William Grant Date: Wed, 14 Feb 2024 18:12:06 +1100 Subject: [PATCH] feat: starting work on new input added into test region of right panel --- .../overlay/OverlayRightPanelSettings.tsx | 53 +++++- ts/components/inputs/SessionInput2.tsx | 173 ++++++++++++++++++ ts/components/inputs/index.tsx | 3 + 3 files changed, 220 insertions(+), 9 deletions(-) create mode 100644 ts/components/inputs/SessionInput2.tsx create mode 100644 ts/components/inputs/index.tsx diff --git a/ts/components/conversation/right-panel/overlay/OverlayRightPanelSettings.tsx b/ts/components/conversation/right-panel/overlay/OverlayRightPanelSettings.tsx index b37a1054b..25ac3ea17 100644 --- a/ts/components/conversation/right-panel/overlay/OverlayRightPanelSettings.tsx +++ b/ts/components/conversation/right-panel/overlay/OverlayRightPanelSettings.tsx @@ -15,16 +15,15 @@ import { useIsRightPanelShowing } from '../../../../hooks/useUI'; import { ConversationInteractionStatus, ConversationInteractionType, - showAddModeratorsByConvoId, showInviteContactByConvoId, showLeaveGroupByConvoId, - showRemoveModeratorsByConvoId, - showUpdateGroupMembersByConvoId, - showUpdateGroupNameByConvoId, } from '../../../../interactions/conversationInteractions'; import { Constants } from '../../../../session'; +import { MAX_USERNAME_BYTES } from '../../../../session/constants'; +import { ToastUtils } from '../../../../session/utils'; +import { sanitizeSessionUsername } from '../../../../session/utils/String'; import { closeRightPanel } from '../../../../state/ducks/conversations'; -import { resetRightOverlayMode, setRightOverlayMode } from '../../../../state/ducks/section'; +import { resetRightOverlayMode } from '../../../../state/ducks/section'; import { useSelectedConversationKey, useSelectedDisplayNameInProfile, @@ -43,10 +42,9 @@ import { getAbsoluteAttachmentPath } from '../../../../types/MessageAttachment'; import { Avatar, AvatarSize } from '../../../avatar/Avatar'; import { Flex } from '../../../basic/Flex'; import { SpacerLG, SpacerMD, SpacerXL } from '../../../basic/Text'; -import { PanelButtonGroup, PanelIconButton } from '../../../buttons'; +import { SessionInput2 } from '../../../inputs'; import { MediaItemType } from '../../../lightbox/LightboxGallery'; import { SessionProgressBar } from '../../../loading'; -import { MediaGallery } from '../../media-gallery/MediaGallery'; import { Header, StyledScrollContainer } from './components'; async function getMediaGalleryProps( @@ -214,6 +212,33 @@ export const OverlayRightPanelSettings = () => { // TODO[epic=ses-50] move this into already have an account screen // #region for testing const [progress, setProgress] = useState(0); + const [inputValue, setInputValue] = useState(''); + const [inputError, setInputError] = useState(undefined); + + function sanitizeDisplayNameOrToast( + displayName: string, + setDisplayName: (sanitized: string) => void, + setDisplayNameError: (error: string | undefined) => void + ) { + try { + const sanitizedName = sanitizeSessionUsername(displayName); + const trimName = sanitizedName.trim(); + setDisplayName(sanitizedName); + setDisplayNameError(!trimName ? window.i18n('displayNameEmpty') : undefined); + } catch (e) { + setDisplayName(displayName); + setDisplayNameError(window.i18n('displayNameTooLong')); + ToastUtils.pushToastError('toolong', window.i18n('displayNameTooLong')); + } + } + + const handleInputChanged = (name: string) => { + sanitizeDisplayNameOrToast(name, setInputValue, setInputError); + }; + + const handleEnterPressed = () => { + ToastUtils.pushToastSuccess('success', window.i18n('done')); + }; useEffect(() => { const interval = setInterval(() => { @@ -308,7 +333,17 @@ export const OverlayRightPanelSettings = () => { subtitle={window.i18n('loadAccountProgressMessage')} showPercentage={true} /> - + + + {/* {showUpdateGroupNameButton && ( { iconType={'delete'} /> )} - + */} diff --git a/ts/components/inputs/SessionInput2.tsx b/ts/components/inputs/SessionInput2.tsx new file mode 100644 index 000000000..f8adb44ef --- /dev/null +++ b/ts/components/inputs/SessionInput2.tsx @@ -0,0 +1,173 @@ +import { ChangeEvent, useState } from 'react'; + +import classNames from 'classnames'; +import styled from 'styled-components'; +import { Noop } from '../../types/Util'; +import { useHTMLDirection } from '../../util/i18n'; +import { SessionIconButton } from '../icon'; + +type Props = { + label?: string; + error?: string; + type?: string; + value?: string; + placeholder: string; + maxLength?: number; + enableShowHide?: boolean; + onValueChanged?: (value: string) => any; + onEnterPressed?: any; + autoFocus?: boolean; + ref?: any; + inputDataTestId?: string; +}; + +const StyledInputWithLabelContainer = styled.label` + height: 46.5px; + width: 280px; + font-family: var(--font-default); + color: var(--text-primary-color); + + padding: 2px 0 2px 0; + transition: opacity var(--default-duration); + opacity: 1; + position: relative; + + label { + line-height: 14px; + opacity: 0; + color: var(--text-primary-color); + + font-size: 10px; + line-height: 11px; + position: absolute; + top: 0px; + } + + &.filled { + opacity: 1; + } + + &.error { + color: var(--danger-color); + } + + input { + border: none; + outline: 0; + height: 14px; + width: 280px; + background: transparent; + color: var(--input-text-color); + + font-family: var(--font-default); + font-size: 12px; + line-height: 14px; + position: absolute; + top: 50%; + transform: translateY(-50%); + + &::placeholder { + color: var(--input-text-placeholder-color); + } + } +`; + +const LabelItem = (props: { inputValue: string; label?: string }) => { + return ( + + {props.label} + + ); +}; + +const ErrorItem = (props: { error: string | undefined }) => { + return ( + + {props.error} + + ); +}; + +const ShowHideButton = (props: { toggleForceShow: Noop }) => { + const htmlDirection = useHTMLDirection(); + const position = htmlDirection === 'ltr' ? { right: '0px' } : { left: '0px' }; + + return ( + + ); +}; + +export const SessionInput2 = (props: Props) => { + const { + autoFocus, + placeholder, + type, + value, + maxLength, + enableShowHide, + error, + label, + onValueChanged, + inputDataTestId, + } = props; + const [inputValue, setInputValue] = useState(''); + const [forceShow, setForceShow] = useState(false); + + const correctType = forceShow ? 'text' : type; + + const updateInputValue = (e: ChangeEvent) => { + e.preventDefault(); + const val = e.target.value; + setInputValue(val); + if (onValueChanged) { + onValueChanged(val); + } + }; + + return ( + + {error ? ( + + ) : ( + + )} + { + if (event.key === 'Enter' && props.onEnterPressed) { + props.onEnterPressed(); + } + }} + /> + + {enableShowHide && ( + { + setForceShow(!forceShow); + }} + /> + )} + + ); +}; diff --git a/ts/components/inputs/index.tsx b/ts/components/inputs/index.tsx new file mode 100644 index 000000000..b767c89c6 --- /dev/null +++ b/ts/components/inputs/index.tsx @@ -0,0 +1,3 @@ +import { SessionInput2 } from './SessionInput2'; + +export { SessionInput2 };