mirror of
https://github.com/hotomoe/hotomoe
synced 2024-11-24 15:16:13 +09:00
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:
parent
44213812b8
commit
0d2bee787d
@ -34,6 +34,7 @@ You should also include the user name that made the change.
|
||||
- API上で`visibility`を`followers`に設定してrenoteすると連合や削除で不具合が発生する問題を修正
|
||||
- AWS S3からのファイル削除でNoSuchKeyエラーが出ると進めらない状態になる問題を修正
|
||||
- fix(frontend): Safariでプラグインが複数ある場合に正常に読み込まれない問題を修正
|
||||
- Bookwyrmのユーザーのプロフィールページで「リモートで表示」をタップしても反応がない問題を修正
|
||||
|
||||
## 13.9.2 (2023/03/06)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<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"/>
|
||||
<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/>
|
||||
<template v-if="user.isCat">
|
||||
@ -7,7 +7,7 @@
|
||||
<div :class="$style.earRight"/>
|
||||
</template>
|
||||
</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"/>
|
||||
<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/>
|
||||
<template v-if="user.isCat">
|
||||
@ -26,6 +26,8 @@ import { acct, userPage } from '@/filters/user';
|
||||
import MkUserOnlineIndicator from '@/components/MkUserOnlineIndicator.vue';
|
||||
import { defaultStore } from '@/store';
|
||||
|
||||
const squareAvatars = $ref(defaultStore.state.squareAvatars);
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
user: misskey.entities.User;
|
||||
target?: string | null;
|
||||
|
@ -20,26 +20,32 @@ import MkSpacer from './global/MkSpacer.vue';
|
||||
import MkStickyContainer from './global/MkStickyContainer.vue';
|
||||
|
||||
export default function(app: App) {
|
||||
app.component('I18n', I18n);
|
||||
app.component('RouterView', RouterView);
|
||||
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);
|
||||
for (const [key, value] of Object.entries(components)) {
|
||||
app.component(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
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' {
|
||||
export interface GlobalComponents {
|
||||
I18n: typeof I18n;
|
||||
|
@ -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="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 class="banner-container" :style="style">
|
||||
@ -100,7 +100,7 @@
|
||||
<XPhotos :key="user.id" :user="user"/>
|
||||
<XActivity :key="user.id" :user="user"/>
|
||||
</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 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<{
|
||||
user: misskey.entities.UserDetailed;
|
||||
/** Test only; MkNotes currently causes problems in vitest */
|
||||
disableNotes: boolean;
|
||||
}>(), {
|
||||
disableNotes: false,
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
|
58
packages/frontend/test/home.test.ts
Normal file
58
packages/frontend/test/home.test.ts
Normal 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');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user