fix(frontend/XHome): fall back to user.uri if user.url does not exist (#10313)

* fix(frontend/XHome): fall back to user.uri if user.url does not exist

* Update CHANGELOG.md
This commit is contained in:
Kagami Sascha Rosylight 2023-03-13 01:46:33 +01:00 committed by GitHub
parent 44213812b8
commit 0d2bee787d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 22 deletions

View file

@ -34,6 +34,7 @@ You should also include the user name that made the change.
- API上で`visibility`を`followers`に設定してrenoteすると連合や削除で不具合が発生する問題を修正 - API上で`visibility`を`followers`に設定してrenoteすると連合や削除で不具合が発生する問題を修正
- AWS S3からのファイル削除でNoSuchKeyエラーが出ると進めらない状態になる問題を修正 - AWS S3からのファイル削除でNoSuchKeyエラーが出ると進めらない状態になる問題を修正
- fix(frontend): Safariでプラグインが複数ある場合に正常に読み込まれない問題を修正 - fix(frontend): Safariでプラグインが複数ある場合に正常に読み込まれない問題を修正
- Bookwyrmのユーザーのプロフィールページで「リモートで表示」をタップしても反応がない問題を修正
## 13.9.2 (2023/03/06) ## 13.9.2 (2023/03/06)

View file

@ -1,5 +1,5 @@
<template> <template>
<span v-if="!link" v-user-preview="preview ? user.id : undefined" class="_noSelect" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: $store.state.squareAvatars }]" :style="{ color }" :title="acct(user)" @click="onClick"> <span v-if="!link" v-user-preview="preview ? user.id : undefined" class="_noSelect" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: squareAvatars }]" :style="{ color }" :title="acct(user)" @click="onClick">
<img :class="$style.inner" :src="url" decoding="async"/> <img :class="$style.inner" :src="url" decoding="async"/>
<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/> <MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/>
<template v-if="user.isCat"> <template v-if="user.isCat">
@ -7,7 +7,7 @@
<div :class="$style.earRight"/> <div :class="$style.earRight"/>
</template> </template>
</span> </span>
<MkA v-else v-user-preview="preview ? user.id : undefined" class="_noSelect" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: $store.state.squareAvatars }]" :style="{ color }" :title="acct(user)" :to="userPage(user)" :target="target"> <MkA v-else v-user-preview="preview ? user.id : undefined" class="_noSelect" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: squareAvatars }]" :style="{ color }" :title="acct(user)" :to="userPage(user)" :target="target">
<img :class="$style.inner" :src="url" decoding="async"/> <img :class="$style.inner" :src="url" decoding="async"/>
<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/> <MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/>
<template v-if="user.isCat"> <template v-if="user.isCat">
@ -26,6 +26,8 @@ import { acct, userPage } from '@/filters/user';
import MkUserOnlineIndicator from '@/components/MkUserOnlineIndicator.vue'; import MkUserOnlineIndicator from '@/components/MkUserOnlineIndicator.vue';
import { defaultStore } from '@/store'; import { defaultStore } from '@/store';
const squareAvatars = $ref(defaultStore.state.squareAvatars);
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
user: misskey.entities.User; user: misskey.entities.User;
target?: string | null; target?: string | null;

View file

@ -20,26 +20,32 @@ import MkSpacer from './global/MkSpacer.vue';
import MkStickyContainer from './global/MkStickyContainer.vue'; import MkStickyContainer from './global/MkStickyContainer.vue';
export default function(app: App) { export default function(app: App) {
app.component('I18n', I18n); for (const [key, value] of Object.entries(components)) {
app.component('RouterView', RouterView); app.component(key, value);
app.component('Mfm', Mfm); }
app.component('MkA', MkA);
app.component('MkAcct', MkAcct);
app.component('MkAvatar', MkAvatar);
app.component('MkEmoji', MkEmoji);
app.component('MkCustomEmoji', MkCustomEmoji);
app.component('MkUserName', MkUserName);
app.component('MkEllipsis', MkEllipsis);
app.component('MkTime', MkTime);
app.component('MkUrl', MkUrl);
app.component('MkLoading', MkLoading);
app.component('MkError', MkError);
app.component('MkAd', MkAd);
app.component('MkPageHeader', MkPageHeader);
app.component('MkSpacer', MkSpacer);
app.component('MkStickyContainer', MkStickyContainer);
} }
export const components = {
I18n: I18n,
RouterView: RouterView,
Mfm: Mfm,
MkA: MkA,
MkAcct: MkAcct,
MkAvatar: MkAvatar,
MkEmoji: MkEmoji,
MkCustomEmoji: MkCustomEmoji,
MkUserName: MkUserName,
MkEllipsis: MkEllipsis,
MkTime: MkTime,
MkUrl: MkUrl,
MkLoading: MkLoading,
MkError: MkError,
MkAd: MkAd,
MkPageHeader: MkPageHeader,
MkSpacer: MkSpacer,
MkStickyContainer: MkStickyContainer,
};
declare module '@vue/runtime-core' { declare module '@vue/runtime-core' {
export interface GlobalComponents { export interface GlobalComponents {
I18n: typeof I18n; I18n: typeof I18n;

View file

@ -7,7 +7,7 @@
<!-- <div class="punished" v-if="user.isSilenced"><i class="ti ti-alert-triangle" style="margin-right: 8px;"></i> {{ i18n.ts.userSilenced }}</div> --> <!-- <div class="punished" v-if="user.isSilenced"><i class="ti ti-alert-triangle" style="margin-right: 8px;"></i> {{ i18n.ts.userSilenced }}</div> -->
<div class="profile _gaps"> <div class="profile _gaps">
<MkRemoteCaution v-if="user.host != null" :href="user.url" class="warn"/> <MkRemoteCaution v-if="user.host != null" :href="user.url ?? user.uri!" class="warn"/>
<div :key="user.id" class="main _panel"> <div :key="user.id" class="main _panel">
<div class="banner-container" :style="style"> <div class="banner-container" :style="style">
@ -100,7 +100,7 @@
<XPhotos :key="user.id" :user="user"/> <XPhotos :key="user.id" :user="user"/>
<XActivity :key="user.id" :user="user"/> <XActivity :key="user.id" :user="user"/>
</template> </template>
<MkNotes :class="$style.tl" :no-gap="true" :pagination="pagination"/> <MkNotes v-if="!disableNotes" :class="$style.tl" :no-gap="true" :pagination="pagination"/>
</div> </div>
</div> </div>
<div v-if="!narrow" class="sub _gaps" style="container-type: inline-size;"> <div v-if="!narrow" class="sub _gaps" style="container-type: inline-size;">
@ -137,7 +137,10 @@ const XActivity = defineAsyncComponent(() => import('./index.activity.vue'));
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
user: misskey.entities.UserDetailed; user: misskey.entities.UserDetailed;
/** Test only; MkNotes currently causes problems in vitest */
disableNotes: boolean;
}>(), { }>(), {
disableNotes: false,
}); });
const router = useRouter(); const router = useRouter();

View file

@ -0,0 +1,58 @@
import { describe, test, assert, afterEach } from 'vitest';
import { render, cleanup, type RenderResult } from '@testing-library/vue';
import './init';
import type * as misskey from 'misskey-js';
import { directives } from '@/directives';
import { components } from '@/components/index';
import XHome from '@/pages/user/home.vue';
describe('XHome', () => {
const renderHome = (user: Partial<misskey.entities.UserDetailed>): RenderResult => {
return render(XHome, {
props: { user, disableNotes: true },
global: { directives, components },
});
};
afterEach(() => {
cleanup();
});
test('Should render the remote caution when user.host exists', async () => {
const home = renderHome({
id: 'blobcat',
name: 'blobcat',
host: 'example.com',
uri: 'https://example.com/@user',
url: 'https://example.com/@user/profile',
roles: [],
createdAt: '1970-01-01T00:00:00.000Z',
fields: [],
pinnedNotes: [],
});
const anchor = home.container.querySelector<HTMLAnchorElement>('a[href^="https://example.com/"]');
assert.exists(anchor, 'anchor to the remote exists');
assert.strictEqual(anchor?.href, 'https://example.com/@user/profile');
assert.ok(anchor?.parentElement?.classList.contains('warn'), 'the parent is a warning');
});
test('The remote caution should fall back to uri if url is null', async () => {
const home = renderHome({
id: 'blobcat',
name: 'blobcat',
host: 'example.com',
uri: 'https://example.com/@user',
url: null,
roles: [],
createdAt: '1970-01-01T00:00:00.000Z',
fields: [],
pinnedNotes: [],
});
const anchor = home.container.querySelector<HTMLAnchorElement>('a[href^="https://example.com/"]');
assert.exists(anchor, 'anchor to the remote exists');
assert.strictEqual(anchor?.href, 'https://example.com/@user');
});
});