Merge remote-tracking branch 'origin/develop' into color-improvements

color-improvements
Alex Gleason 2022-09-10 12:19:08 -05:00
commit b3ad112b30
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
17 zmienionych plików z 148 dodań i 72 usunięć

Wyświetl plik

@ -8,9 +8,10 @@ import type { SearchFilter } from 'soapbox/reducers/search';
import type { AppDispatch, RootState } from 'soapbox/store'; import type { AppDispatch, RootState } from 'soapbox/store';
import type { APIEntity } from 'soapbox/types/entities'; import type { APIEntity } from 'soapbox/types/entities';
const SEARCH_CHANGE = 'SEARCH_CHANGE'; const SEARCH_CHANGE = 'SEARCH_CHANGE';
const SEARCH_CLEAR = 'SEARCH_CLEAR'; const SEARCH_CLEAR = 'SEARCH_CLEAR';
const SEARCH_SHOW = 'SEARCH_SHOW'; const SEARCH_SHOW = 'SEARCH_SHOW';
const SEARCH_RESULTS_CLEAR = 'SEARCH_RESULTS_CLEAR';
const SEARCH_FETCH_REQUEST = 'SEARCH_FETCH_REQUEST'; const SEARCH_FETCH_REQUEST = 'SEARCH_FETCH_REQUEST';
const SEARCH_FETCH_SUCCESS = 'SEARCH_FETCH_SUCCESS'; const SEARCH_FETCH_SUCCESS = 'SEARCH_FETCH_SUCCESS';
@ -28,7 +29,11 @@ const changeSearch = (value: string) =>
(dispatch: AppDispatch) => { (dispatch: AppDispatch) => {
// If backspaced all the way, clear the search // If backspaced all the way, clear the search
if (value.length === 0) { if (value.length === 0) {
return dispatch(clearSearch()); dispatch(clearSearchResults());
return dispatch({
type: SEARCH_CHANGE,
value,
});
} else { } else {
return dispatch({ return dispatch({
type: SEARCH_CHANGE, type: SEARCH_CHANGE,
@ -41,6 +46,10 @@ const clearSearch = () => ({
type: SEARCH_CLEAR, type: SEARCH_CLEAR,
}); });
const clearSearchResults = () => ({
type: SEARCH_RESULTS_CLEAR,
});
const submitSearch = (filter?: SearchFilter) => const submitSearch = (filter?: SearchFilter) =>
(dispatch: AppDispatch, getState: () => RootState) => { (dispatch: AppDispatch, getState: () => RootState) => {
const value = getState().search.value; const value = getState().search.value;
@ -167,6 +176,7 @@ export {
SEARCH_CHANGE, SEARCH_CHANGE,
SEARCH_CLEAR, SEARCH_CLEAR,
SEARCH_SHOW, SEARCH_SHOW,
SEARCH_RESULTS_CLEAR,
SEARCH_FETCH_REQUEST, SEARCH_FETCH_REQUEST,
SEARCH_FETCH_SUCCESS, SEARCH_FETCH_SUCCESS,
SEARCH_FETCH_FAIL, SEARCH_FETCH_FAIL,
@ -177,6 +187,7 @@ export {
SEARCH_ACCOUNT_SET, SEARCH_ACCOUNT_SET,
changeSearch, changeSearch,
clearSearch, clearSearch,
clearSearchResults,
submitSearch, submitSearch,
fetchSearchRequest, fetchSearchRequest,
fetchSearchSuccess, fetchSearchSuccess,

Wyświetl plik

@ -6,7 +6,7 @@ import { Virtuoso, Components, VirtuosoProps, VirtuosoHandle, ListRange, IndexLo
import { useSettings } from 'soapbox/hooks'; import { useSettings } from 'soapbox/hooks';
import LoadMore from './load_more'; import LoadMore from './load_more';
import { Card, Spinner, Text } from './ui'; import { Card, Spinner } from './ui';
/** Custom Viruoso component context. */ /** Custom Viruoso component context. */
type Context = { type Context = {
@ -162,7 +162,7 @@ const ScrollableList = React.forwardRef<VirtuosoHandle, IScrollableList>(({
{isLoading ? ( {isLoading ? (
<Spinner /> <Spinner />
) : ( ) : (
<Text>{emptyMessage}</Text> emptyMessage
)} )}
</Card> </Card>
</div> </div>

Wyświetl plik

@ -301,12 +301,12 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
}; };
const handleCopy: React.EventHandler<React.MouseEvent> = (e) => { const handleCopy: React.EventHandler<React.MouseEvent> = (e) => {
const { url } = status; const { uri } = status;
const textarea = document.createElement('textarea'); const textarea = document.createElement('textarea');
e.stopPropagation(); e.stopPropagation();
textarea.textContent = url; textarea.textContent = uri;
textarea.style.position = 'fixed'; textarea.style.position = 'fixed';
document.body.appendChild(textarea); document.body.appendChild(textarea);

Wyświetl plik

@ -25,7 +25,7 @@ const useButtonStyles = ({
tertiary: tertiary:
'bg-transparent border-gray-400 dark:border-gray-800 hover:border-primary-300 dark:hover:border-primary-700 focus:border-primary-500 text-gray-900 dark:text-gray-100 focus:ring-primary-500', 'bg-transparent border-gray-400 dark:border-gray-800 hover:border-primary-300 dark:hover:border-primary-700 focus:border-primary-500 text-gray-900 dark:text-gray-100 focus:ring-primary-500',
accent: 'border-transparent bg-secondary-500 hover:bg-secondary-400 focus:bg-secondary-500 text-gray-100 focus:ring-secondary-300', accent: 'border-transparent bg-secondary-500 hover:bg-secondary-400 focus:bg-secondary-500 text-gray-100 focus:ring-secondary-300',
danger: 'border-transparent bg-danger-600 text-gray-100 hover:bg-danger-500 dark:hover:bg-danger-700 focus:bg-danger-600 dark:focus:bg-danger-600', danger: 'border-transparent bg-danger-100 dark:bg-danger-900 text-danger-600 dark:text-danger-200 hover:bg-danger-600 hover:text-gray-100 dark:hover:text-gray-100 dark:hover:bg-danger-500 focus:bg-danger-800 dark:focus:bg-danger-600',
transparent: 'border-transparent text-gray-800 backdrop-blur-sm bg-white/75 hover:bg-white/80', transparent: 'border-transparent text-gray-800 backdrop-blur-sm bg-white/75 hover:bg-white/80',
outline: 'border-gray-100 border-2 bg-transparent text-gray-100 hover:bg-white/10', outline: 'border-gray-100 border-2 bg-transparent text-gray-100 hover:bg-white/10',
}; };

Wyświetl plik

@ -1,11 +1,16 @@
import React from 'react'; import React from 'react';
import Text from '../text/text';
import type { Sizes as TextSizes } from '../text/text';
interface IDivider { interface IDivider {
text?: string text?: string
textSize?: TextSizes
} }
/** Divider */ /** Divider */
const Divider = ({ text }: IDivider) => ( const Divider = ({ text, textSize = 'md' }: IDivider) => (
<div className='relative' data-testid='divider'> <div className='relative' data-testid='divider'>
<div className='absolute inset-0 flex items-center' aria-hidden='true'> <div className='absolute inset-0 flex items-center' aria-hidden='true'>
<div className='w-full border-t-2 border-gray-100 dark:border-gray-800 border-solid' /> <div className='w-full border-t-2 border-gray-100 dark:border-gray-800 border-solid' />
@ -13,7 +18,9 @@ const Divider = ({ text }: IDivider) => (
{text && ( {text && (
<div className='relative flex justify-center'> <div className='relative flex justify-center'>
<span className='px-2 bg-white text-gray-400' data-testid='divider-text'>{text}</span> <span className='px-2 bg-white dark:bg-gray-900 text-gray-400' data-testid='divider-text'>
<Text size={textSize} tag='span' theme='inherit'>{text}</Text>
</span>
</div> </div>
)} )}
</div> </div>

Wyświetl plik

@ -20,7 +20,7 @@ interface IInput extends Pick<React.InputHTMLAttributes<HTMLInputElement>, 'maxL
className?: string, className?: string,
/** Extra class names for the outer <div> element. */ /** Extra class names for the outer <div> element. */
outerClassName?: string, outerClassName?: string,
/** URL to the svg icon. Cannot be used with addon. */ /** URL to the svg icon. Cannot be used with prepend. */
icon?: string, icon?: string,
/** Internal input name. */ /** Internal input name. */
name?: string, name?: string,
@ -30,12 +30,14 @@ interface IInput extends Pick<React.InputHTMLAttributes<HTMLInputElement>, 'maxL
value?: string | number, value?: string | number,
/** Change event handler for the input. */ /** Change event handler for the input. */
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void, onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void,
/** HTML input type. */
type?: 'text' | 'number' | 'email' | 'tel' | 'password',
/** Whether to display the input in red. */ /** Whether to display the input in red. */
hasError?: boolean, hasError?: boolean,
/** An element to display as prefix to input. Cannot be used with icon. */ /** An element to display as prefix to input. Cannot be used with icon. */
addon?: React.ReactElement, prepend?: React.ReactElement,
/** An element to display as suffix to input. Cannot be used with password type. */
append?: React.ReactElement,
/** Adds specific styling to denote a searchabe input. */
isSearch?: boolean,
} }
/** Form input element. */ /** Form input element. */
@ -43,7 +45,7 @@ const Input = React.forwardRef<HTMLInputElement, IInput>(
(props, ref) => { (props, ref) => {
const intl = useIntl(); const intl = useIntl();
const { type = 'text', icon, className, outerClassName, hasError, addon, ...filteredProps } = props; const { type = 'text', icon, className, outerClassName, hasError, append, prepend, isSearch, ...filteredProps } = props;
const [revealed, setRevealed] = React.useState(false); const [revealed, setRevealed] = React.useState(false);
@ -54,16 +56,23 @@ const Input = React.forwardRef<HTMLInputElement, IInput>(
}, []); }, []);
return ( return (
<div className={classNames('mt-1 relative rounded-md shadow-sm', outerClassName)}> <div
className={
classNames('mt-1 relative shadow-sm', outerClassName, {
'rounded-md': !isSearch,
'rounded-full': isSearch,
})
}
>
{icon ? ( {icon ? (
<div className='absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none'> <div className='absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none'>
<Icon src={icon} className='h-4 w-4 text-gray-700 dark:text-gray-600' aria-hidden='true' /> <Icon src={icon} className='h-4 w-4 text-gray-700 dark:text-gray-600' aria-hidden='true' />
</div> </div>
) : null} ) : null}
{addon ? ( {prepend ? (
<div className='absolute inset-y-0 left-0 flex items-center'> <div className='absolute inset-y-0 left-0 flex items-center'>
{addon} {prepend}
</div> </div>
) : null} ) : null}
@ -72,15 +81,24 @@ const Input = React.forwardRef<HTMLInputElement, IInput>(
type={revealed ? 'text' : type} type={revealed ? 'text' : type}
ref={ref} ref={ref}
className={classNames({ className={classNames({
'bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 placeholder:text-gray-600 dark:placeholder:text-gray-600 block w-full sm:text-sm border-gray-400 dark:border-gray-800 dark:ring-1 dark:ring-gray-800 rounded-md focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-primary-500 dark:focus:border-primary-500': 'text-gray-900 dark:text-gray-100 placeholder:text-gray-600 dark:placeholder:text-gray-600 block w-full sm:text-sm dark:ring-1 dark:ring-gray-800 focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-primary-500 dark:focus:border-primary-500':
true, true,
'pr-7': isPassword, 'rounded-md bg-white dark:bg-gray-900 border-gray-400 dark:border-gray-800': !isSearch,
'rounded-full bg-gray-200 border-gray-200 dark:bg-gray-800 dark:border-gray-800 focus:bg-white': isSearch,
'pr-7': isPassword || append,
'text-red-600 border-red-600': hasError, 'text-red-600 border-red-600': hasError,
'pl-8': typeof icon !== 'undefined', 'pl-8': typeof icon !== 'undefined',
'pl-16': typeof addon !== 'undefined', 'pl-16': typeof prepend !== 'undefined',
}, className)} }, className)}
/> />
{/* eslint-disable-next-line no-nested-ternary */}
{append ? (
<div className='absolute inset-y-0 right-0 flex items-center pr-3'>
{append}
</div>
) : null}
{isPassword ? ( {isPassword ? (
<Tooltip <Tooltip
text={ text={

Wyświetl plik

@ -67,7 +67,7 @@ const PhoneInput: React.FC<IPhoneInput> = (props) => {
<Input <Input
onChange={handleChange} onChange={handleChange}
value={nationalNumber} value={nationalNumber}
addon={ prepend={
<CountryCodeDropdown <CountryCodeDropdown
countryCode={countryCode} countryCode={countryCode}
onChange={setCountryCode} onChange={setCountryCode}

Wyświetl plik

@ -37,12 +37,13 @@ interface IStack extends React.HTMLAttributes<HTMLDivElement> {
} }
/** Vertical stack of child elements. */ /** Vertical stack of child elements. */
const Stack: React.FC<IStack> = (props) => { const Stack: React.FC<IStack> = React.forwardRef((props, ref: React.LegacyRef<HTMLDivElement> | undefined) => {
const { space, alignItems, justifyContent, className, grow, ...filteredProps } = props; const { space, alignItems, justifyContent, className, grow, ...filteredProps } = props;
return ( return (
<div <div
{...filteredProps} {...filteredProps}
ref={ref}
className={classNames('flex flex-col', { className={classNames('flex flex-col', {
// @ts-ignore // @ts-ignore
[spaces[space]]: typeof space !== 'undefined', [spaces[space]]: typeof space !== 'undefined',
@ -54,6 +55,6 @@ const Stack: React.FC<IStack> = (props) => {
}, className)} }, className)}
/> />
); );
}; });
export default Stack; export default Stack;

Wyświetl plik

@ -3,7 +3,7 @@ import React from 'react';
type Themes = 'default' | 'danger' | 'primary' | 'muted' | 'subtle' | 'success' | 'inherit' | 'white' type Themes = 'default' | 'danger' | 'primary' | 'muted' | 'subtle' | 'success' | 'inherit' | 'white'
type Weights = 'normal' | 'medium' | 'semibold' | 'bold' type Weights = 'normal' | 'medium' | 'semibold' | 'bold'
type Sizes = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' export type Sizes = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl'
type Alignments = 'left' | 'center' | 'right' type Alignments = 'left' | 'center' | 'right'
type TrackingSizes = 'normal' | 'wide' type TrackingSizes = 'normal' | 'wide'
type TransformProperties = 'uppercase' | 'normal' type TransformProperties = 'uppercase' | 'normal'

Wyświetl plik

@ -74,6 +74,7 @@ const messages = defineMessages({
suggestUser: { id: 'admin.users.actions.suggest_user', defaultMessage: 'Suggest @{name}' }, suggestUser: { id: 'admin.users.actions.suggest_user', defaultMessage: 'Suggest @{name}' },
unsuggestUser: { id: 'admin.users.actions.unsuggest_user', defaultMessage: 'Unsuggest @{name}' }, unsuggestUser: { id: 'admin.users.actions.unsuggest_user', defaultMessage: 'Unsuggest @{name}' },
search: { id: 'account.search', defaultMessage: 'Search from @{name}' }, search: { id: 'account.search', defaultMessage: 'Search from @{name}' },
searchSelf: { id: 'account.search_self', defaultMessage: 'Search your posts' },
unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' }, unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' }, blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' },
@ -378,6 +379,13 @@ const Header: React.FC<IHeader> = ({ account }) => {
to: '/settings', to: '/settings',
icon: require('@tabler/icons/settings.svg'), icon: require('@tabler/icons/settings.svg'),
}); });
if (features.searchFromAccount) {
menu.push({
text: intl.formatMessage(messages.searchSelf, { name: account.username }),
action: onSearch,
icon: require('@tabler/icons/search.svg'),
});
}
menu.push(null); menu.push(null);
menu.push({ menu.push({
text: intl.formatMessage(messages.mutes), text: intl.formatMessage(messages.mutes),

Wyświetl plik

@ -9,6 +9,7 @@ import { useHistory } from 'react-router-dom';
import { import {
changeSearch, changeSearch,
clearSearch, clearSearch,
clearSearchResults,
setSearchAccount, setSearchAccount,
showSearch, showSearch,
submitSearch, submitSearch,
@ -72,7 +73,7 @@ const Search = (props: ISearch) => {
event.preventDefault(); event.preventDefault();
if (value.length > 0 || submitted) { if (value.length > 0 || submitted) {
dispatch(clearSearch()); dispatch(clearSearchResults());
} }
}; };
@ -115,27 +116,34 @@ const Search = (props: ISearch) => {
]; ];
const hasValue = value.length > 0 || submitted; const hasValue = value.length > 0 || submitted;
const Component = autosuggest ? AutosuggestAccountInput : 'input'; const componentProps: any = {
className: 'block w-full pl-3 pr-10 py-2 border border-gray-200 dark:border-gray-800 rounded-full leading-5 bg-gray-200 dark:bg-gray-800 dark:text-white placeholder:text-gray-600 dark:placeholder:text-gray-600 focus:outline-none focus:ring-2 focus:ring-primary-500 sm:text-sm',
type: 'text',
id: 'search',
placeholder: intl.formatMessage(messages.placeholder),
value,
onChange: handleChange,
onKeyDown: handleKeyDown,
onFocus: handleFocus,
autoFocus: autoFocus,
};
if (autosuggest) {
componentProps.onSelected = handleSelected;
componentProps.menu = makeMenu();
componentProps.autoSelect = false;
}
return ( return (
<div className='w-full'> <div className='w-full'>
<label htmlFor='search' className='sr-only'>{intl.formatMessage(messages.placeholder)}</label> <label htmlFor='search' className='sr-only'>{intl.formatMessage(messages.placeholder)}</label>
<div className='relative'> <div className='relative'>
<Component {autosuggest ? (
className='block w-full pl-3 pr-10 py-2 border border-gray-200 dark:border-gray-800 rounded-full leading-5 bg-gray-200 dark:bg-gray-800 dark:text-white placeholder:text-gray-600 dark:placeholder:text-gray-600 focus:outline-none focus:ring-2 focus:ring-primary-500 sm:text-sm' <AutosuggestAccountInput {...componentProps} />
type='text' ) : (
id='search' <input {...componentProps} />
placeholder={intl.formatMessage(messages.placeholder)} )}
value={value}
onChange={handleChange}
onKeyDown={handleKeyDown}
onFocus={handleFocus}
onSelected={handleSelected}
autoFocus={autoFocus}
autoSelect={false}
menu={makeMenu()}
/>
<div <div
role='button' role='button'

Wyświetl plik

@ -2,7 +2,7 @@ import classNames from 'clsx';
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
import { clearSearch, expandSearch, setFilter } from 'soapbox/actions/search'; import { expandSearch, setFilter, setSearchAccount } from 'soapbox/actions/search';
import { fetchTrendingStatuses } from 'soapbox/actions/trending_statuses'; import { fetchTrendingStatuses } from 'soapbox/actions/trending_statuses';
import Hashtag from 'soapbox/components/hashtag'; import Hashtag from 'soapbox/components/hashtag';
import IconButton from 'soapbox/components/icon_button'; import IconButton from 'soapbox/components/icon_button';
@ -43,7 +43,7 @@ const SearchResults = () => {
const handleLoadMore = () => dispatch(expandSearch(selectedFilter)); const handleLoadMore = () => dispatch(expandSearch(selectedFilter));
const handleClearSearch = () => dispatch(clearSearch()); const handleUnsetAccount = () => dispatch(setSearchAccount(null));
const selectFilter = (newActiveFilter: SearchFilter) => dispatch(setFilter(newActiveFilter)); const selectFilter = (newActiveFilter: SearchFilter) => dispatch(setFilter(newActiveFilter));
@ -196,7 +196,7 @@ const SearchResults = () => {
<> <>
{filterByAccount ? ( {filterByAccount ? (
<HStack className='mb-4 pb-4 px-2 border-solid border-b border-gray-200 dark:border-gray-800' space={2}> <HStack className='mb-4 pb-4 px-2 border-solid border-b border-gray-200 dark:border-gray-800' space={2}>
<IconButton iconClassName='h-5 w-5' src={require('@tabler/icons/x.svg')} onClick={handleClearSearch} /> <IconButton iconClassName='h-5 w-5' src={require('@tabler/icons/x.svg')} onClick={handleUnsetAccount} />
<Text> <Text>
<FormattedMessage <FormattedMessage
id='search_results.filter_message' id='search_results.filter_message'

Wyświetl plik

@ -0,0 +1,25 @@
let listener: ((rect: any) => void) | undefined = undefined;
const mockDisconnect = jest.fn();
class ResizeObserver {
constructor(ls: any) {
listener = ls;
}
observe() {
// do nothing
}
unobserve() {
// do nothing
}
disconnect() {
mockDisconnect();
}
}
// eslint-disable-next-line compat/compat
(window as any).ResizeObserver = ResizeObserver;
export { ResizeObserver as default, listener, mockDisconnect };

Wyświetl plik

@ -1,21 +1,13 @@
import { renderHook, act } from '@testing-library/react-hooks'; import { renderHook, act } from '@testing-library/react-hooks';
import { listener, mockDisconnect } from '../__mocks__/resize-observer';
import { useDimensions } from '../useDimensions'; import { useDimensions } from '../useDimensions';
let listener: ((rect: any) => void) | undefined = undefined;
(window as any).ResizeObserver = class ResizeObserver {
constructor(ls: any) {
listener = ls;
}
observe() {}
disconnect() {}
};
describe('useDimensions()', () => { describe('useDimensions()', () => {
beforeEach(() => {
mockDisconnect.mockClear();
});
it('defaults to 0', () => { it('defaults to 0', () => {
const { result } = renderHook(() => useDimensions()); const { result } = renderHook(() => useDimensions());
@ -56,16 +48,6 @@ describe('useDimensions()', () => {
}); });
it('disconnects on unmount', () => { it('disconnects on unmount', () => {
const disconnect = jest.fn();
(window as any).ResizeObserver = class ResizeObserver {
observe() {}
disconnect() {
disconnect();
}
};
const { result, unmount } = renderHook(() => useDimensions()); const { result, unmount } = renderHook(() => useDimensions());
act(() => { act(() => {
@ -73,8 +55,8 @@ describe('useDimensions()', () => {
(result.current[1] as any)(div); (result.current[1] as any)(div);
}); });
expect(disconnect).toHaveBeenCalledTimes(0); expect(mockDisconnect).toHaveBeenCalledTimes(0);
unmount(); unmount();
expect(disconnect).toHaveBeenCalledTimes(1); expect(mockDisconnect).toHaveBeenCalledTimes(1);
}); });
}); });

Wyświetl plik

@ -1,4 +1,5 @@
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import ResizeObserver from 'resize-observer-polyfill';
type UseDimensionsRect = { width: number, height: number }; type UseDimensionsRect = { width: number, height: number };
type UseDimensionsResult = [Element | null, any, any] type UseDimensionsResult = [Element | null, any, any]
@ -14,7 +15,7 @@ const useDimensions = (): UseDimensionsResult => {
const observer = useMemo( const observer = useMemo(
() => () =>
new (window as any).ResizeObserver((entries: any) => { new ResizeObserver((entries: any) => {
if (entries[0]) { if (entries[0]) {
const { width, height } = entries[0].contentRect; const { width, height } = entries[0].contentRect;
setRect({ width, height }); setRect({ width, height });

Wyświetl plik

@ -18,6 +18,7 @@ import {
SEARCH_EXPAND_REQUEST, SEARCH_EXPAND_REQUEST,
SEARCH_EXPAND_SUCCESS, SEARCH_EXPAND_SUCCESS,
SEARCH_ACCOUNT_SET, SEARCH_ACCOUNT_SET,
SEARCH_RESULTS_CLEAR,
} from '../actions/search'; } from '../actions/search';
import type { AnyAction } from 'redux'; import type { AnyAction } from 'redux';
@ -105,6 +106,13 @@ export default function search(state = ReducerRecord(), action: AnyAction) {
return state.set('value', action.value); return state.set('value', action.value);
case SEARCH_CLEAR: case SEARCH_CLEAR:
return ReducerRecord(); return ReducerRecord();
case SEARCH_RESULTS_CLEAR:
return state.merge({
value: '',
results: ResultsRecord(),
submitted: false,
submittedValue: '',
});
case SEARCH_SHOW: case SEARCH_SHOW:
return state.set('hidden', false); return state.set('hidden', false);
case COMPOSE_REPLY: case COMPOSE_REPLY:
@ -123,7 +131,13 @@ export default function search(state = ReducerRecord(), action: AnyAction) {
case SEARCH_EXPAND_SUCCESS: case SEARCH_EXPAND_SUCCESS:
return paginateResults(state, action.searchType, action.results, action.searchTerm); return paginateResults(state, action.searchType, action.results, action.searchTerm);
case SEARCH_ACCOUNT_SET: case SEARCH_ACCOUNT_SET:
if (!action.accountId) return state.set('accountId', null); if (!action.accountId) return state.merge({
results: ResultsRecord(),
submitted: false,
submittedValue: '',
filter: 'accounts',
accountId: null,
});
return ReducerRecord({ accountId: action.accountId, filter: 'statuses' }); return ReducerRecord({ accountId: action.accountId, filter: 'statuses' });
default: default:
return state; return state;

Wyświetl plik

@ -181,6 +181,7 @@
"redux-thunk": "^2.2.0", "redux-thunk": "^2.2.0",
"requestidlecallback": "^0.3.0", "requestidlecallback": "^0.3.0",
"reselect": "^4.0.0", "reselect": "^4.0.0",
"resize-observer-polyfill": "^1.5.1",
"sass": "^1.20.3", "sass": "^1.20.3",
"sass-loader": "^13.0.0", "sass-loader": "^13.0.0",
"semver": "^7.3.2", "semver": "^7.3.2",