import cx from 'classnames';
import React, { useMemo, useRef } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { Transition } from 'react-transition-group';
import Pill from 'src/components/Pill/Pill';
import { useBackend } from 'src/contexts/backend/backend';
import { useSigningClient } from 'src/contexts/signerClient';
import usePassportByAddress from 'src/features/passport/hooks/usePassportByAddress';
import useIsOnline from 'src/hooks/useIsOnline';
import useOnClickOutside from 'src/hooks/useOnClickOutside';
import { useAppSelector } from 'src/redux/hooks';
import { routes } from 'src/routes';
import BroadcastChannelSender from 'src/services/backend/channels/BroadcastChannelSender';
import useMediaQuery from '../../../../hooks/useMediaQuery';
import robot from '../../../../image/temple/robot.png';
import { AvataImgIpfs } from '../../../portal/components/avataIpfs';
import MiningBadge from '../../MiningBadge/MiningBadge';
import networkStyles from '../CurrentApp/CurrentApp.module.scss';
import styles from './SwitchAccount.module.scss';

// should be refactored
function AccountItem({
  data,
  onClickSetActive,
  setControlledVisible,
  name: accountName,
  image,
  link,
}) {
  const address = data?.cyber?.bech32;
  const location = useLocation();

  const { passport } = usePassportByAddress(address);

  const name = passport?.extension?.nickname || data?.cyber?.name || accountName;

  const nickname = passport?.extension?.nickname;

  function handleClick() {
    onClickSetActive?.();
    setControlledVisible(false);
  }

  const robotPath = nickname ? routes.robotPassport.getLink(nickname) : routes.robot.path;

  const linkToRobot = location.pathname.includes('@') ? robotPath : undefined;

  return (
    <Link
      to={link || linkToRobot}
      onClick={handleClick}
      className={cx(styles.containerSwichAccount, networkStyles.btnContainerText)}
    >
      <div className={cx(networkStyles.containerInfoSwitch, styles.content)}>
        {name && (
          <span
            className={cx(networkStyles.btnContainerText, {
              [styles.noAccount]: !address,
            })}
          >
            {name}
          </span>
        )}
        <MiningBadge />
      </div>
      <div className={cx(styles.containerAvatarConnect)}>
        <div className={styles.containerAvatarConnectTrue}>
          {image ? (
            <img className={styles.image} src={image} alt={name} />
          ) : (
            <AvataImgIpfs
              style={{ position: 'relative' }}
              cidAvatar={passport?.extension?.avatar}
              addressCyber={address}
            />
          )}
        </div>
      </div>
    </Link>
  );
}

function SwitchAccount() {
  const { signerReady } = useSigningClient();
  const { isIpfsInitialized } = useBackend();
  const isOnline = useIsOnline();
  const mediaQuery = useMediaQuery('(min-width: 768px)');

  const [controlledVisible, setControlledVisible] = React.useState(false);

  const { defaultAccount, accounts } = useAppSelector((state) => state.pocket);

  const useGetAddress = defaultAccount?.account?.cyber?.bech32 || null;

  const { passport } = usePassportByAddress(useGetAddress);

  const containerRef = useRef<HTMLDivElement>(null);

  useOnClickOutside(containerRef, () => {
    setControlledVisible(false);
  });

  const useGetCidAvatar = passport?.extension.avatar;
  const useGetName = passport?.extension.nickname || defaultAccount?.name;
  const isReadOnly = defaultAccount.account?.cyber.keys === 'read-only';

  const onClickChangeActiveAcc = async (key: string) => {
    const broadcastChannel = new BroadcastChannelSender();
    broadcastChannel.postSetDefaultAccount(key);
    setControlledVisible(false);
  };

  const renderItem = useMemo(() => {
    if (!accounts) {
      return null;
    }

    return Object.keys(accounts)
      .filter((item) => defaultAccount.name !== item && accounts[item].cyber)
      .map((key) => {
        return (
          <AccountItem
            key={key}
            data={accounts[key]}
            onClickSetActive={() => onClickChangeActiveAcc(key)}
            setControlledVisible={setControlledVisible}
            name={key}
          />
        );
      });

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [accounts, defaultAccount, onClickChangeActiveAcc]);

  // const multipleAccounts = renderItem && Object.keys(renderItem).length > 0;

  return (
    <div className={styles.switchAccountRoot} style={{ position: 'relative', fontSize: '20px' }} ref={containerRef}>
      <div className={styles.containerSwichAccount}>
        {(!useGetAddress || !mediaQuery) && mediaQuery && (
          <Link className={networkStyles.btnContainerText} to={routes.settings.path}>
            Settings
          </Link>
        )}
        {useGetAddress && mediaQuery && (
          <div
            className={cx(
              networkStyles.containerInfoSwitch,
              isReadOnly || !signerReady ? networkStyles.containerInfoSwitchGapUnSet : undefined
            )}
          >
            {useGetName && (
              <button
                onClick={() => setControlledVisible((item) => !item)}
                className={networkStyles.btnContainerText}
                type="button"
                style={{ fontSize: '20px' }}
              >
                {useGetName}
              </button>
            )}
            {isReadOnly && <Pill color="yellow" text="read only" />}
            {!isReadOnly && !signerReady && isOnline && <Pill color="red" text="unlock wallet" />}
            {!isOnline && <Pill color="red" text="offline" />}
            <MiningBadge />
          </div>
        )}
        {(() => {
          const avatarContent = (
            <div
              className={cx(styles.containerAvatarConnect, {
                [styles.containerAvatarConnectFalse]: !isIpfsInitialized || !isOnline,
                [styles.containerAvatarConnectTrueGreen]: isIpfsInitialized && isOnline,
              })}
            >
              <AvataImgIpfs
                style={{
                  position: 'relative',
                  objectFit: !useGetCidAvatar && 'contain',
                }}
                cidAvatar={useGetCidAvatar}
                addressCyber={useGetAddress}
                img={robot}
              />
            </div>
          );

          return mediaQuery ? (
            <Link
              to={
                passport ? routes.robotPassport.getLink(passport.extension.nickname) : routes.robot.path
              }
              className={styles.content}
            >
              {avatarContent}
            </Link>
          ) : (
            <button
              type="button"
              onClick={() => setControlledVisible((item) => !item)}
              className={styles.content}
              style={{ background: 'none', border: 'none', padding: 0, cursor: 'pointer' }}
            >
              {avatarContent}
            </button>
          );
        })()}
      </div>
      {!mediaQuery && controlledVisible && (
        <div
          className={styles.mobileOverlay}
          onClick={() => setControlledVisible(false)}
        />
      )}
      <Transition in={controlledVisible} timeout={300}>
        {(state) => {
          return (
            <div
              className={styles.tooltipContainerRight}
            >
              <div
                className={cx(styles.containerSwichAccountList, [
                  styles[`containerSwichAccountList_${state}`],
                ])}
              >
                {renderItem}

                <AccountItem
                  name="supersigma"
                  link={routes.sigma.path}
                  setControlledVisible={setControlledVisible}
                  image={require('../../../../image/sigma.png')}
                />
                <AccountItem
                  name="settings"
                  setControlledVisible={setControlledVisible}
                  link={routes.settings.path}
                  image={require('./keys.png')}
                />
              </div>
            </div>
          );
        }}
      </Transition>
    </div>
  );
}

export default SwitchAccount;

Synonyms

pussy-ts/src/containers/application/Header/SwitchAccount/SwitchAccount.tsx

Neighbours