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),
|
||||
});
|
||||
}
|
15
app/javascript/mastodon/models/custom_emoji.ts
Normal file
15
app/javascript/mastodon/models/custom_emoji.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import type { RecordOf } from 'immutable';
|
||||
import { Record } from 'immutable';
|
||||
|
||||
import type { ApiCustomEmojiJSON } from 'mastodon/api_types/custom_emoji';
|
||||
|
||||
type CustomEmojiShape = Required<ApiCustomEmojiJSON>; // no changes from server shape
|
||||
export type CustomEmoji = RecordOf<CustomEmojiShape>;
|
||||
|
||||
export const CustomEmojiFactory = Record<CustomEmojiShape>({
|
||||
shortcode: '',
|
||||
static_url: '',
|
||||
url: '',
|
||||
category: '',
|
||||
visible_in_picker: false,
|
||||
});
|
29
app/javascript/mastodon/models/relationship.ts
Normal file
29
app/javascript/mastodon/models/relationship.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import type { RecordOf } from 'immutable';
|
||||
import { Record } from 'immutable';
|
||||
|
||||
import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships';
|
||||
|
||||
type RelationshipShape = Required<ApiRelationshipJSON>; // no changes from server shape
|
||||
export type Relationship = RecordOf<RelationshipShape>;
|
||||
|
||||
const RelationshipFactory = Record<RelationshipShape>({
|
||||
blocked_by: false,
|
||||
blocking: false,
|
||||
domain_blocking: false,
|
||||
endorsed: false,
|
||||
followed_by: false,
|
||||
following: false,
|
||||
id: '',
|
||||
languages: null,
|
||||
muting_notifications: false,
|
||||
muting: false,
|
||||
note: '',
|
||||
notifying: false,
|
||||
requested_by: false,
|
||||
requested: false,
|
||||
showing_reblogs: false,
|
||||
});
|
||||
|
||||
export function createRelationship(attributes: Partial<RelationshipShape>) {
|
||||
return RelationshipFactory(attributes);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue