mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-22 14:58:16 +00:00
Wrapstodon: Load report data only on display (#37269)
This commit is contained in:
@@ -1,5 +1,3 @@
|
|||||||
import { checkAnnualReport } from '@/mastodon/reducers/slices/annual_report';
|
|
||||||
|
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
|
|
||||||
import { importFetchedAccount } from './importer';
|
import { importFetchedAccount } from './importer';
|
||||||
@@ -31,9 +29,6 @@ export const fetchServer = () => (dispatch, getState) => {
|
|||||||
.get('/api/v2/instance').then(({ data }) => {
|
.get('/api/v2/instance').then(({ data }) => {
|
||||||
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
|
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
|
||||||
dispatch(fetchServerSuccess(data));
|
dispatch(fetchServerSuccess(data));
|
||||||
if (data.wrapstodon) {
|
|
||||||
void dispatch(checkAnnualReport());
|
|
||||||
}
|
|
||||||
}).catch(err => dispatch(fetchServerFail(err)));
|
}).catch(err => dispatch(fetchServerFail(err)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import classNames from 'classnames/bind';
|
|||||||
import { closeModal } from '@/mastodon/actions/modal';
|
import { closeModal } from '@/mastodon/actions/modal';
|
||||||
import { IconButton } from '@/mastodon/components/icon_button';
|
import { IconButton } from '@/mastodon/components/icon_button';
|
||||||
import { LoadingIndicator } from '@/mastodon/components/loading_indicator';
|
import { LoadingIndicator } from '@/mastodon/components/loading_indicator';
|
||||||
|
import { getReport } from '@/mastodon/reducers/slices/annual_report';
|
||||||
import {
|
import {
|
||||||
createAppSelector,
|
createAppSelector,
|
||||||
useAppDispatch,
|
useAppDispatch,
|
||||||
@@ -43,6 +44,13 @@ export const AnnualReport: FC<{ context?: 'modal' | 'standalone' }> = ({
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const report = useAppSelector((state) => state.annualReport.report);
|
const report = useAppSelector((state) => state.annualReport.report);
|
||||||
const account = useAppSelector(accountSelector);
|
const account = useAppSelector(accountSelector);
|
||||||
|
const needsReport = !report; // Make into boolean to avoid object comparison in deps.
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (needsReport) {
|
||||||
|
void dispatch(getReport());
|
||||||
|
}
|
||||||
|
}, [dispatch, needsReport]);
|
||||||
|
|
||||||
const close = useCallback(() => {
|
const close = useCallback(() => {
|
||||||
dispatch(closeModal({ modalType: 'ANNUAL_REPORT', ignoreFocus: false }));
|
dispatch(closeModal({ modalType: 'ANNUAL_REPORT', ignoreFocus: false }));
|
||||||
@@ -57,7 +65,7 @@ export const AnnualReport: FC<{ context?: 'modal' | 'standalone' }> = ({
|
|||||||
}
|
}
|
||||||
}, [pathname, initialPathname, close]);
|
}, [pathname, initialPathname, close]);
|
||||||
|
|
||||||
if (!report) {
|
if (needsReport) {
|
||||||
return <LoadingIndicator />;
|
return <LoadingIndicator />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,7 @@ import { useCallback, useEffect } from 'react';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { closeModal } from '@/mastodon/actions/modal';
|
import { closeModal } from '@/mastodon/actions/modal';
|
||||||
import {
|
import { generateReport } from '@/mastodon/reducers/slices/annual_report';
|
||||||
generateReport,
|
|
||||||
selectWrapstodonYear,
|
|
||||||
} from '@/mastodon/reducers/slices/annual_report';
|
|
||||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||||
|
|
||||||
import { AnnualReport } from '.';
|
import { AnnualReport } from '.';
|
||||||
@@ -21,8 +18,7 @@ const AnnualReportModal: React.FC<{
|
|||||||
onChangeBackgroundColor('var(--color-bg-media-base)');
|
onChangeBackgroundColor('var(--color-bg-media-base)');
|
||||||
}, [onChangeBackgroundColor]);
|
}, [onChangeBackgroundColor]);
|
||||||
|
|
||||||
const { state } = useAppSelector((state) => state.annualReport);
|
const { state, year } = useAppSelector((state) => state.annualReport);
|
||||||
const year = useAppSelector(selectWrapstodonYear);
|
|
||||||
|
|
||||||
const showAnnouncement = year && state && state !== 'available';
|
const showAnnouncement = year && state && state !== 'available';
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import classNames from 'classnames';
|
|||||||
import IconPlanet from '@/images/icons/icon_planet.svg?react';
|
import IconPlanet from '@/images/icons/icon_planet.svg?react';
|
||||||
import { openModal } from '@/mastodon/actions/modal';
|
import { openModal } from '@/mastodon/actions/modal';
|
||||||
import { Icon } from '@/mastodon/components/icon';
|
import { Icon } from '@/mastodon/components/icon';
|
||||||
import { selectWrapstodonYear } from '@/mastodon/reducers/slices/annual_report';
|
|
||||||
import {
|
import {
|
||||||
createAppSelector,
|
createAppSelector,
|
||||||
useAppDispatch,
|
useAppDispatch,
|
||||||
@@ -23,8 +22,7 @@ const selectReportModalOpen = createAppSelector(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const AnnualReportNavItem: FC = () => {
|
export const AnnualReportNavItem: FC = () => {
|
||||||
const { state } = useAppSelector((state) => state.annualReport);
|
const { state, year } = useAppSelector((state) => state.annualReport);
|
||||||
const year = useAppSelector(selectWrapstodonYear);
|
|
||||||
const active = useAppSelector(selectReportModalOpen);
|
const active = useAppSelector(selectReportModalOpen);
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|||||||
@@ -3,17 +3,13 @@ import type { FC } from 'react';
|
|||||||
|
|
||||||
import { openModal } from '@/mastodon/actions/modal';
|
import { openModal } from '@/mastodon/actions/modal';
|
||||||
import { useDismissible } from '@/mastodon/hooks/useDismissible';
|
import { useDismissible } from '@/mastodon/hooks/useDismissible';
|
||||||
import {
|
import { generateReport } from '@/mastodon/reducers/slices/annual_report';
|
||||||
generateReport,
|
|
||||||
selectWrapstodonYear,
|
|
||||||
} from '@/mastodon/reducers/slices/annual_report';
|
|
||||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||||
|
|
||||||
import { AnnualReportAnnouncement } from './announcement';
|
import { AnnualReportAnnouncement } from './announcement';
|
||||||
|
|
||||||
export const AnnualReportTimeline: FC = () => {
|
export const AnnualReportTimeline: FC = () => {
|
||||||
const { state } = useAppSelector((state) => state.annualReport);
|
const { state, year } = useAppSelector((state) => state.annualReport);
|
||||||
const year = useAppSelector(selectWrapstodonYear);
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const handleBuildRequest = useCallback(() => {
|
const handleBuildRequest = useCallback(() => {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { PictureInPicture } from 'mastodon/features/picture_in_picture';
|
|||||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||||
import { layoutFromWindow } from 'mastodon/is_mobile';
|
import { layoutFromWindow } from 'mastodon/is_mobile';
|
||||||
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
import { checkAnnualReport } from '@/mastodon/reducers/slices/annual_report';
|
||||||
|
|
||||||
import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose';
|
import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose';
|
||||||
import { clearHeight } from '../../actions/height_cache';
|
import { clearHeight } from '../../actions/height_cache';
|
||||||
@@ -396,6 +397,7 @@ class UI extends PureComponent {
|
|||||||
this.props.dispatch(expandHomeTimeline());
|
this.props.dispatch(expandHomeTimeline());
|
||||||
this.props.dispatch(fetchNotifications());
|
this.props.dispatch(fetchNotifications());
|
||||||
this.props.dispatch(fetchServerTranslationLanguages());
|
this.props.dispatch(fetchServerTranslationLanguages());
|
||||||
|
this.props.dispatch(checkAnnualReport());
|
||||||
|
|
||||||
setTimeout(() => this.props.dispatch(fetchServer()), 3000);
|
setTimeout(() => this.props.dispatch(fetchServer()), 3000);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
|
import type { ApiAnnualReportState } from './api/annual_report';
|
||||||
import type { ApiAccountJSON } from './api_types/accounts';
|
import type { ApiAccountJSON } from './api_types/accounts';
|
||||||
|
|
||||||
type InitialStateLanguage = [code: string, name: string, localName: string];
|
type InitialStateLanguage = [code: string, name: string, localName: string];
|
||||||
|
|
||||||
interface InitialWrapstodonState {
|
|
||||||
year: number;
|
|
||||||
state: 'available' | 'generating' | 'eligible' | 'ineligible';
|
|
||||||
}
|
|
||||||
|
|
||||||
interface InitialStateMeta {
|
interface InitialStateMeta {
|
||||||
access_token: string;
|
access_token: string;
|
||||||
advanced_layout?: boolean;
|
advanced_layout?: boolean;
|
||||||
@@ -63,6 +59,11 @@ interface Role {
|
|||||||
highlighted: boolean;
|
highlighted: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface InitialWrapstodonState {
|
||||||
|
year: number;
|
||||||
|
state: ApiAnnualReportState;
|
||||||
|
}
|
||||||
|
|
||||||
export interface InitialState {
|
export interface InitialState {
|
||||||
accounts: Record<string, ApiAccountJSON>;
|
accounts: Record<string, ApiAccountJSON>;
|
||||||
languages: InitialStateLanguage[];
|
languages: InitialStateLanguage[];
|
||||||
|
|||||||
@@ -13,12 +13,10 @@ import {
|
|||||||
} from '@/mastodon/api/annual_report';
|
} from '@/mastodon/api/annual_report';
|
||||||
import { wrapstodon } from '@/mastodon/initial_state';
|
import { wrapstodon } from '@/mastodon/initial_state';
|
||||||
import type { AnnualReport } from '@/mastodon/models/annual_report';
|
import type { AnnualReport } from '@/mastodon/models/annual_report';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createAppSelector,
|
|
||||||
createAppThunk,
|
createAppThunk,
|
||||||
createDataLoadingThunk,
|
createDataLoadingThunk,
|
||||||
} from '../../store/typed_functions';
|
} from '@/mastodon/store/typed_functions';
|
||||||
|
|
||||||
interface AnnualReportState {
|
interface AnnualReportState {
|
||||||
year?: number;
|
year?: number;
|
||||||
@@ -57,18 +55,17 @@ const annualReportSlice = createSlice({
|
|||||||
export const annualReport = annualReportSlice.reducer;
|
export const annualReport = annualReportSlice.reducer;
|
||||||
export const { setReport } = annualReportSlice.actions;
|
export const { setReport } = annualReportSlice.actions;
|
||||||
|
|
||||||
export const selectWrapstodonYear = createAppSelector(
|
// Called on initial load to check if we need to refresh the report state.
|
||||||
[(state) => state.annualReport.year],
|
|
||||||
(year: number | null | undefined) => year ?? null,
|
|
||||||
);
|
|
||||||
|
|
||||||
// This kicks everything off, and is called after fetching the server info.
|
|
||||||
export const checkAnnualReport = createAppThunk(
|
export const checkAnnualReport = createAppThunk(
|
||||||
`${annualReportSlice.name}/checkAnnualReport`,
|
`${annualReportSlice.name}/checkAnnualReport`,
|
||||||
(_arg: unknown, { dispatch, getState }) => {
|
(_arg: unknown, { dispatch, getState }) => {
|
||||||
const year = selectWrapstodonYear(getState());
|
const { state, year } = getState().annualReport;
|
||||||
const me = getState().meta.get('me') as string;
|
const me = getState().meta.get('me') as string;
|
||||||
if (!year || !me) {
|
|
||||||
|
// If we have a state, we only need to fetch it again to poll for changes.
|
||||||
|
const needsStateRefresh = !state || state === 'generating';
|
||||||
|
|
||||||
|
if (!year || !me || !needsStateRefresh) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void dispatch(fetchReportState());
|
void dispatch(fetchReportState());
|
||||||
@@ -78,7 +75,7 @@ export const checkAnnualReport = createAppThunk(
|
|||||||
const fetchReportState = createDataLoadingThunk(
|
const fetchReportState = createDataLoadingThunk(
|
||||||
`${annualReportSlice.name}/fetchReportState`,
|
`${annualReportSlice.name}/fetchReportState`,
|
||||||
async (_arg: unknown, { getState }) => {
|
async (_arg: unknown, { getState }) => {
|
||||||
const year = selectWrapstodonYear(getState());
|
const { year } = getState().annualReport;
|
||||||
if (!year) {
|
if (!year) {
|
||||||
throw new Error('Year is not set');
|
throw new Error('Year is not set');
|
||||||
}
|
}
|
||||||
@@ -89,8 +86,6 @@ const fetchReportState = createDataLoadingThunk(
|
|||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
void dispatch(fetchReportState());
|
void dispatch(fetchReportState());
|
||||||
}, 1_000 * refresh.retry);
|
}, 1_000 * refresh.retry);
|
||||||
} else if (state === 'available') {
|
|
||||||
void dispatch(getReport());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
@@ -102,7 +97,7 @@ const fetchReportState = createDataLoadingThunk(
|
|||||||
export const generateReport = createDataLoadingThunk(
|
export const generateReport = createDataLoadingThunk(
|
||||||
`${annualReportSlice.name}/generateReport`,
|
`${annualReportSlice.name}/generateReport`,
|
||||||
async (_arg: unknown, { getState }) => {
|
async (_arg: unknown, { getState }) => {
|
||||||
const year = selectWrapstodonYear(getState());
|
const { year } = getState().annualReport;
|
||||||
if (!year) {
|
if (!year) {
|
||||||
throw new Error('Year is not set');
|
throw new Error('Year is not set');
|
||||||
}
|
}
|
||||||
@@ -116,7 +111,7 @@ export const generateReport = createDataLoadingThunk(
|
|||||||
export const getReport = createDataLoadingThunk(
|
export const getReport = createDataLoadingThunk(
|
||||||
`${annualReportSlice.name}/getReport`,
|
`${annualReportSlice.name}/getReport`,
|
||||||
async (_arg: unknown, { getState }) => {
|
async (_arg: unknown, { getState }) => {
|
||||||
const year = selectWrapstodonYear(getState());
|
const { year } = getState().annualReport;
|
||||||
if (!year) {
|
if (!year) {
|
||||||
throw new Error('Year is not set');
|
throw new Error('Year is not set');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user