feat: ✨ Start work on pronouns
This commit is contained in:
		
							parent
							
								
									f90c947036
								
							
						
					
					
						commit
						4f652dab02
					
				
					 11 changed files with 116 additions and 65 deletions
				
			
		|  | @ -258,6 +258,7 @@ remoteUserCaution: "As this user is from a remote instance, the shown informatio | ||||||
| activity: "Activity" | activity: "Activity" | ||||||
| images: "Images" | images: "Images" | ||||||
| birthday: "Birthday" | birthday: "Birthday" | ||||||
|  | pronouns: "Pronouns" | ||||||
| yearsOld: "{age} years old" | yearsOld: "{age} years old" | ||||||
| registeredDate: "Joined on" | registeredDate: "Joined on" | ||||||
| location: "Location" | location: "Location" | ||||||
|  |  | ||||||
|  | @ -258,6 +258,7 @@ remoteUserCaution: "リモートユーザーのため、情報が不完全です | ||||||
| activity: "アクティビティ" | activity: "アクティビティ" | ||||||
| images: "画像" | images: "画像" | ||||||
| birthday: "誕生日" | birthday: "誕生日" | ||||||
|  | pronouns: "代名詞" | ||||||
| yearsOld: "{age}歳" | yearsOld: "{age}歳" | ||||||
| registeredDate: "登録日" | registeredDate: "登録日" | ||||||
| location: "場所" | location: "場所" | ||||||
|  | @ -1639,7 +1640,7 @@ _pages: | ||||||
|       _for: |       _for: | ||||||
|         arg1: "回数" |         arg1: "回数" | ||||||
|         arg2: "処理" |         arg2: "処理" | ||||||
|     typeError: "スロット{slot}は\"{expect}\"を受け付けますが、\"{actual}\"が入れられています!" |     typeError: 'スロット{slot}は"{expect}"を受け付けますが、"{actual}"が入れられています!' | ||||||
|     thereIsEmptySlot: "スロット{slot}が空です!" |     thereIsEmptySlot: "スロット{slot}が空です!" | ||||||
|     types: |     types: | ||||||
|       string: "テキスト" |       string: "テキスト" | ||||||
|  |  | ||||||
|  | @ -9,33 +9,43 @@ import { ffVisibility, notificationTypes } from '@/types.js'; | ||||||
| @Entity() | @Entity() | ||||||
| export class UserProfile { | export class UserProfile { | ||||||
| 	@PrimaryColumn(id()) | 	@PrimaryColumn(id()) | ||||||
| 	public userId: User['id']; | 	public userId: User["id"]; | ||||||
| 
 | 
 | ||||||
| 	@OneToOne(type => User, { | 	@OneToOne((type) => User, { | ||||||
| 		onDelete: 'CASCADE', | 		onDelete: "CASCADE", | ||||||
| 	}) | 	}) | ||||||
| 	@JoinColumn() | 	@JoinColumn() | ||||||
| 	public user: User | null; | 	public user: User | null; | ||||||
| 
 | 
 | ||||||
| 	@Column('varchar', { | 	@Column("varchar", { | ||||||
| 		length: 128, nullable: true, | 		length: 128, | ||||||
| 		comment: 'The location of the User.', | 		nullable: true, | ||||||
|  | 		comment: "The location of the User.", | ||||||
| 	}) | 	}) | ||||||
| 	public location: string | null; | 	public location: string | null; | ||||||
| 
 | 
 | ||||||
| 	@Column('char', { | 	@Column("varchar", { | ||||||
| 		length: 10, nullable: true, | 		length: 20, | ||||||
| 		comment: 'The birthday (YYYY-MM-DD) of the User.', | 		nullable: true, | ||||||
|  | 		comment: "The pronouns of the User.", | ||||||
|  | 	}) | ||||||
|  | 	public pronouns: string | null; | ||||||
|  | 
 | ||||||
|  | 	@Column("char", { | ||||||
|  | 		length: 10, | ||||||
|  | 		nullable: true, | ||||||
|  | 		comment: "The birthday (YYYY-MM-DD) of the User.", | ||||||
| 	}) | 	}) | ||||||
| 	public birthday: string | null; | 	public birthday: string | null; | ||||||
| 
 | 
 | ||||||
| 	@Column('varchar', { | 	@Column("varchar", { | ||||||
| 		length: 2048, nullable: true, | 		length: 2048, | ||||||
| 		comment: 'The description (bio) of the User.', | 		nullable: true, | ||||||
|  | 		comment: "The description (bio) of the User.", | ||||||
| 	}) | 	}) | ||||||
| 	public description: string | null; | 	public description: string | null; | ||||||
| 
 | 
 | ||||||
| 	@Column('jsonb', { | 	@Column("jsonb", { | ||||||
| 		default: [], | 		default: [], | ||||||
| 	}) | 	}) | ||||||
| 	public fields: { | 	public fields: { | ||||||
|  | @ -43,121 +53,129 @@ export class UserProfile { | ||||||
| 		value: string; | 		value: string; | ||||||
| 	}[]; | 	}[]; | ||||||
| 
 | 
 | ||||||
| 	@Column('varchar', { | 	@Column("varchar", { | ||||||
| 		length: 32, nullable: true, | 		length: 32, | ||||||
|  | 		nullable: true, | ||||||
| 	}) | 	}) | ||||||
| 	public lang: string | null; | 	public lang: string | null; | ||||||
| 
 | 
 | ||||||
| 	@Column('varchar', { | 	@Column("varchar", { | ||||||
| 		length: 512, nullable: true, | 		length: 512, | ||||||
| 		comment: 'Remote URL of the user.', | 		nullable: true, | ||||||
|  | 		comment: "Remote URL of the user.", | ||||||
| 	}) | 	}) | ||||||
| 	public url: string | null; | 	public url: string | null; | ||||||
| 
 | 
 | ||||||
| 	@Column('varchar', { | 	@Column("varchar", { | ||||||
| 		length: 128, nullable: true, | 		length: 128, | ||||||
| 		comment: 'The email address of the User.', | 		nullable: true, | ||||||
|  | 		comment: "The email address of the User.", | ||||||
| 	}) | 	}) | ||||||
| 	public email: string | null; | 	public email: string | null; | ||||||
| 
 | 
 | ||||||
| 	@Column('varchar', { | 	@Column("varchar", { | ||||||
| 		length: 128, nullable: true, | 		length: 128, | ||||||
|  | 		nullable: true, | ||||||
| 	}) | 	}) | ||||||
| 	public emailVerifyCode: string | null; | 	public emailVerifyCode: string | null; | ||||||
| 
 | 
 | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: false, | 		default: false, | ||||||
| 	}) | 	}) | ||||||
| 	public emailVerified: boolean; | 	public emailVerified: boolean; | ||||||
| 
 | 
 | ||||||
| 	@Column('jsonb', { | 	@Column("jsonb", { | ||||||
| 		default: ['follow', 'receiveFollowRequest', 'groupInvited'], | 		default: ["follow", "receiveFollowRequest", "groupInvited"], | ||||||
| 	}) | 	}) | ||||||
| 	public emailNotificationTypes: string[]; | 	public emailNotificationTypes: string[]; | ||||||
| 
 | 
 | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: false, | 		default: false, | ||||||
| 	}) | 	}) | ||||||
| 	public publicReactions: boolean; | 	public publicReactions: boolean; | ||||||
| 
 | 
 | ||||||
| 	@Column('enum', { | 	@Column("enum", { | ||||||
| 		enum: ffVisibility, | 		enum: ffVisibility, | ||||||
| 		default: 'public', | 		default: "public", | ||||||
| 	}) | 	}) | ||||||
| 	public ffVisibility: typeof ffVisibility[number]; | 	public ffVisibility: typeof ffVisibility[number]; | ||||||
| 
 | 
 | ||||||
| 	@Column('varchar', { | 	@Column("varchar", { | ||||||
| 		length: 128, nullable: true, | 		length: 128, | ||||||
|  | 		nullable: true, | ||||||
| 	}) | 	}) | ||||||
| 	public twoFactorTempSecret: string | null; | 	public twoFactorTempSecret: string | null; | ||||||
| 
 | 
 | ||||||
| 	@Column('varchar', { | 	@Column("varchar", { | ||||||
| 		length: 128, nullable: true, | 		length: 128, | ||||||
|  | 		nullable: true, | ||||||
| 	}) | 	}) | ||||||
| 	public twoFactorSecret: string | null; | 	public twoFactorSecret: string | null; | ||||||
| 
 | 
 | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: false, | 		default: false, | ||||||
| 	}) | 	}) | ||||||
| 	public twoFactorEnabled: boolean; | 	public twoFactorEnabled: boolean; | ||||||
| 
 | 
 | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: false, | 		default: false, | ||||||
| 	}) | 	}) | ||||||
| 	public securityKeysAvailable: boolean; | 	public securityKeysAvailable: boolean; | ||||||
| 
 | 
 | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: false, | 		default: false, | ||||||
| 	}) | 	}) | ||||||
| 	public usePasswordLessLogin: boolean; | 	public usePasswordLessLogin: boolean; | ||||||
| 
 | 
 | ||||||
| 	@Column('varchar', { | 	@Column("varchar", { | ||||||
| 		length: 128, nullable: true, | 		length: 128, | ||||||
| 		comment: 'The password hash of the User. It will be null if the origin of the user is local.', | 		nullable: true, | ||||||
|  | 		comment: | ||||||
|  | 			"The password hash of the User. It will be null if the origin of the user is local.", | ||||||
| 	}) | 	}) | ||||||
| 	public password: string | null; | 	public password: string | null; | ||||||
| 
 | 
 | ||||||
| 	// TODO: そのうち消す
 | 	// TODO: そのうち消す
 | ||||||
| 	@Column('jsonb', { | 	@Column("jsonb", { | ||||||
| 		default: {}, | 		default: {}, | ||||||
| 		comment: 'The client-specific data of the User.', | 		comment: "The client-specific data of the User.", | ||||||
| 	}) | 	}) | ||||||
| 	public clientData: Record<string, any>; | 	public clientData: Record<string, any>; | ||||||
| 
 | 
 | ||||||
| 	// TODO: そのうち消す
 | 	// TODO: そのうち消す
 | ||||||
| 	@Column('jsonb', { | 	@Column("jsonb", { | ||||||
| 		default: {}, | 		default: {}, | ||||||
| 		comment: 'The room data of the User.', | 		comment: "The room data of the User.", | ||||||
| 	}) | 	}) | ||||||
| 	public room: Record<string, any>; | 	public room: Record<string, any>; | ||||||
| 
 | 
 | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: false, | 		default: false, | ||||||
| 	}) | 	}) | ||||||
| 	public autoAcceptFollowed: boolean; | 	public autoAcceptFollowed: boolean; | ||||||
| 
 | 
 | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: false, | 		default: false, | ||||||
| 		comment: 'Whether reject index by crawler.', | 		comment: "Whether reject index by crawler.", | ||||||
| 	}) | 	}) | ||||||
| 	public noCrawle: boolean; | 	public noCrawle: boolean; | ||||||
| 
 | 
 | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: false, | 		default: false, | ||||||
| 	}) | 	}) | ||||||
| 	public alwaysMarkNsfw: boolean; | 	public alwaysMarkNsfw: boolean; | ||||||
| 
 | 
 | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: false, | 		default: false, | ||||||
| 	}) | 	}) | ||||||
| 	public carefulBot: boolean; | 	public carefulBot: boolean; | ||||||
| 
 | 
 | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: true, | 		default: true, | ||||||
| 	}) | 	}) | ||||||
| 	public injectFeaturedNote: boolean; | 	public injectFeaturedNote: boolean; | ||||||
| 
 | 
 | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: true, | 		default: true, | ||||||
| 	}) | 	}) | ||||||
| 	public receiveAnnouncementEmail: boolean; | 	public receiveAnnouncementEmail: boolean; | ||||||
|  | @ -166,37 +184,38 @@ export class UserProfile { | ||||||
| 		...id(), | 		...id(), | ||||||
| 		nullable: true, | 		nullable: true, | ||||||
| 	}) | 	}) | ||||||
| 	public pinnedPageId: Page['id'] | null; | 	public pinnedPageId: Page["id"] | null; | ||||||
| 
 | 
 | ||||||
| 	@OneToOne(type => Page, { | 	@OneToOne((type) => Page, { | ||||||
| 		onDelete: 'SET NULL', | 		onDelete: "SET NULL", | ||||||
| 	}) | 	}) | ||||||
| 	@JoinColumn() | 	@JoinColumn() | ||||||
| 	public pinnedPage: Page | null; | 	public pinnedPage: Page | null; | ||||||
| 
 | 
 | ||||||
| 	@Column('jsonb', { | 	@Column("jsonb", { | ||||||
| 		default: {}, | 		default: {}, | ||||||
| 	}) | 	}) | ||||||
| 	public integrations: Record<string, any>; | 	public integrations: Record<string, any>; | ||||||
| 
 | 
 | ||||||
| 	@Index() | 	@Index() | ||||||
| 	@Column('boolean', { | 	@Column("boolean", { | ||||||
| 		default: false, select: false, | 		default: false, | ||||||
|  | 		select: false, | ||||||
| 	}) | 	}) | ||||||
| 	public enableWordMute: boolean; | 	public enableWordMute: boolean; | ||||||
| 
 | 
 | ||||||
| 	@Column('jsonb', { | 	@Column("jsonb", { | ||||||
| 		default: [], | 		default: [], | ||||||
| 	}) | 	}) | ||||||
| 	public mutedWords: string[][]; | 	public mutedWords: string[][]; | ||||||
| 
 | 
 | ||||||
| 	@Column('jsonb', { | 	@Column("jsonb", { | ||||||
| 		default: [], | 		default: [], | ||||||
| 		comment: 'List of instances muted by the user.', | 		comment: "List of instances muted by the user.", | ||||||
| 	}) | 	}) | ||||||
| 	public mutedInstances: string[]; | 	public mutedInstances: string[]; | ||||||
| 
 | 
 | ||||||
| 	@Column('enum', { | 	@Column("enum", { | ||||||
| 		enum: notificationTypes, | 		enum: notificationTypes, | ||||||
| 		array: true, | 		array: true, | ||||||
| 		default: [], | 		default: [], | ||||||
|  | @ -205,9 +224,10 @@ export class UserProfile { | ||||||
| 
 | 
 | ||||||
| 	//#region Denormalized fields
 | 	//#region Denormalized fields
 | ||||||
| 	@Index() | 	@Index() | ||||||
| 	@Column('varchar', { | 	@Column("varchar", { | ||||||
| 		length: 128, nullable: true, | 		length: 128, | ||||||
| 		comment: '[Denormalized]', | 		nullable: true, | ||||||
|  | 		comment: "[Denormalized]", | ||||||
| 	}) | 	}) | ||||||
| 	public userHost: string | null; | 	public userHost: string | null; | ||||||
| 	//#endregion
 | 	//#endregion
 | ||||||
|  |  | ||||||
|  | @ -30,6 +30,7 @@ const nameSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; | ||||||
| const descriptionSchema = { type: 'string', minLength: 1, maxLength: 500 } as const; | const descriptionSchema = { type: 'string', minLength: 1, maxLength: 500 } as const; | ||||||
| const locationSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; | const locationSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; | ||||||
| const birthdaySchema = { type: 'string', pattern: /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.toString().slice(1, -1) } as const; | const birthdaySchema = { type: 'string', pattern: /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.toString().slice(1, -1) } as const; | ||||||
|  | const pronounsSchema = { type: 'string', minLength: 1, maxLength: 20 } as const; | ||||||
| 
 | 
 | ||||||
| function isLocalUser(user: User): user is ILocalUser; | function isLocalUser(user: User): user is ILocalUser; | ||||||
| function isLocalUser<T extends { host: User['host'] }>(user: T): user is T & { host: null; }; | function isLocalUser<T extends { host: User['host'] }>(user: T): user is T & { host: null; }; | ||||||
|  | @ -50,6 +51,7 @@ export const UserRepository = db.getRepository(User).extend({ | ||||||
| 	descriptionSchema, | 	descriptionSchema, | ||||||
| 	locationSchema, | 	locationSchema, | ||||||
| 	birthdaySchema, | 	birthdaySchema, | ||||||
|  | 	pronounsSchema, | ||||||
| 
 | 
 | ||||||
| 	//#region Validators
 | 	//#region Validators
 | ||||||
| 	validateLocalUsername: ajv.compile(localUsernameSchema), | 	validateLocalUsername: ajv.compile(localUsernameSchema), | ||||||
|  | @ -58,6 +60,7 @@ export const UserRepository = db.getRepository(User).extend({ | ||||||
| 	validateDescription: ajv.compile(descriptionSchema), | 	validateDescription: ajv.compile(descriptionSchema), | ||||||
| 	validateLocation: ajv.compile(locationSchema), | 	validateLocation: ajv.compile(locationSchema), | ||||||
| 	validateBirthday: ajv.compile(birthdaySchema), | 	validateBirthday: ajv.compile(birthdaySchema), | ||||||
|  | 	validatePronouns: ajv.compile(pronounsSchema), | ||||||
| 	//#endregion
 | 	//#endregion
 | ||||||
| 
 | 
 | ||||||
| 	async getRelation(me: User['id'], target: User['id']) { | 	async getRelation(me: User['id'], target: User['id']) { | ||||||
|  | @ -318,6 +321,7 @@ export const UserRepository = db.getRepository(User).extend({ | ||||||
| 				isSilenced: user.isSilenced || falsy, | 				isSilenced: user.isSilenced || falsy, | ||||||
| 				isSuspended: user.isSuspended || falsy, | 				isSuspended: user.isSuspended || falsy, | ||||||
| 				description: profile!.description, | 				description: profile!.description, | ||||||
|  | 				pronouns: profile!.pronouns, | ||||||
| 				location: profile!.location, | 				location: profile!.location, | ||||||
| 				birthday: profile!.birthday, | 				birthday: profile!.birthday, | ||||||
| 				lang: profile!.lang, | 				lang: profile!.lang, | ||||||
|  |  | ||||||
|  | @ -143,6 +143,11 @@ export const packedUserDetailedNotMeOnlySchema = { | ||||||
| 			nullable: true, optional: false, | 			nullable: true, optional: false, | ||||||
| 			example: 'Hi masters, I am Ai!', | 			example: 'Hi masters, I am Ai!', | ||||||
| 		}, | 		}, | ||||||
|  | 		pronouns: { | ||||||
|  | 			type: 'string', | ||||||
|  | 			nullable: true, optional: false, | ||||||
|  | 			example: 'They/Them', | ||||||
|  | 		}, | ||||||
| 		location: { | 		location: { | ||||||
| 			type: 'string', | 			type: 'string', | ||||||
| 			nullable: true, optional: false, | 			nullable: true, optional: false, | ||||||
|  |  | ||||||
|  | @ -192,6 +192,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us | ||||||
| 				description: person.summary ? htmlToMfm(truncate(person.summary, summaryLength), person.tag) : null, | 				description: person.summary ? htmlToMfm(truncate(person.summary, summaryLength), person.tag) : null, | ||||||
| 				url: getOneApHrefNullable(person.url), | 				url: getOneApHrefNullable(person.url), | ||||||
| 				fields, | 				fields, | ||||||
|  | 				pronouns: person['vcard:Pronouns'] || null, | ||||||
| 				birthday: bday ? bday[0] : null, | 				birthday: bday ? bday[0] : null, | ||||||
| 				location: person['vcard:Address'] || null, | 				location: person['vcard:Address'] || null, | ||||||
| 				userHost: host, | 				userHost: host, | ||||||
|  | @ -368,6 +369,7 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint | ||||||
| 		url: getOneApHrefNullable(person.url), | 		url: getOneApHrefNullable(person.url), | ||||||
| 		fields, | 		fields, | ||||||
| 		description: person.summary ? htmlToMfm(truncate(person.summary, summaryLength), person.tag) : null, | 		description: person.summary ? htmlToMfm(truncate(person.summary, summaryLength), person.tag) : null, | ||||||
|  | 		pronouns: person['vcard:Pronouns'] || null, | ||||||
| 		birthday: bday ? bday[0] : null, | 		birthday: bday ? bday[0] : null, | ||||||
| 		location: person['vcard:Address'] || null, | 		location: person['vcard:Address'] || null, | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
|  | @ -77,6 +77,10 @@ export async function renderPerson(user: ILocalUser) { | ||||||
| 		attachment: attachment.length ? attachment : undefined, | 		attachment: attachment.length ? attachment : undefined, | ||||||
| 	} as any; | 	} as any; | ||||||
| 
 | 
 | ||||||
|  | 	if (profile?.pronouns) { | ||||||
|  | 		person['vcard:Pronouns'] = profile.pronouns; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if (profile?.birthday) { | 	if (profile?.birthday) { | ||||||
| 		person['vcard:bday'] = profile.birthday; | 		person['vcard:bday'] = profile.birthday; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -164,6 +164,7 @@ export interface IActor extends IObject { | ||||||
| 	endpoints?: { | 	endpoints?: { | ||||||
| 		sharedInbox?: string; | 		sharedInbox?: string; | ||||||
| 	}; | 	}; | ||||||
|  | 	'vcard:Pronouns'?: string; | ||||||
| 	'vcard:bday'?: string; | 	'vcard:bday'?: string; | ||||||
| 	'vcard:Address'?: string; | 	'vcard:Address'?: string; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -72,6 +72,7 @@ export const paramDef = { | ||||||
| 	properties: { | 	properties: { | ||||||
| 		name: { ...Users.nameSchema, nullable: true }, | 		name: { ...Users.nameSchema, nullable: true }, | ||||||
| 		description: { ...Users.descriptionSchema, nullable: true }, | 		description: { ...Users.descriptionSchema, nullable: true }, | ||||||
|  | 		pronouns: { ...Users.pronounsSchema, nullable: true }, | ||||||
| 		location: { ...Users.locationSchema, nullable: true }, | 		location: { ...Users.locationSchema, nullable: true }, | ||||||
| 		birthday: { ...Users.birthdaySchema, nullable: true }, | 		birthday: { ...Users.birthdaySchema, nullable: true }, | ||||||
| 		lang: { type: 'string', enum: [null, ...Object.keys(langmap)], nullable: true }, | 		lang: { type: 'string', enum: [null, ...Object.keys(langmap)], nullable: true }, | ||||||
|  | @ -132,6 +133,7 @@ export default define(meta, paramDef, async (ps, _user, token) => { | ||||||
| 	if (ps.name !== undefined) updates.name = ps.name; | 	if (ps.name !== undefined) updates.name = ps.name; | ||||||
| 	if (ps.description !== undefined) profileUpdates.description = ps.description; | 	if (ps.description !== undefined) profileUpdates.description = ps.description; | ||||||
| 	if (ps.lang !== undefined) profileUpdates.lang = ps.lang; | 	if (ps.lang !== undefined) profileUpdates.lang = ps.lang; | ||||||
|  | 	if (ps.pronouns !== undefined) profileUpdates.pronouns = ps.pronouns; | ||||||
| 	if (ps.location !== undefined) profileUpdates.location = ps.location; | 	if (ps.location !== undefined) profileUpdates.location = ps.location; | ||||||
| 	if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday; | 	if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday; | ||||||
| 	if (ps.ffVisibility !== undefined) profileUpdates.ffVisibility = ps.ffVisibility; | 	if (ps.ffVisibility !== undefined) profileUpdates.ffVisibility = ps.ffVisibility; | ||||||
|  |  | ||||||
|  | @ -17,6 +17,11 @@ | ||||||
| 		<template #caption>{{ i18n.ts._profile.youCanIncludeHashtags }}</template> | 		<template #caption>{{ i18n.ts._profile.youCanIncludeHashtags }}</template> | ||||||
| 	</FormTextarea> | 	</FormTextarea> | ||||||
| 
 | 
 | ||||||
|  | 	<FormInput v-model="profile.pronouns" manual-save class="_formBlock"> | ||||||
|  | 		<template #label>{{ i18n.ts.pronouns }}</template> | ||||||
|  | 		<template #prefix><i class="fas fa-heart"></i></template> | ||||||
|  | 	</FormInput> | ||||||
|  | 
 | ||||||
| 	<FormInput v-model="profile.location" manual-save class="_formBlock"> | 	<FormInput v-model="profile.location" manual-save class="_formBlock"> | ||||||
| 		<template #label>{{ i18n.ts.location }}</template> | 		<template #label>{{ i18n.ts.location }}</template> | ||||||
| 		<template #prefix><i class="fas fa-map-marker-alt"></i></template> | 		<template #prefix><i class="fas fa-map-marker-alt"></i></template> | ||||||
|  | @ -82,6 +87,7 @@ import { langmap } from '@/scripts/langmap'; | ||||||
| const profile = reactive({ | const profile = reactive({ | ||||||
| 	name: $i.name, | 	name: $i.name, | ||||||
| 	description: $i.description, | 	description: $i.description, | ||||||
|  | 	pronouns: $i.pronouns, | ||||||
| 	location: $i.location, | 	location: $i.location, | ||||||
| 	birthday: $i.birthday, | 	birthday: $i.birthday, | ||||||
| 	lang: $i.lang, | 	lang: $i.lang, | ||||||
|  | @ -120,6 +126,7 @@ function save() { | ||||||
| 	os.apiWithDialog('i/update', { | 	os.apiWithDialog('i/update', { | ||||||
| 		name: profile.name || null, | 		name: profile.name || null, | ||||||
| 		description: profile.description || null, | 		description: profile.description || null, | ||||||
|  | 		pronouns: profile.pronouns || null, | ||||||
| 		location: profile.location || null, | 		location: profile.location || null, | ||||||
| 		birthday: profile.birthday || null, | 		birthday: profile.birthday || null, | ||||||
| 		lang: profile.lang || null, | 		lang: profile.lang || null, | ||||||
|  |  | ||||||
|  | @ -47,6 +47,10 @@ | ||||||
| 								<p v-else class="empty">{{ $ts.noAccountDescription }}</p> | 								<p v-else class="empty">{{ $ts.noAccountDescription }}</p> | ||||||
| 							</div> | 							</div> | ||||||
| 							<div class="fields system"> | 							<div class="fields system"> | ||||||
|  | 								<dl v-if="user.pronouns" class="field"> | ||||||
|  | 									<dt class="name"><i class="fas fa-heart fa-fw"></i> {{ $ts.pronouns }}</dt> | ||||||
|  | 									<dd class="value">{{ user.pronouns }}</dd> | ||||||
|  | 								</dl> | ||||||
| 								<dl v-if="user.location" class="field"> | 								<dl v-if="user.location" class="field"> | ||||||
| 									<dt class="name"><i class="fas fa-map-marker fa-fw"></i> {{ $ts.location }}</dt> | 									<dt class="name"><i class="fas fa-map-marker fa-fw"></i> {{ $ts.location }}</dt> | ||||||
| 									<dd class="value">{{ user.location }}</dd> | 									<dd class="value">{{ user.location }}</dd> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue