[Glitch] Change design of boost modal in web UI
Port 29b9642b31 to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
			
			
This commit is contained in:
		
							parent
							
								
									d3629d191f
								
							
						
					
					
						commit
						e15fad27bc
					
				| 
						 | 
				
			
			@ -1,28 +1,17 @@
 | 
			
		|||
import type { MouseEventHandler } from 'react';
 | 
			
		||||
import { useCallback, useState } from 'react';
 | 
			
		||||
 | 
			
		||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
 | 
			
		||||
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
import { useHistory } from 'react-router';
 | 
			
		||||
 | 
			
		||||
import type Immutable from 'immutable';
 | 
			
		||||
 | 
			
		||||
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
 | 
			
		||||
import AttachmentList from 'flavours/glitch/components/attachment_list';
 | 
			
		||||
import { Button } from 'flavours/glitch/components/button';
 | 
			
		||||
import { Icon } from 'flavours/glitch/components/icon';
 | 
			
		||||
import { VisibilityIcon } from 'flavours/glitch/components/visibility_icon';
 | 
			
		||||
import PrivacyDropdown from 'flavours/glitch/features/compose/components/privacy_dropdown';
 | 
			
		||||
import type { Account } from 'flavours/glitch/models/account';
 | 
			
		||||
import { EmbeddedStatus } from 'flavours/glitch/features/notifications_v2/components/embedded_status';
 | 
			
		||||
import type { Status, StatusVisibility } from 'flavours/glitch/models/status';
 | 
			
		||||
import { useAppSelector } from 'flavours/glitch/store';
 | 
			
		||||
 | 
			
		||||
import { Avatar } from '../../../components/avatar';
 | 
			
		||||
import { Button } from '../../../components/button';
 | 
			
		||||
import { DisplayName } from '../../../components/display_name';
 | 
			
		||||
import { RelativeTimestamp } from '../../../components/relative_timestamp';
 | 
			
		||||
import StatusContent from '../../../components/status_content';
 | 
			
		||||
 | 
			
		||||
const messages = defineMessages({
 | 
			
		||||
  cancel_reblog: {
 | 
			
		||||
    id: 'status.cancel_reblog_private',
 | 
			
		||||
| 
						 | 
				
			
			@ -35,21 +24,19 @@ export const BoostModal: React.FC<{
 | 
			
		|||
  status: Status;
 | 
			
		||||
  onClose: () => void;
 | 
			
		||||
  onReblog: (status: Status, privacy: StatusVisibility) => void;
 | 
			
		||||
  missingMediaDescription?: boolean;
 | 
			
		||||
}> = ({ status, onReblog, onClose, missingMediaDescription }) => {
 | 
			
		||||
}> = ({ status, onReblog, onClose }) => {
 | 
			
		||||
  const intl = useIntl();
 | 
			
		||||
  const history = useHistory();
 | 
			
		||||
 | 
			
		||||
  const default_privacy = useAppSelector(
 | 
			
		||||
  const defaultPrivacy = useAppSelector(
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
 | 
			
		||||
    (state) => state.compose.get('default_privacy') as StatusVisibility,
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const account = status.get('account') as Account;
 | 
			
		||||
  const statusId = status.get('id') as string;
 | 
			
		||||
  const statusVisibility = status.get('visibility') as StatusVisibility;
 | 
			
		||||
 | 
			
		||||
  const [privacy, setPrivacy] = useState<StatusVisibility>(
 | 
			
		||||
    statusVisibility === 'private' ? 'private' : default_privacy,
 | 
			
		||||
    statusVisibility === 'private' ? 'private' : defaultPrivacy,
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const onPrivacyChange = useCallback((value: StatusVisibility) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -61,20 +48,9 @@ export const BoostModal: React.FC<{
 | 
			
		|||
    onClose();
 | 
			
		||||
  }, [onClose, onReblog, status, privacy]);
 | 
			
		||||
 | 
			
		||||
  const handleAccountClick = useCallback<MouseEventHandler>(
 | 
			
		||||
    (e) => {
 | 
			
		||||
      if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
        onClose();
 | 
			
		||||
        history.push(`/@${account.acct}`);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    [history, onClose, account],
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const buttonText = status.get('reblogged')
 | 
			
		||||
    ? messages.cancel_reblog
 | 
			
		||||
    : messages.reblog;
 | 
			
		||||
  const handleCancel = useCallback(() => {
 | 
			
		||||
    onClose();
 | 
			
		||||
  }, [onClose]);
 | 
			
		||||
 | 
			
		||||
  const findContainer = useCallback(
 | 
			
		||||
    () => document.getElementsByClassName('modal-root__container')[0],
 | 
			
		||||
| 
						 | 
				
			
			@ -82,88 +58,78 @@ export const BoostModal: React.FC<{
 | 
			
		|||
  );
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className='modal-root__modal boost-modal'>
 | 
			
		||||
      <div className='boost-modal__container'>
 | 
			
		||||
        <div
 | 
			
		||||
          className={classNames(
 | 
			
		||||
            'status',
 | 
			
		||||
            `status-${statusVisibility}`,
 | 
			
		||||
            'light',
 | 
			
		||||
          )}
 | 
			
		||||
        >
 | 
			
		||||
          <div className='status__info'>
 | 
			
		||||
            <a
 | 
			
		||||
              href={status.get('url') as string}
 | 
			
		||||
              className='status__relative-time'
 | 
			
		||||
              target='_blank'
 | 
			
		||||
              rel='noopener noreferrer'
 | 
			
		||||
            >
 | 
			
		||||
              <span className='status__visibility-icon'>
 | 
			
		||||
                <VisibilityIcon visibility={statusVisibility} />
 | 
			
		||||
              </span>
 | 
			
		||||
              <RelativeTimestamp
 | 
			
		||||
                timestamp={status.get('created_at') as string}
 | 
			
		||||
              />
 | 
			
		||||
            </a>
 | 
			
		||||
 | 
			
		||||
            <a
 | 
			
		||||
              onClick={handleAccountClick}
 | 
			
		||||
              href={account.url}
 | 
			
		||||
              className='status__display-name'
 | 
			
		||||
            >
 | 
			
		||||
              <div className='status__avatar'>
 | 
			
		||||
                <Avatar account={account} size={48} />
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
              <DisplayName account={account} />
 | 
			
		||||
            </a>
 | 
			
		||||
    <div className='modal-root__modal safety-action-modal'>
 | 
			
		||||
      <div className='safety-action-modal__top'>
 | 
			
		||||
        <div className='safety-action-modal__header'>
 | 
			
		||||
          <div className='safety-action-modal__header__icon'>
 | 
			
		||||
            <Icon icon={RepeatIcon} id='retweet' />
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          {/* @ts-expect-error Expected until StatusContent is typed */}
 | 
			
		||||
          <StatusContent status={status} />
 | 
			
		||||
          <div>
 | 
			
		||||
            <h1>
 | 
			
		||||
              {status.get('reblogged') ? (
 | 
			
		||||
                <FormattedMessage
 | 
			
		||||
                  id='boost_modal.undo_reblog'
 | 
			
		||||
                  defaultMessage='Unboost post?'
 | 
			
		||||
                />
 | 
			
		||||
              ) : (
 | 
			
		||||
                <FormattedMessage
 | 
			
		||||
                  id='boost_modal.reblog'
 | 
			
		||||
                  defaultMessage='Boost post?'
 | 
			
		||||
                />
 | 
			
		||||
              )}
 | 
			
		||||
            </h1>
 | 
			
		||||
            <div>
 | 
			
		||||
              <FormattedMessage
 | 
			
		||||
                id='boost_modal.combo'
 | 
			
		||||
                defaultMessage='You can press {combo} to skip this next time'
 | 
			
		||||
                values={{
 | 
			
		||||
                  combo: (
 | 
			
		||||
                    <span className='hotkey-combination'>
 | 
			
		||||
                      <kbd>Shift</kbd>+<Icon id='retweet' icon={RepeatIcon} />
 | 
			
		||||
                    </span>
 | 
			
		||||
                  ),
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
          {(status.get('media_attachments') as Immutable.List<unknown>).size >
 | 
			
		||||
            0 && (
 | 
			
		||||
            <AttachmentList compact media={status.get('media_attachments')} />
 | 
			
		||||
          )}
 | 
			
		||||
        <div className='safety-action-modal__status'>
 | 
			
		||||
          <EmbeddedStatus statusId={statusId} />
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div className='boost-modal__action-bar'>
 | 
			
		||||
        <div>
 | 
			
		||||
          {missingMediaDescription ? (
 | 
			
		||||
            <FormattedMessage
 | 
			
		||||
              id='boost_modal.missing_description'
 | 
			
		||||
              defaultMessage='This toot contains some media without description'
 | 
			
		||||
            />
 | 
			
		||||
          ) : (
 | 
			
		||||
            <FormattedMessage
 | 
			
		||||
              id='boost_modal.combo'
 | 
			
		||||
              defaultMessage='You can press {combo} to skip this next time'
 | 
			
		||||
              values={{
 | 
			
		||||
                combo: (
 | 
			
		||||
                  <span>
 | 
			
		||||
                    Shift + <Icon id='retweet' icon={RepeatIcon} />
 | 
			
		||||
                  </span>
 | 
			
		||||
                ),
 | 
			
		||||
              }}
 | 
			
		||||
      <div className={classNames('safety-action-modal__bottom')}>
 | 
			
		||||
        <div className='safety-action-modal__actions'>
 | 
			
		||||
          {!status.get('reblogged') && (
 | 
			
		||||
            <PrivacyDropdown
 | 
			
		||||
              noDirect
 | 
			
		||||
              value={privacy}
 | 
			
		||||
              container={findContainer}
 | 
			
		||||
              onChange={onPrivacyChange}
 | 
			
		||||
              disabled={statusVisibility === 'private'}
 | 
			
		||||
            />
 | 
			
		||||
          )}
 | 
			
		||||
        </div>
 | 
			
		||||
        {statusVisibility !== 'private' && !status.get('reblogged') && (
 | 
			
		||||
          <PrivacyDropdown
 | 
			
		||||
            noDirect
 | 
			
		||||
            value={privacy}
 | 
			
		||||
            container={findContainer}
 | 
			
		||||
            onChange={onPrivacyChange}
 | 
			
		||||
 | 
			
		||||
          <div className='spacer' />
 | 
			
		||||
 | 
			
		||||
          <button onClick={handleCancel} className='link-button'>
 | 
			
		||||
            <FormattedMessage
 | 
			
		||||
              id='confirmation_modal.cancel'
 | 
			
		||||
              defaultMessage='Cancel'
 | 
			
		||||
            />
 | 
			
		||||
          </button>
 | 
			
		||||
 | 
			
		||||
          <Button
 | 
			
		||||
            onClick={handleReblog}
 | 
			
		||||
            text={intl.formatMessage(
 | 
			
		||||
              status.get('reblogged')
 | 
			
		||||
                ? messages.cancel_reblog
 | 
			
		||||
                : messages.reblog,
 | 
			
		||||
            )}
 | 
			
		||||
          />
 | 
			
		||||
        )}
 | 
			
		||||
        <Button
 | 
			
		||||
          text={intl.formatMessage(buttonText)}
 | 
			
		||||
          onClick={handleReblog}
 | 
			
		||||
          // eslint-disable-next-line jsx-a11y/no-autofocus
 | 
			
		||||
          autoFocus
 | 
			
		||||
        />
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6590,6 +6590,48 @@ a.status-card {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__status {
 | 
			
		||||
    border: 1px solid var(--modal-border-color);
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
    padding: 8px;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
 | 
			
		||||
    &__account {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      gap: 4px;
 | 
			
		||||
      margin-bottom: 8px;
 | 
			
		||||
      color: $dark-text-color;
 | 
			
		||||
 | 
			
		||||
      bdi {
 | 
			
		||||
        color: inherit;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__content {
 | 
			
		||||
      display: -webkit-box;
 | 
			
		||||
      font-size: 15px;
 | 
			
		||||
      line-height: 22px;
 | 
			
		||||
      color: $dark-text-color;
 | 
			
		||||
      -webkit-line-clamp: 4;
 | 
			
		||||
      -webkit-box-orient: vertical;
 | 
			
		||||
      max-height: 4 * 22px;
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
 | 
			
		||||
      p,
 | 
			
		||||
      a {
 | 
			
		||||
        color: inherit;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .reply-indicator__attachments {
 | 
			
		||||
      margin-top: 0;
 | 
			
		||||
      font-size: 15px;
 | 
			
		||||
      line-height: 22px;
 | 
			
		||||
      color: $dark-text-color;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__bullet-points {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
| 
						 | 
				
			
			@ -6667,6 +6709,12 @@ a.status-card {
 | 
			
		|||
    gap: 8px;
 | 
			
		||||
    justify-content: flex-end;
 | 
			
		||||
 | 
			
		||||
    &__hint {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
      line-height: 20px;
 | 
			
		||||
      color: $dark-text-color;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .link-button {
 | 
			
		||||
      padding: 10px 12px;
 | 
			
		||||
      font-weight: 600;
 | 
			
		||||
| 
						 | 
				
			
			@ -6674,6 +6722,18 @@ a.status-card {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hotkey-combination {
 | 
			
		||||
  display: inline-flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  gap: 4px;
 | 
			
		||||
 | 
			
		||||
  kbd {
 | 
			
		||||
    padding: 3px 5px;
 | 
			
		||||
    border: 1px solid var(--background-border-color);
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.doodle-modal,
 | 
			
		||||
.boost-modal,
 | 
			
		||||
.report-modal,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue