feat: added monospace textarea support to sessioninput

this will replace the sessionideditable eventually still needs error handling etc
pull/3083/head
William Grant 1 year ago
parent e96519445d
commit 30118c3426

@ -3,7 +3,7 @@
"accept": "Accept",
"accountIDCopy": "Copy Account ID",
"accountIdEnter": "Enter Account ID",
"accountIdEnterYourFriends": "Enter your friend's Account ID or ONS",
"accountIdOrOnsEnter": "Enter Account ID or ONS",
"accountIdYours": "Your Account ID",
"accountIdErrorInvalid": "This Account ID is invalid. Please check and try again.",
"activeMembers": "$count$ active members",

@ -30,13 +30,14 @@ const StyledInputContainer = styled(Flex)<{ error: boolean }>`
}
}
input::placeholder {
input::placeholder,
textarea::placeholder {
transition: opacity var(--default-duration) color var(--default-duration);
${props => props.error && `color: var(--danger-color); opacity: 1;`}
}
`;
const StyledInput = styled(motion.input)`
const StyledInput = styled(motion.input)<{ centerText?: boolean }>`
border: 1px solid var(--input-border-color);
border-radius: 13px;
outline: 0;
@ -48,9 +49,57 @@ const StyledInput = styled(motion.input)`
font-size: 12px;
line-height: 14px;
padding: var(--margins-lg);
${props => props.centerText && 'text-align: center;'}
::placeholder {
color: var(--input-text-placeholder-color);
${props => props.centerText && 'text-align: center;'}
}
`;
const StyledTextAreaContainer = styled(motion.div)<{ centerText?: boolean }>`
border: 1px solid var(--input-border-color);
border-radius: 13px;
outline: 0;
width: 100%;
background: transparent;
color: var(--input-text-color);
font-family: var(--font-mono);
font-size: var(--font-size-md);
min-height: 100px;
line-height: 18px;
${props => props.centerText && 'text-align: center;'}
textarea {
width: 100%;
outline: 0;
border: none;
background: transparent;
resize: none;
overflow: hidden;
overflow-wrap: break-word;
user-select: all;
display: inline-block;
padding: var(--margins-lg);
margin: var(--margins-xs) 0;
${props => props.centerText && 'text-align: center;'}
:placeholder-shown {
font-family: var(--font-default);
height: 28px;
margin: var(--margins-md) 0;
padding: var(--margins-xl);
}
::placeholder {
color: var(--input-text-placeholder-color);
${props => props.centerText && 'text-align: center;'}
}
}
`;
@ -123,6 +172,9 @@ type Props = {
inputDataTestId?: string;
id?: string;
ctaButton?: ReactNode;
/** Gives us a textarea with a monospace font. Mostly used for joining conversations, groups or communities */
isSpecial?: boolean;
centerText?: boolean;
};
export const SessionInput = (props: Props) => {
@ -140,6 +192,8 @@ export const SessionInput = (props: Props) => {
inputDataTestId,
id = 'session-input-floating-label',
ctaButton,
isSpecial,
centerText,
} = props;
const [inputValue, setInputValue] = useState('');
const [errorString, setErrorString] = useState('');
@ -156,6 +210,38 @@ export const SessionInput = (props: Props) => {
}
};
// TODO[epic=893] Type inputProps properly
const inputProps: any = {
id,
type: correctType,
placeholder,
value,
maxLength,
autoFocus,
'data-testid': inputDataTestId,
onChange: updateInputValue,
style: { paddingInlineEnd: enableShowHide ? '48px' : undefined },
// just in case onChange isn't triggered
onBlur: (event: ChangeEvent<HTMLInputElement>) => {
if (!disabledOnBlur) {
updateInputValue(event);
}
},
onKeyDown: (event: KeyboardEvent) => {
if (event.key === 'Enter' && onEnterPressed) {
onEnterPressed(inputValue);
setErrorString('');
}
},
initial: {
borderColor: errorString ? 'var(--input-border-color)' : undefined,
},
animate: {
borderColor: errorString ? 'var(--danger-color)' : undefined,
},
transition: { duration: THEME_GLOBALS['--default-duration-seconds'] },
};
// if we have an error, we want to show it even if the input changes to a valid value
useEffect(() => {
if (error && !isEmpty(error) && !isEqual(error, errorString)) {
@ -172,36 +258,13 @@ export const SessionInput = (props: Props) => {
error={Boolean(errorString)}
>
<Flex container={true} width="100%" alignItems="center" style={{ position: 'relative' }}>
<StyledInput
id={id}
type={correctType}
placeholder={placeholder}
value={value}
maxLength={maxLength}
autoFocus={autoFocus}
data-testid={inputDataTestId}
onChange={updateInputValue}
style={{ paddingInlineEnd: enableShowHide ? '48px' : undefined }}
// just in case onChange isn't triggered
onBlur={(event: ChangeEvent<HTMLInputElement>) => {
if (!disabledOnBlur) {
updateInputValue(event);
}
}}
onKeyDown={event => {
if (event.key === 'Enter' && onEnterPressed) {
onEnterPressed(inputValue);
setErrorString('');
}
}}
initial={{
borderColor: errorString ? 'var(--input-border-color)' : undefined,
}}
animate={{
borderColor: errorString ? 'var(--danger-color)' : undefined,
}}
transition={{ duration: THEME_GLOBALS['--default-duration-seconds'] }}
/>
{isSpecial ? (
<StyledTextAreaContainer centerText={centerText}>
<textarea {...inputProps} />
</StyledTextAreaContainer>
) : (
<StyledInput {...inputProps} centerText={centerText} />
)}
{enableShowHide && (
<ShowHideButton
forceShow={forceShow}

@ -10,14 +10,14 @@ import { ToastUtils, UserUtils } from '../../../session/utils';
import { openConversationWithMessages } from '../../../state/ducks/conversations';
import { resetLeftOverlayMode } from '../../../state/ducks/section';
import { SessionButton } from '../../basic/SessionButton';
import { SessionIdEditable } from '../../basic/SessionIdEditable';
import { SessionSpinner } from '../../loading';
import { ONSResolve } from '../../../session/apis/snode_api/onsResolve';
import { Flex } from '../../basic/Flex';
import { SpacerMD } from '../../basic/Text';
import { SpacerLG, SpacerMD } from '../../basic/Text';
import { YourSessionIDPill, YourSessionIDSelectable } from '../../basic/YourSessionIDPill';
import { SessionIconButton } from '../../icon';
import { SessionInput } from '../../inputs';
const SessionIDDescription = styled.div`
color: var(--text-secondary-color);
@ -49,7 +49,7 @@ export const OverlayMessage = () => {
const [loading, setLoading] = useState(false);
const buttonText = window.i18n('next');
const placeholder = window.i18n('accountIdEnterYourFriends');
const placeholder = window.i18n('accountIdOrOnsEnter');
const disableNextButton = !pubkeyOrOns || loading;
@ -111,13 +111,29 @@ export const OverlayMessage = () => {
return (
<div className="module-left-pane-overlay">
<SessionIdEditable
{/* TODO[epic=893] Replace everywhere and test new error handling */}
{/* <SessionIdEditable
editable={!loading}
placeholder={placeholder}
onChange={setPubkeyOrOns}
dataTestId="new-session-conversation"
onPressEnter={handleMessageButtonClick}
/> */}
<div style={{ width: '90%', margin: '0 auto' }}>
<SessionInput
autoFocus={true}
type="text"
placeholder={placeholder}
value={pubkeyOrOns}
onValueChanged={setPubkeyOrOns}
onEnterPressed={handleMessageButtonClick}
inputDataTestId="new-session-conversation"
isSpecial={true}
centerText={true}
/>
</div>
<SpacerLG />
<SessionSpinner loading={loading} />

@ -3,8 +3,8 @@ export type LocalizerKeys =
| 'accept'
| 'accountIDCopy'
| 'accountIdEnter'
| 'accountIdEnterYourFriends'
| 'accountIdErrorInvalid'
| 'accountIdOrOnsEnter'
| 'accountIdYours'
| 'activeMembers'
| 'add'

Loading…
Cancel
Save