Use Immutable Record
for accounts in Redux state (#26559)
This commit is contained in:
parent
9d799d40ba
commit
3bf2a7296e
65 changed files with 765 additions and 662 deletions
149
app/javascript/mastodon/models/account.ts
Normal file
149
app/javascript/mastodon/models/account.ts
Normal file
|
@ -0,0 +1,149 @@
|
|||
import type { RecordOf } from 'immutable';
|
||||
import { List, Record as ImmutableRecord } from 'immutable';
|
||||
|
||||
import escapeTextContentForBrowser from 'escape-html';
|
||||
|
||||
import type {
|
||||
ApiAccountFieldJSON,
|
||||
ApiAccountRoleJSON,
|
||||
ApiAccountJSON,
|
||||
} from 'mastodon/api_types/accounts';
|
||||
import type { ApiCustomEmojiJSON } from 'mastodon/api_types/custom_emoji';
|
||||
import emojify from 'mastodon/features/emoji/emoji';
|
||||
import { unescapeHTML } from 'mastodon/utils/html';
|
||||
|
||||
import { CustomEmojiFactory } from './custom_emoji';
|
||||
import type { CustomEmoji } from './custom_emoji';
|
||||
|
||||
// AccountField
|
||||
interface AccountFieldShape extends Required<ApiAccountFieldJSON> {
|
||||
name_emojified: string;
|
||||
value_emojified: string;
|
||||
value_plain: string | null;
|
||||
}
|
||||
|
||||
type AccountField = RecordOf<AccountFieldShape>;
|
||||
|
||||
const AccountFieldFactory = ImmutableRecord<AccountFieldShape>({
|
||||
name: '',
|
||||
value: '',
|
||||
verified_at: null,
|
||||
name_emojified: '',
|
||||
value_emojified: '',
|
||||
value_plain: null,
|
||||
});
|
||||
|
||||
// AccountRole
|
||||
export type AccountRoleShape = ApiAccountRoleJSON;
|
||||
export type AccountRole = RecordOf<AccountRoleShape>;
|
||||
|
||||
const AccountRoleFactory = ImmutableRecord<AccountRoleShape>({
|
||||
color: '',
|
||||
id: '',
|
||||
name: '',
|
||||
});
|
||||
|
||||
// Account
|
||||
export interface AccountShape
|
||||
extends Required<
|
||||
Omit<ApiAccountJSON, 'emojis' | 'fields' | 'roles' | 'moved'>
|
||||
> {
|
||||
emojis: List<CustomEmoji>;
|
||||
fields: List<AccountField>;
|
||||
roles: List<AccountRole>;
|
||||
display_name_html: string;
|
||||
note_emojified: string;
|
||||
note_plain: string | null;
|
||||
hidden: boolean;
|
||||
moved: string | null;
|
||||
}
|
||||
|
||||
export type Account = RecordOf<AccountShape>;
|
||||
|
||||
export const accountDefaultValues: AccountShape = {
|
||||
acct: '',
|
||||
avatar: '',
|
||||
avatar_static: '',
|
||||
bot: false,
|
||||
created_at: '',
|
||||
discoverable: false,
|
||||
display_name: '',
|
||||
display_name_html: '',
|
||||
emojis: List<CustomEmoji>(),
|
||||
fields: List<AccountField>(),
|
||||
group: false,
|
||||
header: '',
|
||||
header_static: '',
|
||||
id: '',
|
||||
last_status_at: '',
|
||||
locked: false,
|
||||
noindex: false,
|
||||
note: '',
|
||||
note_emojified: '',
|
||||
note_plain: 'string',
|
||||
roles: List<AccountRole>(),
|
||||
uri: '',
|
||||
url: '',
|
||||
username: '',
|
||||
followers_count: 0,
|
||||
following_count: 0,
|
||||
statuses_count: 0,
|
||||
hidden: false,
|
||||
suspended: false,
|
||||
memorial: false,
|
||||
limited: false,
|
||||
moved: null,
|
||||
};
|
||||
|
||||
const AccountFactory = ImmutableRecord<AccountShape>(accountDefaultValues);
|
||||
|
||||
type EmojiMap = Record<string, ApiCustomEmojiJSON>;
|
||||
|
||||
function makeEmojiMap(emojis: ApiCustomEmojiJSON[]) {
|
||||
return emojis.reduce<EmojiMap>((obj, emoji) => {
|
||||
obj[`:${emoji.shortcode}:`] = emoji;
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function createAccountField(
|
||||
jsonField: ApiAccountFieldJSON,
|
||||
emojiMap: EmojiMap,
|
||||
) {
|
||||
return AccountFieldFactory({
|
||||
...jsonField,
|
||||
name_emojified: emojify(
|
||||
escapeTextContentForBrowser(jsonField.name),
|
||||
emojiMap,
|
||||
),
|
||||
value_emojified: emojify(jsonField.value, emojiMap),
|
||||
value_plain: unescapeHTML(jsonField.value),
|
||||
});
|
||||
}
|
||||
|
||||
export function createAccountFromServerJSON(serverJSON: ApiAccountJSON) {
|
||||
const { moved, ...accountJSON } = serverJSON;
|
||||
|
||||
const emojiMap = makeEmojiMap(accountJSON.emojis);
|
||||
|
||||
const displayName =
|
||||
accountJSON.display_name.trim().length === 0
|
||||
? accountJSON.username
|
||||
: accountJSON.display_name;
|
||||
|
||||
return AccountFactory({
|
||||
...accountJSON,
|
||||
moved: moved?.id,
|
||||
fields: List(
|
||||
serverJSON.fields.map((field) => createAccountField(field, emojiMap)),
|
||||
),
|
||||
emojis: List(serverJSON.emojis.map((emoji) => CustomEmojiFactory(emoji))),
|
||||
roles: List(serverJSON.roles?.map((role) => AccountRoleFactory(role))),
|
||||
display_name_html: emojify(
|
||||
escapeTextContentForBrowser(displayName),
|
||||
emojiMap,
|
||||
),
|
||||
note_emojified: emojify(accountJSON.note, emojiMap),
|
||||
note_plain: unescapeHTML(accountJSON.note),
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue