Show user fields (#3590)
This commit is contained in:
		
							parent
							
								
									1d1a373ca8
								
							
						
					
					
						commit
						638d81b66e
					
				
					 7 changed files with 132 additions and 1 deletions
				
			
		| 
						 | 
					@ -26,6 +26,14 @@
 | 
				
			||||||
			<div class="description">
 | 
								<div class="description">
 | 
				
			||||||
				<misskey-flavored-markdown v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
 | 
									<misskey-flavored-markdown v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
								<div class="fields" v-if="user.fields">
 | 
				
			||||||
 | 
									<dl class="field" v-for="(field, i) in user.fields" :key="i">
 | 
				
			||||||
 | 
										<dt class="name">{{ field.name }}</dt>
 | 
				
			||||||
 | 
										<dd class="value">
 | 
				
			||||||
 | 
											<misskey-flavored-markdown :text="field.value" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
 | 
				
			||||||
 | 
										</dd>
 | 
				
			||||||
 | 
									</dl>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
			<div class="counts">
 | 
								<div class="counts">
 | 
				
			||||||
				<div>
 | 
									<div>
 | 
				
			||||||
					<b>{{ user.notesCount | number }}</b>
 | 
										<b>{{ user.notesCount | number }}</b>
 | 
				
			||||||
| 
						 | 
					@ -416,6 +424,31 @@ export default Vue.extend({
 | 
				
			||||||
			border-right solid 16px transparent
 | 
								border-right solid 16px transparent
 | 
				
			||||||
			border-bottom solid 16px var(--face)
 | 
								border-bottom solid 16px var(--face)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .fields
 | 
				
			||||||
 | 
								margin-top 8px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> .field
 | 
				
			||||||
 | 
									display flex
 | 
				
			||||||
 | 
									padding 0
 | 
				
			||||||
 | 
									margin 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> .name
 | 
				
			||||||
 | 
										padding 4px
 | 
				
			||||||
 | 
										margin 4px
 | 
				
			||||||
 | 
										width 30%
 | 
				
			||||||
 | 
										overflow hidden
 | 
				
			||||||
 | 
										white-space nowrap
 | 
				
			||||||
 | 
										text-overflow ellipsis
 | 
				
			||||||
 | 
										font-weight bold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> .value
 | 
				
			||||||
 | 
										padding 4px
 | 
				
			||||||
 | 
										margin 4px
 | 
				
			||||||
 | 
										width 70%
 | 
				
			||||||
 | 
										overflow hidden
 | 
				
			||||||
 | 
										white-space nowrap
 | 
				
			||||||
 | 
										text-overflow ellipsis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .counts
 | 
							> .counts
 | 
				
			||||||
			display grid
 | 
								display grid
 | 
				
			||||||
			grid-template-columns 1fr 1fr 1fr
 | 
								grid-template-columns 1fr 1fr 1fr
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,14 @@
 | 
				
			||||||
		<div class="description">
 | 
							<div class="description">
 | 
				
			||||||
			<misskey-flavored-markdown v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
 | 
								<misskey-flavored-markdown v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
 | 
							<div class="fields" v-if="user.fields">
 | 
				
			||||||
 | 
								<dl class="field" v-for="(field, i) in user.fields" :key="i">
 | 
				
			||||||
 | 
									<dt class="name">{{ field.name }}</dt>
 | 
				
			||||||
 | 
									<dd class="value">
 | 
				
			||||||
 | 
										<misskey-flavored-markdown :text="field.value" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
 | 
				
			||||||
 | 
									</dd>
 | 
				
			||||||
 | 
								</dl>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
		<div class="info">
 | 
							<div class="info">
 | 
				
			||||||
			<span class="location" v-if="user.host === null && user.profile.location"><fa icon="map-marker"/> {{ user.profile.location }}</span>
 | 
								<span class="location" v-if="user.host === null && user.profile.location"><fa icon="map-marker"/> {{ user.profile.location }}</span>
 | 
				
			||||||
			<span class="birthday" v-if="user.host === null && user.profile.birthday"><fa icon="birthday-cake"/> {{ user.profile.birthday.replace('-', $t('year')).replace('-', $t('month')) + $t('day') }} ({{ $t('years-old', { age }) }})</span>
 | 
								<span class="birthday" v-if="user.host === null && user.profile.birthday"><fa icon="birthday-cake"/> {{ user.profile.birthday.replace('-', $t('year')).replace('-', $t('month')) + $t('day') }} ({{ $t('years-old', { age }) }})</span>
 | 
				
			||||||
| 
						 | 
					@ -174,6 +182,33 @@ export default Vue.extend({
 | 
				
			||||||
		padding 16px 16px 16px 154px
 | 
							padding 16px 16px 16px 154px
 | 
				
			||||||
		color var(--text)
 | 
							color var(--text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> .fields
 | 
				
			||||||
 | 
								margin-top 16px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> .field
 | 
				
			||||||
 | 
									display flex
 | 
				
			||||||
 | 
									padding 0
 | 
				
			||||||
 | 
									margin 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> .name
 | 
				
			||||||
 | 
										border-right solid 1px var(--faceDivider)
 | 
				
			||||||
 | 
										padding 4px
 | 
				
			||||||
 | 
										margin 4px
 | 
				
			||||||
 | 
										width 30%
 | 
				
			||||||
 | 
										overflow hidden
 | 
				
			||||||
 | 
										white-space nowrap
 | 
				
			||||||
 | 
										text-overflow ellipsis
 | 
				
			||||||
 | 
										font-weight bold
 | 
				
			||||||
 | 
										text-align center
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> .value
 | 
				
			||||||
 | 
										padding 4px
 | 
				
			||||||
 | 
										margin 4px
 | 
				
			||||||
 | 
										width 70%
 | 
				
			||||||
 | 
										overflow hidden
 | 
				
			||||||
 | 
										white-space nowrap
 | 
				
			||||||
 | 
										text-overflow ellipsis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .info
 | 
							> .info
 | 
				
			||||||
			margin-top 16px
 | 
								margin-top 16px
 | 
				
			||||||
			padding-top 16px
 | 
								padding-top 16px
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,14 @@
 | 
				
			||||||
				<div class="description">
 | 
									<div class="description">
 | 
				
			||||||
					<misskey-flavored-markdown v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
 | 
										<misskey-flavored-markdown v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
 | 
									<div class="fields" v-if="user.fields">
 | 
				
			||||||
 | 
										<dl class="field" v-for="(field, i) in user.fields" :key="i">
 | 
				
			||||||
 | 
											<dt class="name">{{ field.name }}</dt>
 | 
				
			||||||
 | 
											<dd class="value">
 | 
				
			||||||
 | 
												<misskey-flavored-markdown :text="field.value" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
 | 
				
			||||||
 | 
											</dd>
 | 
				
			||||||
 | 
										</dl>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
				<div class="info">
 | 
									<div class="info">
 | 
				
			||||||
					<p class="location" v-if="user.host === null && user.profile.location">
 | 
										<p class="location" v-if="user.host === null && user.profile.location">
 | 
				
			||||||
						<fa icon="map-marker"/>{{ user.profile.location }}
 | 
											<fa icon="map-marker"/>{{ user.profile.location }}
 | 
				
			||||||
| 
						 | 
					@ -301,6 +309,33 @@ main
 | 
				
			||||||
				margin 8px 0
 | 
									margin 8px 0
 | 
				
			||||||
				color var(--mobileUserPageDescription)
 | 
									color var(--mobileUserPageDescription)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> .fields
 | 
				
			||||||
 | 
									margin 8px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> .field
 | 
				
			||||||
 | 
										display flex
 | 
				
			||||||
 | 
										padding 0
 | 
				
			||||||
 | 
										margin 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										> .name
 | 
				
			||||||
 | 
											padding 4px
 | 
				
			||||||
 | 
											margin 4px
 | 
				
			||||||
 | 
											width 30%
 | 
				
			||||||
 | 
											overflow hidden
 | 
				
			||||||
 | 
											white-space nowrap
 | 
				
			||||||
 | 
											text-overflow ellipsis
 | 
				
			||||||
 | 
											font-weight bold
 | 
				
			||||||
 | 
											color var(--mobileUserPageStatusHighlight)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										> .value
 | 
				
			||||||
 | 
											padding 4px
 | 
				
			||||||
 | 
											margin 4px
 | 
				
			||||||
 | 
											width 70%
 | 
				
			||||||
 | 
											overflow hidden
 | 
				
			||||||
 | 
											white-space nowrap
 | 
				
			||||||
 | 
											text-overflow ellipsis
 | 
				
			||||||
 | 
											color var(--mobileUserPageStatusHighlight)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> .info
 | 
								> .info
 | 
				
			||||||
				margin 8px 0
 | 
									margin 8px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ export default function(html: string): string {
 | 
				
			||||||
				if ((rel && rel.value.match('tag') !== null) || !href || href.value == txt) {
 | 
									if ((rel && rel.value.match('tag') !== null) || !href || href.value == txt) {
 | 
				
			||||||
					text += txt;
 | 
										text += txt;
 | 
				
			||||||
				// メンション
 | 
									// メンション
 | 
				
			||||||
				} else if (txt.startsWith('@')) {
 | 
									} else if (txt.startsWith('@') && !rel || !rel.value.match(/^me /)) {
 | 
				
			||||||
					const part = txt.split('@');
 | 
										const part = txt.split('@');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if (part.length == 2) {
 | 
										if (part.length == 2) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,6 +109,10 @@ export interface ILocalUser extends IUserBase {
 | 
				
			||||||
		birthday: string; // 'YYYY-MM-DD'
 | 
							birthday: string; // 'YYYY-MM-DD'
 | 
				
			||||||
		tags: string[];
 | 
							tags: string[];
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						fields?: {
 | 
				
			||||||
 | 
							name: string;
 | 
				
			||||||
 | 
							value: string;
 | 
				
			||||||
 | 
						}[];
 | 
				
			||||||
	isCat: boolean;
 | 
						isCat: boolean;
 | 
				
			||||||
	isAdmin?: boolean;
 | 
						isAdmin?: boolean;
 | 
				
			||||||
	isModerator?: boolean;
 | 
						isModerator?: boolean;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,7 @@ import registerInstance from '../../../services/register-instance';
 | 
				
			||||||
import Instance from '../../../models/instance';
 | 
					import Instance from '../../../models/instance';
 | 
				
			||||||
import getDriveFileUrl from '../../../misc/get-drive-file-url';
 | 
					import getDriveFileUrl from '../../../misc/get-drive-file-url';
 | 
				
			||||||
import { IEmoji } from '../../../models/emoji';
 | 
					import { IEmoji } from '../../../models/emoji';
 | 
				
			||||||
 | 
					import { ITag } from './tag';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const log = debug('misskey:activitypub');
 | 
					const log = debug('misskey:activitypub');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,6 +136,10 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<IU
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const host = toUnicode(new URL(object.id).hostname.toLowerCase());
 | 
						const host = toUnicode(new URL(object.id).hostname.toLowerCase());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const fields = await extractFields(person.attachment).catch(e => {
 | 
				
			||||||
 | 
							console.log(`cat not extract fields: ${e}`);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const isBot = object.type == 'Service';
 | 
						const isBot = object.type == 'Service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Create user
 | 
						// Create user
 | 
				
			||||||
| 
						 | 
					@ -164,6 +169,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<IU
 | 
				
			||||||
			endpoints: person.endpoints,
 | 
								endpoints: person.endpoints,
 | 
				
			||||||
			uri: person.id,
 | 
								uri: person.id,
 | 
				
			||||||
			url: person.url,
 | 
								url: person.url,
 | 
				
			||||||
 | 
								fields,
 | 
				
			||||||
			isBot: isBot,
 | 
								isBot: isBot,
 | 
				
			||||||
			isCat: (person as any).isCat === true
 | 
								isCat: (person as any).isCat === true
 | 
				
			||||||
		}) as IRemoteUser;
 | 
							}) as IRemoteUser;
 | 
				
			||||||
| 
						 | 
					@ -325,6 +331,10 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const emojiNames = emojis.map(emoji => emoji.name);
 | 
						const emojiNames = emojis.map(emoji => emoji.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const fields = await extractFields(person.attachment).catch(e => {
 | 
				
			||||||
 | 
							console.log(`cat not extract fields: ${e}`);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Update user
 | 
						// Update user
 | 
				
			||||||
	await User.update({ _id: exist._id }, {
 | 
						await User.update({ _id: exist._id }, {
 | 
				
			||||||
		$set: {
 | 
							$set: {
 | 
				
			||||||
| 
						 | 
					@ -346,6 +356,7 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
 | 
				
			||||||
			name: person.name,
 | 
								name: person.name,
 | 
				
			||||||
			url: person.url,
 | 
								url: person.url,
 | 
				
			||||||
			endpoints: person.endpoints,
 | 
								endpoints: person.endpoints,
 | 
				
			||||||
 | 
								fields,
 | 
				
			||||||
			isBot: object.type == 'Service',
 | 
								isBot: object.type == 'Service',
 | 
				
			||||||
			isCat: (person as any).isCat === true,
 | 
								isCat: (person as any).isCat === true,
 | 
				
			||||||
			isLocked: person.manuallyApprovesFollowers,
 | 
								isLocked: person.manuallyApprovesFollowers,
 | 
				
			||||||
| 
						 | 
					@ -382,6 +393,18 @@ export async function resolvePerson(uri: string, verifier?: string, resolver?: R
 | 
				
			||||||
	return await createPerson(uri, resolver);
 | 
						return await createPerson(uri, resolver);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function extractFields(attachments: ITag[]) {
 | 
				
			||||||
 | 
						if (!attachments) return [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return attachments.filter(a => a.type === 'PropertyValue' && a.name && a.value)
 | 
				
			||||||
 | 
							.map(a => {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									name: a.name,
 | 
				
			||||||
 | 
									value: htmlToMFM(a.value)
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function updateFeatured(userId: mongo.ObjectID) {
 | 
					export async function updateFeatured(userId: mongo.ObjectID) {
 | 
				
			||||||
	const user = await User.findOne({ _id: userId });
 | 
						const user = await User.findOne({ _id: userId });
 | 
				
			||||||
	if (!isRemoteUser(user)) return;
 | 
						if (!isRemoteUser(user)) return;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ export type ITag = {
 | 
				
			||||||
	id: string;
 | 
						id: string;
 | 
				
			||||||
	type: string;
 | 
						type: string;
 | 
				
			||||||
	name?: string;
 | 
						name?: string;
 | 
				
			||||||
 | 
						value?: string;
 | 
				
			||||||
	updated?: Date;
 | 
						updated?: Date;
 | 
				
			||||||
	icon?: IIcon;
 | 
						icon?: IIcon;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue