mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-27 21:26:41 +00:00
[Glitch] Wrapstodon: Add nav modal
Port e206b0d0de to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
@@ -11,7 +11,7 @@ export interface AnnualReportAnnouncementProps {
|
||||
year: string;
|
||||
state: Exclude<ApiAnnualReportState, 'ineligible'>;
|
||||
onRequestBuild: () => void;
|
||||
onOpen: () => void;
|
||||
onOpen?: () => void; // This is optional when inside the modal, as it won't be shown then.
|
||||
onDismiss: () => void;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
var(--color-bg-primary);
|
||||
border-bottom: 1px solid var(--color-border-primary);
|
||||
position: relative;
|
||||
pointer-events: all;
|
||||
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
@@ -34,4 +35,8 @@
|
||||
right: 8px;
|
||||
margin-inline: 0;
|
||||
}
|
||||
|
||||
:global(.modal-root__modal) & {
|
||||
border-radius: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,3 +332,7 @@ $mobile-breakpoint: 540px;
|
||||
left: 0;
|
||||
mix-blend-mode: screen;
|
||||
}
|
||||
|
||||
.navItemBadge {
|
||||
background: var(--color-bg-brand-soft);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,11 @@ import { closeModal } from '@/flavours/glitch/actions/modal';
|
||||
import { IconButton } from '@/flavours/glitch/components/icon_button';
|
||||
import { LoadingIndicator } from '@/flavours/glitch/components/loading_indicator';
|
||||
import { me } from '@/flavours/glitch/initial_state';
|
||||
import { useAppDispatch, useAppSelector } from '@/flavours/glitch/store';
|
||||
import {
|
||||
createAppSelector,
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
} from '@/flavours/glitch/store';
|
||||
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
|
||||
|
||||
import { Archetype } from './archetype';
|
||||
@@ -23,21 +27,26 @@ import { NewPosts } from './new_posts';
|
||||
|
||||
const moduleClassNames = classNames.bind(styles);
|
||||
|
||||
const accountSelector = createAppSelector(
|
||||
[(state) => state.accounts, (state) => state.annualReport.report],
|
||||
(accounts, report) => {
|
||||
if (me) {
|
||||
return accounts.get(me);
|
||||
}
|
||||
if (report?.schema_version === 2) {
|
||||
return accounts.get(report.account_id);
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
);
|
||||
|
||||
export const AnnualReport: FC<{ context?: 'modal' | 'standalone' }> = ({
|
||||
context = 'standalone',
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const report = useAppSelector((state) => state.annualReport.report);
|
||||
const account = useAppSelector((state) => {
|
||||
if (me) {
|
||||
return state.accounts.get(me);
|
||||
}
|
||||
if (report?.schema_version === 2) {
|
||||
return state.accounts.get(report.account_id);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
const account = useAppSelector(accountSelector);
|
||||
|
||||
const close = useCallback(() => {
|
||||
dispatch(closeModal({ modalType: 'ANNUAL_REPORT', ignoreFocus: false }));
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import type { MouseEventHandler } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { closeModal } from '@/flavours/glitch/actions/modal';
|
||||
import { useAppDispatch } from '@/flavours/glitch/store';
|
||||
import {
|
||||
generateReport,
|
||||
selectWrapstodonYear,
|
||||
} from '@/flavours/glitch/reducers/slices/annual_report';
|
||||
import { useAppDispatch, useAppSelector } from '@/flavours/glitch/store';
|
||||
|
||||
import { AnnualReport } from '.';
|
||||
import { AnnualReportAnnouncement } from './announcement';
|
||||
import styles from './index.module.scss';
|
||||
|
||||
const AnnualReportModal: React.FC<{
|
||||
@@ -15,17 +21,42 @@ const AnnualReportModal: React.FC<{
|
||||
onChangeBackgroundColor('var(--color-bg-media-base)');
|
||||
}, [onChangeBackgroundColor]);
|
||||
|
||||
const { state } = useAppSelector((state) => state.annualReport);
|
||||
const year = useAppSelector(selectWrapstodonYear);
|
||||
|
||||
const showAnnouncement = year && state && state !== 'available';
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const handleCloseModal = useCallback<React.MouseEventHandler<HTMLDivElement>>(
|
||||
|
||||
const handleBuildRequest = useCallback(() => {
|
||||
void dispatch(generateReport());
|
||||
}, [dispatch]);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
dispatch(closeModal({ modalType: 'ANNUAL_REPORT', ignoreFocus: false }));
|
||||
}, [dispatch]);
|
||||
|
||||
const handleCloseModal: MouseEventHandler = useCallback(
|
||||
(e) => {
|
||||
if (e.target === e.currentTarget)
|
||||
dispatch(
|
||||
closeModal({ modalType: 'ANNUAL_REPORT', ignoreFocus: false }),
|
||||
);
|
||||
if (e.target === e.currentTarget) {
|
||||
handleClose();
|
||||
}
|
||||
},
|
||||
[dispatch],
|
||||
[handleClose],
|
||||
);
|
||||
|
||||
// Auto-close if ineligible
|
||||
useEffect(() => {
|
||||
if (state === 'ineligible') {
|
||||
handleClose();
|
||||
}
|
||||
}, [handleClose, state]);
|
||||
|
||||
if (state === 'ineligible') {
|
||||
// Not sure how you got here, but don't show anything.
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
// It's fine not to provide a keyboard handler here since there is a global
|
||||
// [Esc] key listener that will close open modals.
|
||||
@@ -40,7 +71,16 @@ const AnnualReportModal: React.FC<{
|
||||
)}
|
||||
onClick={handleCloseModal}
|
||||
>
|
||||
<AnnualReport context='modal' />
|
||||
{!showAnnouncement ? (
|
||||
<AnnualReport context='modal' />
|
||||
) : (
|
||||
<AnnualReportAnnouncement
|
||||
year={year.toString()}
|
||||
state={state}
|
||||
onDismiss={handleClose}
|
||||
onRequestBuild={handleBuildRequest}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { useCallback } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { openModal } from '@/flavours/glitch/actions/modal';
|
||||
import { Icon } from '@/flavours/glitch/components/icon';
|
||||
import { selectWrapstodonYear } from '@/flavours/glitch/reducers/slices/annual_report';
|
||||
import {
|
||||
createAppSelector,
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
} from '@/flavours/glitch/store';
|
||||
import IconPlanet from '@/images/icons/icon_planet.svg?react';
|
||||
|
||||
import classes from './index.module.scss';
|
||||
|
||||
const selectReportModalOpen = createAppSelector(
|
||||
[(state) => state.modal.getIn(['stack', 0, 'modalType'])],
|
||||
(modalType) => modalType === 'ANNUAL_REPORT',
|
||||
);
|
||||
|
||||
export const AnnualReportNavItem: FC = () => {
|
||||
const { state } = useAppSelector((state) => state.annualReport);
|
||||
const year = useAppSelector(selectWrapstodonYear);
|
||||
const active = useAppSelector(selectReportModalOpen);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const handleClick = useCallback(() => {
|
||||
dispatch(openModal({ modalType: 'ANNUAL_REPORT', modalProps: {} }));
|
||||
}, [dispatch]);
|
||||
|
||||
if (!year || !state || state === 'ineligible') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type='button'
|
||||
className={classNames('column-link column-link--transparent', { active })}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<Icon icon={IconPlanet} id='wrapstodon-planet' width='24' height='24' />
|
||||
<span>Wrapstodon {year}</span>
|
||||
<span className={classNames('column-link__badge', classes.navItemBadge)}>
|
||||
<FormattedMessage
|
||||
id='annual_report.nav_item.badge'
|
||||
defaultMessage='New'
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
@@ -51,6 +51,8 @@ import { canViewFeed } from 'flavours/glitch/permissions';
|
||||
import { selectUnreadNotificationGroupsCount } from 'flavours/glitch/selectors/notifications';
|
||||
import { useAppSelector, useAppDispatch } from 'flavours/glitch/store';
|
||||
|
||||
import { AnnualReportNavItem } from '../annual_report/nav_item';
|
||||
|
||||
import { DisabledAccountBanner } from './components/disabled_account_banner';
|
||||
import { FollowedTagsPanel } from './components/followed_tags_panel';
|
||||
import { ListPanel } from './components/list_panel';
|
||||
@@ -318,6 +320,8 @@ export const NavigationPanel: React.FC<{ multiColumn?: boolean }> = ({
|
||||
|
||||
<FollowRequestsLink />
|
||||
|
||||
<AnnualReportNavItem />
|
||||
|
||||
<hr />
|
||||
|
||||
<ListPanel />
|
||||
|
||||
Reference in New Issue
Block a user