mirror of
https://github.com/hotomoe/hotomoe
synced 2024-11-25 15:46:17 +09:00
Show user fields (#3590)
This commit is contained in:
parent
1d1a373ca8
commit
638d81b66e
@ -26,6 +26,14 @@
|
||||
<div class="description">
|
||||
<misskey-flavored-markdown v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
|
||||
</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>
|
||||
<b>{{ user.notesCount | number }}</b>
|
||||
@ -416,6 +424,31 @@ export default Vue.extend({
|
||||
border-right solid 16px transparent
|
||||
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
|
||||
display grid
|
||||
grid-template-columns 1fr 1fr 1fr
|
||||
|
@ -18,6 +18,14 @@
|
||||
<div class="description">
|
||||
<misskey-flavored-markdown v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
|
||||
</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">
|
||||
<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>
|
||||
@ -174,6 +182,33 @@ export default Vue.extend({
|
||||
padding 16px 16px 16px 154px
|
||||
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
|
||||
margin-top 16px
|
||||
padding-top 16px
|
||||
|
@ -24,6 +24,14 @@
|
||||
<div class="description">
|
||||
<misskey-flavored-markdown v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
|
||||
</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">
|
||||
<p class="location" v-if="user.host === null && user.profile.location">
|
||||
<fa icon="map-marker"/>{{ user.profile.location }}
|
||||
@ -301,6 +309,33 @@ main
|
||||
margin 8px 0
|
||||
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
|
||||
margin 8px 0
|
||||
|
||||
|
@ -41,7 +41,7 @@ export default function(html: string): string {
|
||||
if ((rel && rel.value.match('tag') !== null) || !href || href.value == txt) {
|
||||
text += txt;
|
||||
// メンション
|
||||
} else if (txt.startsWith('@')) {
|
||||
} else if (txt.startsWith('@') && !rel || !rel.value.match(/^me /)) {
|
||||
const part = txt.split('@');
|
||||
|
||||
if (part.length == 2) {
|
||||
|
@ -109,6 +109,10 @@ export interface ILocalUser extends IUserBase {
|
||||
birthday: string; // 'YYYY-MM-DD'
|
||||
tags: string[];
|
||||
};
|
||||
fields?: {
|
||||
name: string;
|
||||
value: string;
|
||||
}[];
|
||||
isCat: boolean;
|
||||
isAdmin?: boolean;
|
||||
isModerator?: boolean;
|
||||
|
@ -17,6 +17,7 @@ import registerInstance from '../../../services/register-instance';
|
||||
import Instance from '../../../models/instance';
|
||||
import getDriveFileUrl from '../../../misc/get-drive-file-url';
|
||||
import { IEmoji } from '../../../models/emoji';
|
||||
import { ITag } from './tag';
|
||||
|
||||
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 fields = await extractFields(person.attachment).catch(e => {
|
||||
console.log(`cat not extract fields: ${e}`);
|
||||
});
|
||||
|
||||
const isBot = object.type == 'Service';
|
||||
|
||||
// Create user
|
||||
@ -164,6 +169,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<IU
|
||||
endpoints: person.endpoints,
|
||||
uri: person.id,
|
||||
url: person.url,
|
||||
fields,
|
||||
isBot: isBot,
|
||||
isCat: (person as any).isCat === true
|
||||
}) as IRemoteUser;
|
||||
@ -325,6 +331,10 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
|
||||
|
||||
const emojiNames = emojis.map(emoji => emoji.name);
|
||||
|
||||
const fields = await extractFields(person.attachment).catch(e => {
|
||||
console.log(`cat not extract fields: ${e}`);
|
||||
});
|
||||
|
||||
// Update user
|
||||
await User.update({ _id: exist._id }, {
|
||||
$set: {
|
||||
@ -346,6 +356,7 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
|
||||
name: person.name,
|
||||
url: person.url,
|
||||
endpoints: person.endpoints,
|
||||
fields,
|
||||
isBot: object.type == 'Service',
|
||||
isCat: (person as any).isCat === true,
|
||||
isLocked: person.manuallyApprovesFollowers,
|
||||
@ -382,6 +393,18 @@ export async function resolvePerson(uri: string, verifier?: string, resolver?: R
|
||||
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) {
|
||||
const user = await User.findOne({ _id: userId });
|
||||
if (!isRemoteUser(user)) return;
|
||||
|
@ -7,6 +7,7 @@ export type ITag = {
|
||||
id: string;
|
||||
type: string;
|
||||
name?: string;
|
||||
value?: string;
|
||||
updated?: Date;
|
||||
icon?: IIcon;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user