diff --git a/app/javascript/flavours/glitch/actions/server.js b/app/javascript/flavours/glitch/actions/server.js
index e35c25f524..32ee093afa 100644
--- a/app/javascript/flavours/glitch/actions/server.js
+++ b/app/javascript/flavours/glitch/actions/server.js
@@ -1,5 +1,3 @@
-import { checkAnnualReport } from '@/flavours/glitch/reducers/slices/annual_report';
-
import api from '../api';
import { importFetchedAccount } from './importer';
@@ -31,9 +29,6 @@ export const fetchServer = () => (dispatch, getState) => {
.get('/api/v2/instance').then(({ data }) => {
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
dispatch(fetchServerSuccess(data));
- if (data.wrapstodon) {
- void dispatch(checkAnnualReport());
- }
}).catch(err => dispatch(fetchServerFail(err)));
};
diff --git a/app/javascript/flavours/glitch/features/annual_report/index.tsx b/app/javascript/flavours/glitch/features/annual_report/index.tsx
index f796b0c967..ea88a168cf 100644
--- a/app/javascript/flavours/glitch/features/annual_report/index.tsx
+++ b/app/javascript/flavours/glitch/features/annual_report/index.tsx
@@ -10,6 +10,7 @@ import classNames from 'classnames/bind';
import { closeModal } from '@/flavours/glitch/actions/modal';
import { IconButton } from '@/flavours/glitch/components/icon_button';
import { LoadingIndicator } from '@/flavours/glitch/components/loading_indicator';
+import { getReport } from '@/flavours/glitch/reducers/slices/annual_report';
import {
createAppSelector,
useAppDispatch,
@@ -43,6 +44,13 @@ export const AnnualReport: FC<{ context?: 'modal' | 'standalone' }> = ({
const dispatch = useAppDispatch();
const report = useAppSelector((state) => state.annualReport.report);
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(() => {
dispatch(closeModal({ modalType: 'ANNUAL_REPORT', ignoreFocus: false }));
@@ -57,7 +65,7 @@ export const AnnualReport: FC<{ context?: 'modal' | 'standalone' }> = ({
}
}, [pathname, initialPathname, close]);
- if (!report) {
+ if (needsReport) {
return ;
}
diff --git a/app/javascript/flavours/glitch/features/annual_report/modal.tsx b/app/javascript/flavours/glitch/features/annual_report/modal.tsx
index 7c2cec8d89..29034de6b9 100644
--- a/app/javascript/flavours/glitch/features/annual_report/modal.tsx
+++ b/app/javascript/flavours/glitch/features/annual_report/modal.tsx
@@ -4,10 +4,7 @@ import { useCallback, useEffect } from 'react';
import classNames from 'classnames';
import { closeModal } from '@/flavours/glitch/actions/modal';
-import {
- generateReport,
- selectWrapstodonYear,
-} from '@/flavours/glitch/reducers/slices/annual_report';
+import { generateReport } from '@/flavours/glitch/reducers/slices/annual_report';
import { useAppDispatch, useAppSelector } from '@/flavours/glitch/store';
import { AnnualReport } from '.';
@@ -21,8 +18,7 @@ const AnnualReportModal: React.FC<{
onChangeBackgroundColor('var(--color-bg-media-base)');
}, [onChangeBackgroundColor]);
- const { state } = useAppSelector((state) => state.annualReport);
- const year = useAppSelector(selectWrapstodonYear);
+ const { state, year } = useAppSelector((state) => state.annualReport);
const showAnnouncement = year && state && state !== 'available';
diff --git a/app/javascript/flavours/glitch/features/annual_report/nav_item.tsx b/app/javascript/flavours/glitch/features/annual_report/nav_item.tsx
index f67b99f01a..8ac9826612 100644
--- a/app/javascript/flavours/glitch/features/annual_report/nav_item.tsx
+++ b/app/javascript/flavours/glitch/features/annual_report/nav_item.tsx
@@ -7,7 +7,6 @@ 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,
@@ -23,8 +22,7 @@ const selectReportModalOpen = createAppSelector(
);
export const AnnualReportNavItem: FC = () => {
- const { state } = useAppSelector((state) => state.annualReport);
- const year = useAppSelector(selectWrapstodonYear);
+ const { state, year } = useAppSelector((state) => state.annualReport);
const active = useAppSelector(selectReportModalOpen);
const dispatch = useAppDispatch();
diff --git a/app/javascript/flavours/glitch/features/annual_report/timeline.tsx b/app/javascript/flavours/glitch/features/annual_report/timeline.tsx
index 82b26cdab8..a56ac379e6 100644
--- a/app/javascript/flavours/glitch/features/annual_report/timeline.tsx
+++ b/app/javascript/flavours/glitch/features/annual_report/timeline.tsx
@@ -3,17 +3,13 @@ import type { FC } from 'react';
import { openModal } from '@/flavours/glitch/actions/modal';
import { useDismissible } from '@/flavours/glitch/hooks/useDismissible';
-import {
- generateReport,
- selectWrapstodonYear,
-} from '@/flavours/glitch/reducers/slices/annual_report';
+import { generateReport } from '@/flavours/glitch/reducers/slices/annual_report';
import { useAppDispatch, useAppSelector } from '@/flavours/glitch/store';
import { AnnualReportAnnouncement } from './announcement';
export const AnnualReportTimeline: FC = () => {
- const { state } = useAppSelector((state) => state.annualReport);
- const year = useAppSelector(selectWrapstodonYear);
+ const { state, year } = useAppSelector((state) => state.annualReport);
const dispatch = useAppDispatch();
const handleBuildRequest = useCallback(() => {
diff --git a/app/javascript/flavours/glitch/features/ui/index.jsx b/app/javascript/flavours/glitch/features/ui/index.jsx
index 9cf4b2372e..858bdd1a7b 100644
--- a/app/javascript/flavours/glitch/features/ui/index.jsx
+++ b/app/javascript/flavours/glitch/features/ui/index.jsx
@@ -24,6 +24,7 @@ import { identityContextPropShape, withIdentity } from 'flavours/glitch/identity
import { layoutFromWindow } from 'flavours/glitch/is_mobile';
import { selectUnreadNotificationGroupsCount } from 'flavours/glitch/selectors/notifications';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
+import { checkAnnualReport } from '@/flavours/glitch/reducers/slices/annual_report';
import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose';
import { clearHeight } from '../../actions/height_cache';
@@ -411,6 +412,7 @@ class UI extends PureComponent {
this.props.dispatch(expandHomeTimeline());
this.props.dispatch(fetchNotifications());
this.props.dispatch(fetchServerTranslationLanguages());
+ this.props.dispatch(checkAnnualReport());
setTimeout(() => this.props.dispatch(fetchServer()), 3000);
}
diff --git a/app/javascript/flavours/glitch/initial_state.ts b/app/javascript/flavours/glitch/initial_state.ts
index 670969e70d..615dc2848e 100644
--- a/app/javascript/flavours/glitch/initial_state.ts
+++ b/app/javascript/flavours/glitch/initial_state.ts
@@ -1,12 +1,8 @@
+import type { ApiAnnualReportState } from './api/annual_report';
import type { ApiAccountJSON } from './api_types/accounts';
type InitialStateLanguage = [code: string, name: string, localName: string];
-interface InitialWrapstodonState {
- year: number;
- state: 'available' | 'generating' | 'eligible' | 'ineligible';
-}
-
interface InitialStateMeta {
access_token: string;
advanced_layout?: boolean;
@@ -73,6 +69,11 @@ interface PollLimits {
max_expiration: number;
}
+interface InitialWrapstodonState {
+ year: number;
+ state: ApiAnnualReportState;
+}
+
export interface InitialState {
accounts: Record;
languages: InitialStateLanguage[];
diff --git a/app/javascript/flavours/glitch/reducers/slices/annual_report.ts b/app/javascript/flavours/glitch/reducers/slices/annual_report.ts
index 0d159f947e..23160a0f89 100644
--- a/app/javascript/flavours/glitch/reducers/slices/annual_report.ts
+++ b/app/javascript/flavours/glitch/reducers/slices/annual_report.ts
@@ -11,22 +11,25 @@ import {
apiGetAnnualReportState,
apiRequestGenerateAnnualReport,
} from '@/flavours/glitch/api/annual_report';
+import { wrapstodon } from '@/flavours/glitch/initial_state';
import type { AnnualReport } from '@/flavours/glitch/models/annual_report';
-
import {
- createAppSelector,
createAppThunk,
createDataLoadingThunk,
-} from '../../store/typed_functions';
+} from '@/flavours/glitch/store/typed_functions';
interface AnnualReportState {
+ year?: number;
state?: ApiAnnualReportState;
report?: AnnualReport;
}
const annualReportSlice = createSlice({
name: 'annualReport',
- initialState: {} as AnnualReportState,
+ initialState: {
+ year: wrapstodon?.year,
+ state: wrapstodon?.state,
+ } as AnnualReportState,
reducers: {
setReport(state, action: PayloadAction) {
state.report = action.payload;
@@ -52,18 +55,17 @@ const annualReportSlice = createSlice({
export const annualReport = annualReportSlice.reducer;
export const { setReport } = annualReportSlice.actions;
-export const selectWrapstodonYear = createAppSelector(
- [(state) => state.server.getIn(['server', 'wrapstodon'])],
- (year: unknown) => (typeof year === 'number' && year > 2000 ? year : null),
-);
-
-// This kicks everything off, and is called after fetching the server info.
+// Called on initial load to check if we need to refresh the report state.
export const checkAnnualReport = createAppThunk(
`${annualReportSlice.name}/checkAnnualReport`,
(_arg: unknown, { dispatch, getState }) => {
- const year = selectWrapstodonYear(getState());
+ const { state, year } = getState().annualReport;
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;
}
void dispatch(fetchReportState());
@@ -73,7 +75,7 @@ export const checkAnnualReport = createAppThunk(
const fetchReportState = createDataLoadingThunk(
`${annualReportSlice.name}/fetchReportState`,
async (_arg: unknown, { getState }) => {
- const year = selectWrapstodonYear(getState());
+ const { year } = getState().annualReport;
if (!year) {
throw new Error('Year is not set');
}
@@ -84,8 +86,6 @@ const fetchReportState = createDataLoadingThunk(
window.setTimeout(() => {
void dispatch(fetchReportState());
}, 1_000 * refresh.retry);
- } else if (state === 'available') {
- void dispatch(getReport());
}
return state;
@@ -97,7 +97,7 @@ const fetchReportState = createDataLoadingThunk(
export const generateReport = createDataLoadingThunk(
`${annualReportSlice.name}/generateReport`,
async (_arg: unknown, { getState }) => {
- const year = selectWrapstodonYear(getState());
+ const { year } = getState().annualReport;
if (!year) {
throw new Error('Year is not set');
}
@@ -111,7 +111,7 @@ export const generateReport = createDataLoadingThunk(
export const getReport = createDataLoadingThunk(
`${annualReportSlice.name}/getReport`,
async (_arg: unknown, { getState }) => {
- const year = selectWrapstodonYear(getState());
+ const { year } = getState().annualReport;
if (!year) {
throw new Error('Year is not set');
}