From 069281b6bd84565d96b9d838553162e88a611fac Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 16 Apr 2021 17:34:06 +0900 Subject: [PATCH] =?UTF-8?q?=E8=A9=B3=E7=B4=B0=E3=83=A6=E3=83=BC=E3=82=B6?= =?UTF-8?q?=E3=83=BC=E6=83=85=E5=A0=B1=E3=83=9A=E3=83=BC=E3=82=B8=E3=81=AA?= =?UTF-8?q?=E3=81=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/ja-JP.yml | 3 + src/client/components/form/base.vue | 10 +- src/client/components/form/group.vue | 52 ++++++-- src/client/components/form/key-value-view.vue | 2 +- src/client/components/form/object-view.vue | 102 ++++++++++++++ src/client/components/form/suspense.vue | 76 +++++++++++ src/client/pages/instance-info.vue | 124 ++++++++++++++++++ src/client/pages/user-ap-info.vue | 122 +++++++++++++++++ src/client/pages/user-info.vue | 87 ++++++++++++ src/client/router.ts | 3 + src/client/scripts/get-user-menu.ts | 8 +- src/client/style.scss | 2 +- src/models/repositories/user.ts | 1 + src/server/api/endpoints/ap/get.ts | 38 ++++++ 14 files changed, 614 insertions(+), 16 deletions(-) create mode 100644 src/client/components/form/object-view.vue create mode 100644 src/client/components/form/suspense.vue create mode 100644 src/client/pages/instance-info.vue create mode 100644 src/client/pages/user-ap-info.vue create mode 100644 src/client/pages/user-info.vue create mode 100644 src/server/api/endpoints/ap/get.ts diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 741a5a619..86deff675 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -719,6 +719,9 @@ quitFullView: "フルビュー解除" addDescription: "説明を追加" userPagePinTip: "個々のノートのメニューから「ピン留め」を選択することで、ここにノートを表示しておくことができます。" notSpecifiedMentionWarning: "宛先に含まれていないメンションがあります" +info: "情報" +userInfo: "ユーザー情報" +unknown: "不明" _email: _follow: diff --git a/src/client/components/form/base.vue b/src/client/components/form/base.vue index 84438a5b3..de46d1bd1 100644 --- a/src/client/components/form/base.vue +++ b/src/client/components/form/base.vue @@ -40,16 +40,16 @@ export default defineComponent({ } ._form_group { - > * { - &:not(:first-child) { + > *:not(._formNoConcat) { + &:not(:last-child):not(._formNoConcatPrev) { &._formPanel, ._formPanel { - border-top: none; + border-bottom: solid 0.5px var(--divider); } } - &:not(:last-child) { + &:not(:first-child):not(._formNoConcatNext) { &._formPanel, ._formPanel { - border-bottom: solid 0.5px var(--divider); + border-top: none; } } } diff --git a/src/client/components/form/group.vue b/src/client/components/form/group.vue index 9af33013a..34ccaeff0 100644 --- a/src/client/components/form/group.vue +++ b/src/client/components/form/group.vue @@ -1,7 +1,7 @@ diff --git a/src/client/components/form/suspense.vue b/src/client/components/form/suspense.vue new file mode 100644 index 000000000..4b47cb959 --- /dev/null +++ b/src/client/components/form/suspense.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/src/client/pages/instance-info.vue b/src/client/pages/instance-info.vue new file mode 100644 index 000000000..420ecc31b --- /dev/null +++ b/src/client/pages/instance-info.vue @@ -0,0 +1,124 @@ + + + diff --git a/src/client/pages/user-ap-info.vue b/src/client/pages/user-ap-info.vue new file mode 100644 index 000000000..d86437830 --- /dev/null +++ b/src/client/pages/user-ap-info.vue @@ -0,0 +1,122 @@ + + + diff --git a/src/client/pages/user-info.vue b/src/client/pages/user-info.vue new file mode 100644 index 000000000..a1ff56106 --- /dev/null +++ b/src/client/pages/user-info.vue @@ -0,0 +1,87 @@ + + + diff --git a/src/client/router.ts b/src/client/router.ts index 3effb2edb..bf45c806e 100644 --- a/src/client/router.ts +++ b/src/client/router.ts @@ -72,6 +72,9 @@ export const router = createRouter({ { path: '/instance/abuses', component: page('instance/abuses') }, { path: '/notes/:note', name: 'note', component: page('note'), props: route => ({ noteId: route.params.note }) }, { path: '/tags/:tag', component: page('tag'), props: route => ({ tag: route.params.tag }) }, + { path: '/user-info/:user', component: page('user-info'), props: route => ({ userId: route.params.user }) }, + { path: '/user-ap-info/:user', component: page('user-ap-info'), props: route => ({ userId: route.params.user }) }, + { path: '/instance-info/:host', component: page('instance-info'), props: route => ({ host: route.params.host }) }, { path: '/games/reversi', component: page('reversi/index') }, { path: '/games/reversi/:gameId', component: page('reversi/game'), props: route => ({ gameId: route.params.gameId }) }, { path: '/mfm-cheat-sheet', component: page('mfm-cheat-sheet') }, diff --git a/src/client/scripts/get-user-menu.ts b/src/client/scripts/get-user-menu.ts index 163eff619..0496e8750 100644 --- a/src/client/scripts/get-user-menu.ts +++ b/src/client/scripts/get-user-menu.ts @@ -1,4 +1,4 @@ -import { faAt, faListUl, faEye, faEyeSlash, faBan, faPencilAlt, faComments, faUsers, faMicrophoneSlash, faPlug, faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; +import { faAt, faListUl, faEye, faEyeSlash, faBan, faPencilAlt, faComments, faUsers, faMicrophoneSlash, faPlug, faExclamationCircle, faInfoCircle } from '@fortawesome/free-solid-svg-icons'; import { faSnowflake, faEnvelope } from '@fortawesome/free-regular-svg-icons'; import { i18n } from '@client/i18n'; import copyToClipboard from '@client/scripts/copy-to-clipboard'; @@ -126,6 +126,12 @@ export function getUserMenu(user) { action: () => { copyToClipboard(`@${user.username}@${user.host || host}`); } + }, { + icon: faInfoCircle, + text: i18n.locale.info, + action: () => { + os.pageWindow(`/user-info/${user.id}`); + } }, { icon: faEnvelope, text: i18n.locale.sendMessage, diff --git a/src/client/style.scss b/src/client/style.scss index b12299422..eadf56bf3 100644 --- a/src/client/style.scss +++ b/src/client/style.scss @@ -455,7 +455,7 @@ hr { } ._monospace { - font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace; + font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace !important; } ._code { diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts index bb084f024..203b878fb 100644 --- a/src/models/repositories/user.ts +++ b/src/models/repositories/user.ts @@ -195,6 +195,7 @@ export class UserRepository extends Repository { ...(opts.detail ? { url: profile!.url, + uri: user.uri, createdAt: user.createdAt.toISOString(), updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null, bannerUrl: user.bannerUrl, diff --git a/src/server/api/endpoints/ap/get.ts b/src/server/api/endpoints/ap/get.ts new file mode 100644 index 000000000..c889d472b --- /dev/null +++ b/src/server/api/endpoints/ap/get.ts @@ -0,0 +1,38 @@ +import $ from 'cafy'; +import define from '../../define'; +import Resolver from '../../../../remote/activitypub/resolver'; +import { ApiError } from '../../error'; + +export const meta = { + tags: ['federation'], + + desc: { + 'ja-JP': 'URIを指定してActivityPubオブジェクトを参照します。', + 'en-US': 'Browse to the ActivityPub object by specifying the URI.' + }, + + requireCredential: false as const, + + params: { + uri: { + validator: $.str, + desc: { + 'ja-JP': 'ActivityPubオブジェクトのURI' + } + }, + }, + + errors: { + }, + + res: { + type: 'object' as const, + optional: false as const, nullable: false as const, + } +}; + +export default define(meta, async (ps) => { + const resolver = new Resolver(); + const object = await resolver.resolve(ps.uri); + return object; +});