import { ChangeEvent, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';
import { Avatar, AvatarSize } from '../avatar/Avatar';
import { SyncUtils, ToastUtils, UserUtils } from '../../session/utils';
import { YourSessionIDPill, YourSessionIDSelectable } from '../basic/YourSessionIDPill';
import { useOurAvatarPath, useOurConversationUsername } from '../../hooks/useParamSelector';
import { ConversationTypeEnum } from '../../models/conversationAttributes';
import { MAX_NAME_LENGTH_BYTES } from '../../session/constants';
import { getConversationController } from '../../session/conversations';
import { sanitizeSessionUsername } from '../../session/utils/String';
import { editProfileModal, updateEditProfilePictureModel } from '../../state/ducks/modalDialog';
import { getTheme } from '../../state/selectors/theme';
import { getThemeValue } from '../../themes/globals';
import { setLastProfileUpdateTimestamp } from '../../util/storage';
import { SessionQRCode } from '../SessionQRCode';
import { SessionWrapperModal } from '../SessionWrapperModal';
import { Flex } from '../basic/Flex';
import { SessionButton } from '../basic/SessionButton';
import { Spacer2XL, Spacer3XL, SpacerLG, SpacerSM, SpacerXL, SpacerXS } from '../basic/Text';
import { SessionIconButton } from '../icon';
import { SessionSpinner } from '../loading';
const StyledEditProfileDialog = styled.div`
.session-modal {
width: 468px;
.session-modal__body {
overflow: initial;
}
}
.avatar-center-inner {
position: relative;
.qr-view-button {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: -8px;
right: -8px;
height: 34px;
width: 34px;
border-radius: 50%;
background-color: var(--white-color);
transition: var(--default-duration);
&:hover {
filter: brightness(90%);
}
.session-icon-button {
opacity: 1;
}
}
}
`;
const StyledProfileName = styled(Flex)`
input {
height: 38px;
border-radius: 5px;
text-align: center;
font-size: var(--font-size-md);
}
&.uneditable {
p {
margin: 0;
padding: 0px var(--margins-lg) 0 var(--margins-sm);
}
.session-icon-button {
padding: 0px;
}
}
`;
const StyledSessionIdSection = styled(Flex)`
.session-button {
width: 160px;
}
`;
const QRView = ({ sessionID }: { sessionID: string }) => {
const theme = useSelector(getTheme);
return (
);
};
const updateDisplayName = async (newName: string) => {
const ourNumber = UserUtils.getOurPubKeyStrFromCache();
const conversation = await getConversationController().getOrCreateAndWait(
ourNumber,
ConversationTypeEnum.PRIVATE
);
conversation.setSessionDisplayNameNoCommit(newName);
// might be good to not trigger a sync if the name did not change
await conversation.commit();
await setLastProfileUpdateTimestamp(Date.now());
await SyncUtils.forceSyncConfigurationNowIfNeeded(true);
};
type ProfileAvatarProps = {
avatarPath: string | null;
newAvatarObjectUrl?: string | null;
profileName: string | undefined;
ourId: string;
};
export const ProfileAvatar = (props: ProfileAvatarProps) => {
const { newAvatarObjectUrl, avatarPath, profileName, ourId } = props;
return (
);
};
type ProfileHeaderProps = ProfileAvatarProps & {
onClick: () => void;
setMode: (mode: ProfileDialogModes) => void;
};
const ProfileHeader = (props: ProfileHeaderProps) => {
const { avatarPath, profileName, ourId, onClick, setMode } = props;
return (
{
setMode('qr');
}}
role="button"
>
);
};
type ProfileDialogModes = 'default' | 'edit' | 'qr';
export const EditProfileDialog = () => {
const dispatch = useDispatch();
const _profileName = useOurConversationUsername() || '';
const [profileName, setProfileName] = useState(_profileName);
const [updatedProfileName, setUpdateProfileName] = useState(profileName);
const avatarPath = useOurAvatarPath() || '';
const ourId = UserUtils.getOurPubKeyStrFromCache();
const [mode, setMode] = useState('default');
const [loading, setLoading] = useState(false);
const closeDialog = () => {
window.removeEventListener('keyup', handleOnKeyUp);
window.inboxStore?.dispatch(editProfileModal(null));
};
const backButton =
mode === 'edit' || mode === 'qr'
? [
{
iconType: 'chevron',
iconRotation: 90,
onClick: () => {
setMode('default');
},
},
]
: undefined;
const onClickOK = async () => {
/**
* Tidy the profile name input text and save the new profile name and avatar
*/
try {
const newName = profileName ? profileName.trim() : '';
if (newName.length === 0 || newName.length > MAX_NAME_LENGTH_BYTES) {
return;
}
// this throw if the length in bytes is too long
const sanitizedName = sanitizeSessionUsername(newName);
const trimName = sanitizedName.trim();
setUpdateProfileName(trimName);
setLoading(true);
await updateDisplayName(newName);
setMode('default');
setUpdateProfileName(profileName);
setLoading(false);
} catch (e) {
ToastUtils.pushToastError('nameTooLong', window.i18n('displayNameTooLong'));
}
};
const handleOnKeyUp = (event: any) => {
switch (event.key) {
case 'Enter':
if (mode === 'edit') {
void onClickOK();
}
break;
case 'Esc':
case 'Escape':
closeDialog();
break;
default:
}
};
const handleProfileHeaderClick = () => {
closeDialog();
dispatch(
updateEditProfilePictureModel({
avatarPath,
profileName,
ourId,
})
);
};
const onNameEdited = (event: ChangeEvent) => {
const displayName = event.target.value;
try {
const newName = sanitizeSessionUsername(displayName);
setProfileName(newName);
} catch (e) {
setProfileName(displayName);
ToastUtils.pushToastError('nameTooLong', window.i18n('displayNameTooLong'));
}
};
return (
/* The