Add wrapstodon to initial state and show wrapstodon sidebar item on load (#37261)

This commit is contained in:
Claire
2025-12-16 10:47:18 +01:00
committed by GitHub
parent 4c679c698f
commit 550a6d4765
5 changed files with 50 additions and 17 deletions

View File

@@ -57,27 +57,18 @@ class Api::V1::AnnualReportsController < Api::BaseController
render_empty render_empty
end end
def refresh_key
"wrapstodon:#{current_account.id}:#{year}"
end
private private
def report_state def report_state
return 'available' if GeneratedAnnualReport.exists?(account_id: current_account.id, year: year) AnnualReport.new(current_account, year).state do |async_refresh|
async_refresh = AsyncRefresh.new(refresh_key)
if async_refresh.running?
add_async_refresh_header(async_refresh, retry_seconds: 2) add_async_refresh_header(async_refresh, retry_seconds: 2)
'generating'
elsif AnnualReport.current_campaign == year && AnnualReport.new(current_account, year).eligible?
'eligible'
else
'ineligible'
end end
end end
def refresh_key
"wrapstodon:#{current_account.id}:#{year}"
end
def year def year
params[:id]&.to_i params[:id]&.to_i
end end

View File

@@ -2,6 +2,11 @@ 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;
@@ -47,6 +52,7 @@ interface InitialStateMeta {
status_page_url: string; status_page_url: string;
terms_of_service_enabled: boolean; terms_of_service_enabled: boolean;
emoji_style?: string; emoji_style?: string;
wrapstodon?: InitialWrapstodonState | null;
} }
interface Role { interface Role {
@@ -128,6 +134,7 @@ export const criticalUpdatesPending = initialState?.critical_updates_pending;
export const statusPageUrl = getMeta('status_page_url'); export const statusPageUrl = getMeta('status_page_url');
export const sso_redirect = getMeta('sso_redirect'); export const sso_redirect = getMeta('sso_redirect');
export const termsOfServiceEnabled = getMeta('terms_of_service_enabled'); export const termsOfServiceEnabled = getMeta('terms_of_service_enabled');
export const wrapstodon = getMeta('wrapstodon');
const displayNames = const displayNames =
// Intl.DisplayNames can be undefined in old browsers // Intl.DisplayNames can be undefined in old browsers

View File

@@ -11,6 +11,7 @@ import {
apiGetAnnualReportState, apiGetAnnualReportState,
apiRequestGenerateAnnualReport, apiRequestGenerateAnnualReport,
} from '@/mastodon/api/annual_report'; } from '@/mastodon/api/annual_report';
import { wrapstodon } from '@/mastodon/initial_state';
import type { AnnualReport } from '@/mastodon/models/annual_report'; import type { AnnualReport } from '@/mastodon/models/annual_report';
import { import {
@@ -20,13 +21,17 @@ import {
} from '../../store/typed_functions'; } from '../../store/typed_functions';
interface AnnualReportState { interface AnnualReportState {
year?: number;
state?: ApiAnnualReportState; state?: ApiAnnualReportState;
report?: AnnualReport; report?: AnnualReport;
} }
const annualReportSlice = createSlice({ const annualReportSlice = createSlice({
name: 'annualReport', name: 'annualReport',
initialState: {} as AnnualReportState, initialState: {
year: wrapstodon?.year,
state: wrapstodon?.state,
} as AnnualReportState,
reducers: { reducers: {
setReport(state, action: PayloadAction<AnnualReport>) { setReport(state, action: PayloadAction<AnnualReport>) {
state.report = action.payload; state.report = action.payload;
@@ -53,8 +58,8 @@ export const annualReport = annualReportSlice.reducer;
export const { setReport } = annualReportSlice.actions; export const { setReport } = annualReportSlice.actions;
export const selectWrapstodonYear = createAppSelector( export const selectWrapstodonYear = createAppSelector(
[(state) => state.server.getIn(['server', 'wrapstodon'])], [(state) => state.annualReport.year],
(year: unknown) => (typeof year === 'number' && year > 2000 ? year : null), (year: number | null | undefined) => year ?? null,
); );
// This kicks everything off, and is called after fetching the server info. // This kicks everything off, and is called after fetching the server info.

View File

@@ -34,6 +34,25 @@ class AnnualReport
end end
end end
def state
return 'available' if GeneratedAnnualReport.exists?(account_id: @account.id, year: @year)
async_refresh = AsyncRefresh.new(refresh_key)
if async_refresh.running?
yield async_refresh if block_given?
'generating'
elsif AnnualReport.current_campaign == @year && eligible?
'eligible'
else
'ineligible'
end
end
def refresh_key
"wrapstodon:#{@account.id}:#{@year}"
end
def generate def generate
return if GeneratedAnnualReport.exists?(account: @account, year: @year) return if GeneratedAnnualReport.exists?(account: @account, year: @year)

View File

@@ -32,6 +32,7 @@ class InitialStateSerializer < ActiveModel::Serializer
store[:use_pending_items] = object_account_user.setting_use_pending_items store[:use_pending_items] = object_account_user.setting_use_pending_items
store[:show_trends] = Setting.trends && object_account_user.setting_trends store[:show_trends] = Setting.trends && object_account_user.setting_trends
store[:emoji_style] = object_account_user.settings['web.emoji_style'] store[:emoji_style] = object_account_user.settings['web.emoji_style']
store[:wrapstodon] = wrapstodon
else else
store[:auto_play_gif] = Setting.auto_play_gif store[:auto_play_gif] = Setting.auto_play_gif
store[:display_media] = Setting.display_media store[:display_media] = Setting.display_media
@@ -94,6 +95,16 @@ class InitialStateSerializer < ActiveModel::Serializer
private private
def wrapstodon
current_campaign = AnnualReport.current_campaign
return if current_campaign.blank?
{
year: current_campaign,
state: AnnualReport.new(object.current_account, current_campaign).state,
}
end
def default_meta_store def default_meta_store
{ {
access_token: object.token, access_token: object.token,