mirror of
https://activitypub.software/TransFem-org/Sharkey
synced 2024-12-22 16:30:13 +00: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
5 changed files with 92 additions and 22 deletions
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
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 a new issue