Merge branch 'language-dropdown' into 'main'
Add Language Dropdown Feature Closes #1726 See merge request soapbox-pub/soapbox!3128
This commit is contained in:
commit
8730794ae8
|
@ -19,6 +19,7 @@ export type Menu = Array<MenuItem | null>;
|
|||
|
||||
interface IDropdownMenu {
|
||||
children?: React.ReactElement;
|
||||
modal?: boolean;
|
||||
disabled?: boolean;
|
||||
items: Menu;
|
||||
onClose?: () => void;
|
||||
|
@ -35,6 +36,7 @@ const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
|||
const DropdownMenu = (props: IDropdownMenu) => {
|
||||
const {
|
||||
children,
|
||||
modal = false,
|
||||
disabled,
|
||||
items,
|
||||
onClose,
|
||||
|
@ -90,7 +92,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
|
|||
* On mobile screens, let's replace the Popper dropdown with a Modal.
|
||||
*/
|
||||
const handleOpen = () => {
|
||||
if (userTouching.matches) {
|
||||
if (userTouching.matches || modal) {
|
||||
dispatch(
|
||||
openModal('ACTIONS', {
|
||||
status: filteredProps.status,
|
||||
|
@ -111,7 +113,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
|
|||
const handleClose = () => {
|
||||
(refs.reference.current as HTMLButtonElement)?.focus();
|
||||
|
||||
if (userTouching.matches) {
|
||||
if (userTouching.matches || modal) {
|
||||
dispatch(closeModal('ACTIONS'));
|
||||
} else {
|
||||
closeDropdownMenu();
|
||||
|
|
|
@ -59,13 +59,15 @@ export interface IColumn {
|
|||
children?: React.ReactNode;
|
||||
/** Action for the ColumnHeader, displayed at the end. */
|
||||
action?: React.ReactNode;
|
||||
/** Determines if the action for the ColumnHeader is displayed on the right. */
|
||||
actionRightPosition?: boolean;
|
||||
/** Column size, inherited from Card. */
|
||||
size?: CardSizes;
|
||||
}
|
||||
|
||||
/** A backdrop for the main section of the UI. */
|
||||
const Column = React.forwardRef<HTMLDivElement, IColumn>((props, ref): JSX.Element => {
|
||||
const { backHref, children, label, transparent = false, withHeader = true, className, bodyClassName, action, size } = props;
|
||||
const { backHref, children, label, transparent = false, withHeader = true, className, bodyClassName, action, actionRightPosition, size } = props;
|
||||
const soapboxConfig = useSoapboxConfig();
|
||||
const [isScrolled, setIsScrolled] = useState(false);
|
||||
|
||||
|
@ -106,11 +108,11 @@ const Column = React.forwardRef<HTMLDivElement, IColumn>((props, ref): JSX.Eleme
|
|||
'p-4 sm:p-0 sm:pb-4 black:p-4': transparent,
|
||||
'-mt-4 p-4': size !== 'lg' && !transparent,
|
||||
'-mt-4 p-4 sm:-mt-6 sm:-mx-6 sm:p-6': size === 'lg' && !transparent,
|
||||
'w-full': actionRightPosition,
|
||||
})}
|
||||
action={action}
|
||||
/>
|
||||
)}
|
||||
|
||||
<CardBody className={bodyClassName}>
|
||||
{children}
|
||||
</CardBody>
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
import React, { useState } from 'react';
|
||||
|
||||
import { openDropdownMenu } from 'soapbox/actions/dropdown-menu';
|
||||
import { clearTimeline, expandPublicTimeline } from 'soapbox/actions/timelines';
|
||||
import DropdownMenu from 'soapbox/components/dropdown-menu';
|
||||
import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
||||
import { languages } from 'soapbox/features/preferences';
|
||||
import { useAppDispatch } from 'soapbox/hooks';
|
||||
|
||||
const formatterLanguage = (lang: {}) => {
|
||||
|
||||
const sigLanguage = Object.keys(lang).sort().map((sig) => {
|
||||
return sig.substring(0, 2);
|
||||
});
|
||||
|
||||
return [...new Set(sigLanguage)];
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const LanguageDropdown = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const [languageIcon, setLanguageIcon] = useState('');
|
||||
|
||||
const handleChangeLanguage = (language?: string) => {
|
||||
if (language) {
|
||||
dispatch(clearTimeline('public'));
|
||||
dispatch(expandPublicTimeline({ url: `/api/v1/timelines/public?language=${language}` }));
|
||||
} else {
|
||||
dispatch(clearTimeline('public'));
|
||||
dispatch(expandPublicTimeline({ url: '/api/v1/timelines/public' }));
|
||||
}
|
||||
};
|
||||
|
||||
const formattedLanguage = formatterLanguage(languages);
|
||||
|
||||
const newMenu: any[] = [{ icon: require('@tabler/icons/outline/world.svg'), text: 'Default', action: () => {
|
||||
setLanguageIcon('');
|
||||
handleChangeLanguage();
|
||||
} }];
|
||||
|
||||
formattedLanguage.map((lg: string) => {
|
||||
const languageText = languages[lg as keyof typeof languages];
|
||||
|
||||
if (languageText !== undefined) {
|
||||
newMenu.push({
|
||||
text: `${lg.toUpperCase()} - ${languageText}`,
|
||||
action: () => {
|
||||
setLanguageIcon(lg.toUpperCase());
|
||||
handleChangeLanguage(lg);
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return (
|
||||
<DropdownMenu items={newMenu} modal>
|
||||
{ languageIcon === '' ?
|
||||
<SvgIcon src={require('@tabler/icons/outline/world.svg')} className='text-gray-700 hover:cursor-pointer hover:text-gray-500 black:absolute black:right-0 black:top-4 black:text-white black:hover:text-gray-600 sm:mr-4' />
|
||||
|
||||
:
|
||||
<button type='button' className='flex h-full rounded-lg border-2 border-gray-700 px-1 text-gray-700 hover:cursor-pointer hover:border-gray-500 hover:text-gray-500 sm:mr-4 dark:border-white dark:text-white dark:hover:border-gray-700' onClick={() => dispatch(openDropdownMenu())}>
|
||||
{languageIcon}
|
||||
</button>
|
||||
}
|
||||
</DropdownMenu>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export { LanguageDropdown };
|
|
@ -3,10 +3,11 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { changeSetting } from 'soapbox/actions/settings';
|
||||
import { expandPublicTimeline } from 'soapbox/actions/timelines';
|
||||
import { clearTimeline, expandPublicTimeline } from 'soapbox/actions/timelines';
|
||||
import { usePublicStream } from 'soapbox/api/hooks';
|
||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||
import { Accordion, Column } from 'soapbox/components/ui';
|
||||
import { LanguageDropdown } from 'soapbox/components/ui/language-dropdown/language-dropdown';
|
||||
import { useAppSelector, useAppDispatch, useInstance, useSettings, useTheme, useFeatures } from 'soapbox/hooks';
|
||||
import { useIsMobile } from 'soapbox/hooks/useIsMobile';
|
||||
|
||||
|
@ -57,8 +58,13 @@ const PublicTimeline = () => {
|
|||
dispatch(expandPublicTimeline({ onlyMedia }));
|
||||
}, [onlyMedia]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(clearTimeline('public'));
|
||||
dispatch(expandPublicTimeline({ url: '/api/v1/timelines/public' }));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Column className='-mt-3 sm:mt-0' label={intl.formatMessage(messages.title)} transparent={!isMobile}>
|
||||
<Column className='-mt-3 sm:mt-0' label={intl.formatMessage(messages.title)} transparent={!isMobile} action={<LanguageDropdown />} actionRightPosition>
|
||||
<PinnedHostsPicker />
|
||||
|
||||
{showExplanationBox && (
|
||||
|
|
Loading…
Reference in New Issue