mirror of
https://github.com/kokonect-link/cherrypick
synced 2025-01-23 02:04:33 +09:00
enhance(frontend): 상대방이 나를 차단한 경우 차단되었음을 알 수 있도록 개선함
- 차단되면 다음 기능들이 화면 상에서 사라지고 사용이 제한됩니다. - 팔로우 버튼 - 사용자 페이지에서 기본 정보 외 다른 모든 정보는 열람할 수 없음 - 사용자 페이지에서 요약 탭 외에 모든 탭이 사용할 수 없게됨
This commit is contained in:
parent
92c8f6721a
commit
652403ca3b
@ -56,6 +56,11 @@ Misskey의 전체 변경 사항을 확인하려면, [CHANGELOG.md#2024xx](CHANGE
|
|||||||
- Enhance: 사용자 페이지와 사용자 팝업 개선
|
- Enhance: 사용자 페이지와 사용자 팝업 개선
|
||||||
- 사용자 페이지와 사용자 팝업에 `새 노트 알림 켜기` 버튼이 추가됨
|
- 사용자 페이지와 사용자 팝업에 `새 노트 알림 켜기` 버튼이 추가됨
|
||||||
- 사용자 페이지에 `사용자 노트 검색` 버튼이 추가됨
|
- 사용자 페이지에 `사용자 노트 검색` 버튼이 추가됨
|
||||||
|
- Enhance: 상대방이 나를 차단한 경우 차단되었음을 알 수 있도록 개선함
|
||||||
|
- 차단되면 다음 기능들이 화면 상에서 사라지고 사용이 제한됩니다.
|
||||||
|
- 팔로우 버튼
|
||||||
|
- 사용자 페이지에서 기본 정보 외 다른 모든 정보는 열람할 수 없음
|
||||||
|
- 사용자 페이지에서 요약 탭 외에 모든 탭이 사용할 수 없게됨
|
||||||
- Fix: 임베디드 코드에서 CherryPick의 색상 설정이 반영되지 않음
|
- Fix: 임베디드 코드에서 CherryPick의 색상 설정이 반영되지 않음
|
||||||
- Fix: 임베디드 코드에 `fade`와 `Temml(KaTex)`가 반영되지 않음
|
- Fix: 임베디드 코드에 `fade`와 `Temml(KaTex)`가 반영되지 않음
|
||||||
- Fix: 노트의 QR 코드를 생성했을 때 `링크 복사` 버튼을 누르면 잘못된 토스트 알림이 표시됨
|
- Fix: 노트의 QR 코드를 생성했을 때 `링크 복사` 버튼을 누르면 잘못된 토스트 알림이 표시됨
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
---
|
---
|
||||||
_lang_: "English"
|
_lang_: "English"
|
||||||
|
youBlocked: "You’re blocked"
|
||||||
|
youBlockedDescription: "You can’t follow or see {user}’s posts."
|
||||||
schedulePost: "Posting a scheduled note"
|
schedulePost: "Posting a scheduled note"
|
||||||
schedulePostList: "List of scheduled notes"
|
schedulePostList: "List of scheduled notes"
|
||||||
welcomeBackToast: "Display a welcome message when you log in after a certain period of time"
|
welcomeBackToast: "Display a welcome message when you log in after a certain period of time"
|
||||||
|
8
locales/index.d.ts
vendored
8
locales/index.d.ts
vendored
@ -13,6 +13,14 @@ export interface Locale extends ILocale {
|
|||||||
* 日本語
|
* 日本語
|
||||||
*/
|
*/
|
||||||
"_lang_": string;
|
"_lang_": string;
|
||||||
|
/**
|
||||||
|
* ブロックされています
|
||||||
|
*/
|
||||||
|
"youBlocked": string;
|
||||||
|
/**
|
||||||
|
* {user}さんのフォローやポストの表示はできません。
|
||||||
|
*/
|
||||||
|
"youBlockedDescription": ParameterizedString<"user">;
|
||||||
/**
|
/**
|
||||||
* 予約投稿
|
* 予約投稿
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
_lang_: "日本語"
|
_lang_: "日本語"
|
||||||
|
|
||||||
|
youBlocked: "ブロックされています"
|
||||||
|
youBlockedDescription: "{user}さんのフォローやポストの表示はできません。"
|
||||||
schedulePost: "予約投稿"
|
schedulePost: "予約投稿"
|
||||||
schedulePostList: "予約投稿一覧"
|
schedulePostList: "予約投稿一覧"
|
||||||
welcomeBackToast: "一定時間が経過した後に接続したときに歓迎メッセージを表示"
|
welcomeBackToast: "一定時間が経過した後に接続したときに歓迎メッセージを表示"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
---
|
---
|
||||||
_lang_: "한국어"
|
_lang_: "한국어"
|
||||||
|
youBlocked: "앗.. 차단당했어요.."
|
||||||
|
youBlockedDescription: "{user} 님을 팔로우하거나 해당 사용자의 게시물을 볼 수 없어요."
|
||||||
schedulePost: "노트 게시 예약"
|
schedulePost: "노트 게시 예약"
|
||||||
schedulePostList: "게시가 예약된 노트 목록"
|
schedulePostList: "게시가 예약된 노트 목록"
|
||||||
welcomeBackToast: "일정 시간이 지난 후 접속했을 때 환영 메시지 표시"
|
welcomeBackToast: "일정 시간이 지난 후 접속했을 때 환영 메시지 표시"
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class YouBlockedImageUrl1730364663000 {
|
||||||
|
name = 'YouBlockedImageUrl1730364663000'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "youBlockedImageUrl" character varying(1024)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "youBlockedImageUrl"`);
|
||||||
|
}
|
||||||
|
}
|
@ -104,6 +104,7 @@ export class MetaEntityService {
|
|||||||
infoImageUrl: instance.infoImageUrl,
|
infoImageUrl: instance.infoImageUrl,
|
||||||
serverErrorImageUrl: instance.serverErrorImageUrl,
|
serverErrorImageUrl: instance.serverErrorImageUrl,
|
||||||
notFoundImageUrl: instance.notFoundImageUrl,
|
notFoundImageUrl: instance.notFoundImageUrl,
|
||||||
|
youBlockedImageUrl: instance.youBlockedImageUrl,
|
||||||
iconUrl: instance.iconUrl,
|
iconUrl: instance.iconUrl,
|
||||||
backgroundImageUrl: instance.backgroundImageUrl,
|
backgroundImageUrl: instance.backgroundImageUrl,
|
||||||
logoImageUrl: instance.logoImageUrl,
|
logoImageUrl: instance.logoImageUrl,
|
||||||
|
@ -157,6 +157,12 @@ export class MiMeta {
|
|||||||
})
|
})
|
||||||
public infoImageUrl: string | null;
|
public infoImageUrl: string | null;
|
||||||
|
|
||||||
|
@Column('varchar', {
|
||||||
|
length: 1024,
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
public youBlockedImageUrl: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column('boolean', {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
|
@ -144,6 +144,10 @@ export const packedMetaLiteSchema = {
|
|||||||
type: 'string',
|
type: 'string',
|
||||||
optional: false, nullable: true,
|
optional: false, nullable: true,
|
||||||
},
|
},
|
||||||
|
youBlockedImageUrl: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false, nullable: true,
|
||||||
|
},
|
||||||
iconUrl: {
|
iconUrl: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: false, nullable: true,
|
optional: false, nullable: true,
|
||||||
|
@ -94,6 +94,10 @@ export const meta = {
|
|||||||
type: 'string',
|
type: 'string',
|
||||||
optional: false, nullable: true,
|
optional: false, nullable: true,
|
||||||
},
|
},
|
||||||
|
youBlockedImageUrl: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false, nullable: true,
|
||||||
|
},
|
||||||
iconUrl: {
|
iconUrl: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: false, nullable: true,
|
optional: false, nullable: true,
|
||||||
@ -654,6 +658,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||||||
serverErrorImageUrl: instance.serverErrorImageUrl,
|
serverErrorImageUrl: instance.serverErrorImageUrl,
|
||||||
notFoundImageUrl: instance.notFoundImageUrl,
|
notFoundImageUrl: instance.notFoundImageUrl,
|
||||||
infoImageUrl: instance.infoImageUrl,
|
infoImageUrl: instance.infoImageUrl,
|
||||||
|
youBlockedImageUrl: instance.youBlockedImageUrl,
|
||||||
iconUrl: instance.iconUrl,
|
iconUrl: instance.iconUrl,
|
||||||
app192IconUrl: instance.app192IconUrl,
|
app192IconUrl: instance.app192IconUrl,
|
||||||
app512IconUrl: instance.app512IconUrl,
|
app512IconUrl: instance.app512IconUrl,
|
||||||
|
@ -54,6 +54,7 @@ export const paramDef = {
|
|||||||
serverErrorImageUrl: { type: 'string', nullable: true },
|
serverErrorImageUrl: { type: 'string', nullable: true },
|
||||||
infoImageUrl: { type: 'string', nullable: true },
|
infoImageUrl: { type: 'string', nullable: true },
|
||||||
notFoundImageUrl: { type: 'string', nullable: true },
|
notFoundImageUrl: { type: 'string', nullable: true },
|
||||||
|
youBlockedImageUrl: { type: 'string', nullable: true },
|
||||||
iconUrl: { type: 'string', nullable: true },
|
iconUrl: { type: 'string', nullable: true },
|
||||||
app192IconUrl: { type: 'string', nullable: true },
|
app192IconUrl: { type: 'string', nullable: true },
|
||||||
app512IconUrl: { type: 'string', nullable: true },
|
app512IconUrl: { type: 'string', nullable: true },
|
||||||
@ -302,6 +303,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||||||
set.notFoundImageUrl = ps.notFoundImageUrl;
|
set.notFoundImageUrl = ps.notFoundImageUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ps.youBlockedImageUrl !== undefined) {
|
||||||
|
set.youBlockedImageUrl = ps.youBlockedImageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
if (ps.backgroundImageUrl !== undefined) {
|
if (ps.backgroundImageUrl !== undefined) {
|
||||||
set.backgroundImageUrl = ps.backgroundImageUrl;
|
set.backgroundImageUrl = ps.backgroundImageUrl;
|
||||||
}
|
}
|
||||||
|
@ -198,6 +198,7 @@ export class ClientServerService {
|
|||||||
serverErrorImageUrl: meta.serverErrorImageUrl ?? 'https://xn--931a.moe/assets/error.jpg',
|
serverErrorImageUrl: meta.serverErrorImageUrl ?? 'https://xn--931a.moe/assets/error.jpg',
|
||||||
infoImageUrl: meta.infoImageUrl ?? 'https://xn--931a.moe/assets/info.jpg',
|
infoImageUrl: meta.infoImageUrl ?? 'https://xn--931a.moe/assets/info.jpg',
|
||||||
notFoundImageUrl: meta.notFoundImageUrl ?? 'https://xn--931a.moe/assets/not-found.jpg',
|
notFoundImageUrl: meta.notFoundImageUrl ?? 'https://xn--931a.moe/assets/not-found.jpg',
|
||||||
|
youBlockedImageUrl: meta.youBlockedImageUrl ?? 'https://xn--931a.moe/assets/error.jpg',
|
||||||
instanceUrl: this.config.url,
|
instanceUrl: this.config.url,
|
||||||
metaJson: htmlSafeJsonStringify(await this.metaEntityService.packDetailed(meta)),
|
metaJson: htmlSafeJsonStringify(await this.metaEntityService.packDetailed(meta)),
|
||||||
now: Date.now(),
|
now: Date.now(),
|
||||||
|
@ -5334,6 +5334,7 @@ export type components = {
|
|||||||
serverErrorImageUrl: string | null;
|
serverErrorImageUrl: string | null;
|
||||||
infoImageUrl: string | null;
|
infoImageUrl: string | null;
|
||||||
notFoundImageUrl: string | null;
|
notFoundImageUrl: string | null;
|
||||||
|
youBlockedImageUrl: string | null;
|
||||||
iconUrl: string | null;
|
iconUrl: string | null;
|
||||||
maxNoteTextLength: number;
|
maxNoteTextLength: number;
|
||||||
ads: {
|
ads: {
|
||||||
@ -5465,6 +5466,7 @@ export type operations = {
|
|||||||
serverErrorImageUrl: string | null;
|
serverErrorImageUrl: string | null;
|
||||||
infoImageUrl: string | null;
|
infoImageUrl: string | null;
|
||||||
notFoundImageUrl: string | null;
|
notFoundImageUrl: string | null;
|
||||||
|
youBlockedImageUrl: string | null;
|
||||||
iconUrl: string | null;
|
iconUrl: string | null;
|
||||||
app192IconUrl: string | null;
|
app192IconUrl: string | null;
|
||||||
app512IconUrl: string | null;
|
app512IconUrl: string | null;
|
||||||
@ -10152,6 +10154,7 @@ export type operations = {
|
|||||||
serverErrorImageUrl?: string | null;
|
serverErrorImageUrl?: string | null;
|
||||||
infoImageUrl?: string | null;
|
infoImageUrl?: string | null;
|
||||||
notFoundImageUrl?: string | null;
|
notFoundImageUrl?: string | null;
|
||||||
|
youBlockedImageUrl?: string | null;
|
||||||
iconUrl?: string | null;
|
iconUrl?: string | null;
|
||||||
app192IconUrl?: string | null;
|
app192IconUrl?: string | null;
|
||||||
app512IconUrl?: string | null;
|
app512IconUrl?: string | null;
|
||||||
|
@ -120,6 +120,7 @@ export const CURRENT_STICKY_BOTTOM = 'CURRENT_STICKY_BOTTOM';
|
|||||||
export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://xn--931a.moe/assets/error.jpg';
|
export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://xn--931a.moe/assets/error.jpg';
|
||||||
export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://xn--931a.moe/assets/not-found.jpg';
|
export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://xn--931a.moe/assets/not-found.jpg';
|
||||||
export const DEFAULT_INFO_IMAGE_URL = 'https://xn--931a.moe/assets/info.jpg';
|
export const DEFAULT_INFO_IMAGE_URL = 'https://xn--931a.moe/assets/info.jpg';
|
||||||
|
export const DEFAULT_YOU_BLOCKED_IMAGE_URL = 'https://xn--931a.moe/assets/error.jpg';
|
||||||
|
|
||||||
export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'border', 'font', 'blur', 'rainbow', 'sparkle', 'fade', 'rotate', 'ruby', 'unixtime'];
|
export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'border', 'font', 'blur', 'rainbow', 'sparkle', 'fade', 'rotate', 'ruby', 'unixtime'];
|
||||||
export const MFM_PARAMS: Record<typeof MFM_TAGS[number], string[]> = {
|
export const MFM_PARAMS: Record<typeof MFM_TAGS[number], string[]> = {
|
||||||
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
v-if="(!disableIfFollowing || !isFollowing) && ($i != null && $i.id != user.id)"
|
v-if="(!disableIfFollowing || !isFollowing) && ($i != null && $i.id != user.id) && !user.isBlocked"
|
||||||
class="_button"
|
class="_button"
|
||||||
:class="[$style.root, { [$style.wait]: wait, [$style.active]: isFollowing || hasPendingFollowRequestFromYou, [$style.full]: full, [$style.large]: large }]"
|
:class="[$style.root, { [$style.wait]: wait, [$style.active]: isFollowing || hasPendingFollowRequestFromYou, [$style.full]: full, [$style.large]: large }]"
|
||||||
:disabled="wait"
|
:disabled="wait"
|
||||||
|
@ -29,7 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<p :class="$style.statusItemLabel">{{ i18n.ts.followers }}</p><span :class="$style.statusItemValue">{{ number(user.followersCount) }}</span>
|
<p :class="$style.statusItemLabel">{{ i18n.ts.followers }}</p><span :class="$style.statusItemValue">{{ number(user.followersCount) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MkFollowButton v-if="user.id != $i?.id" :class="$style.follow" :user="user" mini/>
|
<MkFollowButton v-if="user.id != $i?.id && !user.isBlocked" :class="$style.follow" :user="user" mini/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -44,9 +44,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<div>{{ number(user.followersCount) }}</div>
|
<div>{{ number(user.followersCount) }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="_button" :class="$style.menu" @click="showMenu"><i class="ti ti-dots"></i></button>
|
<button class="_button" :class="[$style.menu, { [$style.isBlocked]: user.isBlocked }]" @click="showMenu"><i class="ti ti-dots"></i></button>
|
||||||
<button v-tooltip="user.notify === 'none' ? i18n.ts.notifyNotes : i18n.ts.unnotifyNotes" class="_button" :class="$style.notify" @click="toggleNotify"><i :class="user.notify === 'none' ? 'ti ti-bell-plus' : 'ti ti-bell-minus'"></i></button>
|
<button v-tooltip="user.notify === 'none' ? i18n.ts.notifyNotes : i18n.ts.unnotifyNotes" class="_button" :class="[$style.notify, { [$style.isBlocked]: user.isBlocked }]" @click="toggleNotify"><i :class="user.notify === 'none' ? 'ti ti-bell-plus' : 'ti ti-bell-minus'"></i></button>
|
||||||
<MkFollowButton v-model:user="user" :class="$style.follow" mini/>
|
<MkFollowButton v-if="!user.isBlocked" v-model:user="user" :class="$style.follow" mini/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<MkLoading/>
|
<MkLoading/>
|
||||||
@ -260,8 +260,18 @@ onMounted(() => {
|
|||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
&.isBlocked {
|
||||||
|
right: 44px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.notify {
|
.notify {
|
||||||
right: 44px;
|
right: 44px;
|
||||||
|
|
||||||
|
&.isBlocked {
|
||||||
|
right: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.follow {
|
.follow {
|
||||||
|
@ -52,7 +52,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="!thin_ && !canBack && !(actions && actions.length > 0)" :class="$style.buttonsRight"/>
|
<div v-else-if="!thin_ && !canBack && !(actions && actions.length > 0)" :class="$style.buttonsRight"/>
|
||||||
<div v-if="pageMetadata && pageMetadata.avatar && ($i && $i.id !== pageMetadata.userName?.id)" :class="$style.followButton">
|
<div v-if="pageMetadata && pageMetadata.avatar && ($i && $i.id !== pageMetadata.userName?.id) && !disableFollowButton" :class="$style.followButton">
|
||||||
<MkFollowButton v-if="mainRouter.currentRoute.value.name === 'user'" :user="pageMetadata.avatar" :transparent="false" :full="!narrow"/>
|
<MkFollowButton v-if="mainRouter.currentRoute.value.name === 'user'" :user="pageMetadata.avatar" :transparent="false" :full="!narrow"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -90,6 +90,7 @@ const props = withDefaults(defineProps<{
|
|||||||
actions?: PageHeaderItem[] | null;
|
actions?: PageHeaderItem[] | null;
|
||||||
thin?: boolean;
|
thin?: boolean;
|
||||||
displayMyAvatar?: boolean;
|
displayMyAvatar?: boolean;
|
||||||
|
disableFollowButton?: boolean;
|
||||||
}>(), {
|
}>(), {
|
||||||
tabs: () => ([] as Tab[]),
|
tabs: () => ([] as Tab[]),
|
||||||
});
|
});
|
||||||
|
@ -55,7 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="!thin_ && !canBack && !(actions && actions.length > 0)" :class="$style.buttonsRight"/>
|
<div v-else-if="!thin_ && !canBack && !(actions && actions.length > 0)" :class="$style.buttonsRight"/>
|
||||||
<div v-if="pageMetadata && pageMetadata.avatar && ($i && $i.id !== pageMetadata.userName?.id) && mainRouter.currentRoute.value.name === 'user'" :class="$style.followButton">
|
<div v-if="pageMetadata && pageMetadata.avatar && ($i && $i.id !== pageMetadata.userName?.id) && mainRouter.currentRoute.value.name === 'user' && !disableFollowButton" :class="$style.followButton">
|
||||||
<MkFollowButton :user="pageMetadata.avatar" :transparent="false" :full="!narrow"/>
|
<MkFollowButton :user="pageMetadata.avatar" :transparent="false" :full="!narrow"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -92,6 +92,7 @@ const props = withDefaults(defineProps<{
|
|||||||
actions?: PageHeaderItem[] | null;
|
actions?: PageHeaderItem[] | null;
|
||||||
thin?: boolean;
|
thin?: boolean;
|
||||||
displayMyAvatar?: boolean;
|
displayMyAvatar?: boolean;
|
||||||
|
disableFollowButton?: boolean;
|
||||||
}>(), {
|
}>(), {
|
||||||
tabs: () => ([] as Tab[]),
|
tabs: () => ([] as Tab[]),
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import { computed, reactive } from 'vue';
|
import { computed, reactive } from 'vue';
|
||||||
import * as Misskey from 'cherrypick-js';
|
import * as Misskey from 'cherrypick-js';
|
||||||
import { DEFAULT_INFO_IMAGE_URL, DEFAULT_NOT_FOUND_IMAGE_URL, DEFAULT_SERVER_ERROR_IMAGE_URL } from '@@/js/const.js';
|
import { DEFAULT_INFO_IMAGE_URL, DEFAULT_NOT_FOUND_IMAGE_URL, DEFAULT_SERVER_ERROR_IMAGE_URL, DEFAULT_YOU_BLOCKED_IMAGE_URL } from '@@/js/const.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { miLocalStorage } from '@/local-storage.js';
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
|
|
||||||
@ -36,6 +36,8 @@ export const infoImageUrl = computed(() => instance.infoImageUrl ?? DEFAULT_INFO
|
|||||||
|
|
||||||
export const notFoundImageUrl = computed(() => instance.notFoundImageUrl ?? DEFAULT_NOT_FOUND_IMAGE_URL);
|
export const notFoundImageUrl = computed(() => instance.notFoundImageUrl ?? DEFAULT_NOT_FOUND_IMAGE_URL);
|
||||||
|
|
||||||
|
export const youBlockedImageUrl = computed(() => instance.youBlockedImageUrl ?? DEFAULT_YOU_BLOCKED_IMAGE_URL);
|
||||||
|
|
||||||
export const isEnabledUrlPreview = computed(() => instance.enableUrlPreview ?? true);
|
export const isEnabledUrlPreview = computed(() => instance.enableUrlPreview ?? true);
|
||||||
|
|
||||||
export async function fetchInstance(force = false): Promise<Misskey.entities.MetaDetailed> {
|
export async function fetchInstance(force = false): Promise<Misskey.entities.MetaDetailed> {
|
||||||
|
@ -62,6 +62,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<template #label>{{ i18n.ts.somethingHappened }}</template>
|
<template #label>{{ i18n.ts.somethingHappened }}</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
|
|
||||||
|
<MkInput v-model="youBlockedImageUrl" type="url">
|
||||||
|
<template #prefix><i class="ti ti-link"></i></template>
|
||||||
|
<template #label>{{ i18n.ts.youBlocked }}</template>
|
||||||
|
</MkInput>
|
||||||
|
|
||||||
<MkColorInput v-model="themeColor">
|
<MkColorInput v-model="themeColor">
|
||||||
<template #label>{{ i18n.ts.themeColor }}</template>
|
<template #label>{{ i18n.ts.themeColor }}</template>
|
||||||
</MkColorInput>
|
</MkColorInput>
|
||||||
@ -135,6 +140,7 @@ const defaultDarkTheme = ref<string | null>(null);
|
|||||||
const serverErrorImageUrl = ref<string | null>(null);
|
const serverErrorImageUrl = ref<string | null>(null);
|
||||||
const infoImageUrl = ref<string | null>(null);
|
const infoImageUrl = ref<string | null>(null);
|
||||||
const notFoundImageUrl = ref<string | null>(null);
|
const notFoundImageUrl = ref<string | null>(null);
|
||||||
|
const youBlockedImageUrl = ref<string | null>(null);
|
||||||
const repositoryUrl = ref<string | null>(null);
|
const repositoryUrl = ref<string | null>(null);
|
||||||
const feedbackUrl = ref<string | null>(null);
|
const feedbackUrl = ref<string | null>(null);
|
||||||
const manifestJsonOverride = ref<string>('{}');
|
const manifestJsonOverride = ref<string>('{}');
|
||||||
@ -153,6 +159,7 @@ async function init() {
|
|||||||
serverErrorImageUrl.value = meta.serverErrorImageUrl;
|
serverErrorImageUrl.value = meta.serverErrorImageUrl;
|
||||||
infoImageUrl.value = meta.infoImageUrl;
|
infoImageUrl.value = meta.infoImageUrl;
|
||||||
notFoundImageUrl.value = meta.notFoundImageUrl;
|
notFoundImageUrl.value = meta.notFoundImageUrl;
|
||||||
|
youBlockedImageUrl.value = meta.youBlockedImageUrl;
|
||||||
repositoryUrl.value = meta.repositoryUrl;
|
repositoryUrl.value = meta.repositoryUrl;
|
||||||
feedbackUrl.value = meta.feedbackUrl;
|
feedbackUrl.value = meta.feedbackUrl;
|
||||||
manifestJsonOverride.value = meta.manifestJsonOverride === '' ? '{}' : JSON.stringify(JSON.parse(meta.manifestJsonOverride), null, '\t');
|
manifestJsonOverride.value = meta.manifestJsonOverride === '' ? '{}' : JSON.stringify(JSON.parse(meta.manifestJsonOverride), null, '\t');
|
||||||
@ -171,6 +178,7 @@ function save() {
|
|||||||
defaultDarkTheme: defaultDarkTheme.value === '' ? null : defaultDarkTheme.value,
|
defaultDarkTheme: defaultDarkTheme.value === '' ? null : defaultDarkTheme.value,
|
||||||
infoImageUrl: infoImageUrl.value === '' ? null : infoImageUrl.value,
|
infoImageUrl: infoImageUrl.value === '' ? null : infoImageUrl.value,
|
||||||
notFoundImageUrl: notFoundImageUrl.value === '' ? null : notFoundImageUrl.value,
|
notFoundImageUrl: notFoundImageUrl.value === '' ? null : notFoundImageUrl.value,
|
||||||
|
youBlockedImageUrl: youBlockedImageUrl.value === '' ? null : youBlockedImageUrl.value,
|
||||||
serverErrorImageUrl: serverErrorImageUrl.value === '' ? null : serverErrorImageUrl.value,
|
serverErrorImageUrl: serverErrorImageUrl.value === '' ? null : serverErrorImageUrl.value,
|
||||||
repositoryUrl: repositoryUrl.value === '' ? null : repositoryUrl.value,
|
repositoryUrl: repositoryUrl.value === '' ? null : repositoryUrl.value,
|
||||||
feedbackUrl: feedbackUrl.value === '' ? null : feedbackUrl.value,
|
feedbackUrl: feedbackUrl.value === '' ? null : feedbackUrl.value,
|
||||||
|
@ -148,11 +148,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="contents _gaps">
|
<div class="contents _gaps">
|
||||||
<div v-if="user.pinnedNotes.length > 0" class="_gaps">
|
<div v-if="user.pinnedNotes.length > 0 && !user.isBlocked" class="_gaps">
|
||||||
<MkNote v-for="note in user.pinnedNotes" :key="note.id" class="note _panel" :note="note" :pinned="true"/>
|
<MkNote v-for="note in user.pinnedNotes" :key="note.id" class="note _panel" :note="note" :pinned="true"/>
|
||||||
</div>
|
</div>
|
||||||
<MkInfo v-else-if="$i && $i.id === user.id">{{ i18n.ts.userPagePinTip }}</MkInfo>
|
<MkInfo v-else-if="$i && $i.id === user.id">{{ i18n.ts.userPagePinTip }}</MkInfo>
|
||||||
<template v-if="narrow">
|
<template v-if="narrow && !user.isBlocked">
|
||||||
<MkLazy>
|
<MkLazy>
|
||||||
<XFiles :key="user.id" :user="user"/>
|
<XFiles :key="user.id" :user="user"/>
|
||||||
</MkLazy>
|
</MkLazy>
|
||||||
@ -160,14 +160,19 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<XActivity :key="user.id" :user="user"/>
|
<XActivity :key="user.id" :user="user"/>
|
||||||
</MkLazy>
|
</MkLazy>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="!disableNotes">
|
<div v-if="!disableNotes && !user.isBlocked">
|
||||||
<MkLazy>
|
<MkLazy>
|
||||||
<XTimeline :user="user"/>
|
<XTimeline :user="user"/>
|
||||||
</MkLazy>
|
</MkLazy>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="user.isBlocked" class="_fullinfo">
|
||||||
|
<img :src="youBlockedImageUrl" class="_ghost"/>
|
||||||
|
<div style="font-size: 1.4rem; font-weight: bold; padding-bottom: 4px;">{{ i18n.ts.youBlocked }}</div>
|
||||||
|
<div style="opacity: 0.7">{{ i18n.tsx.youBlockedDescription({ user: `@${ user.username }` }) }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!narrow" class="sub _gaps" style="container-type: inline-size;">
|
</div>
|
||||||
|
<div v-if="!narrow && !user.isBlocked" class="sub _gaps" style="container-type: inline-size;">
|
||||||
<XFiles :key="user.id" :user="user"/>
|
<XFiles :key="user.id" :user="user"/>
|
||||||
<XActivity :key="user.id" :user="user"/>
|
<XActivity :key="user.id" :user="user"/>
|
||||||
</div>
|
</div>
|
||||||
@ -207,6 +212,7 @@ import { vibrate } from '@/scripts/vibrate.js';
|
|||||||
import detectLanguage from '@/scripts/detect-language.js';
|
import detectLanguage from '@/scripts/detect-language.js';
|
||||||
import { globalEvents } from '@/events.js';
|
import { globalEvents } from '@/events.js';
|
||||||
import { notesSearchAvailable, canSearchNonLocalNotes } from '@/scripts/check-permissions.js';
|
import { notesSearchAvailable, canSearchNonLocalNotes } from '@/scripts/check-permissions.js';
|
||||||
|
import { youBlockedImageUrl } from '@/instance.js';
|
||||||
|
|
||||||
function calcAge(birthdate: string): number {
|
function calcAge(birthdate: string): number {
|
||||||
const date = new Date(birthdate);
|
const date = new Date(birthdate);
|
||||||
|
@ -6,8 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
<template>
|
<template>
|
||||||
<MkStickyContainer>
|
<MkStickyContainer>
|
||||||
<template #header>
|
<template #header>
|
||||||
<CPPageHeader v-if="isMobile && defaultStore.state.mobileHeaderChange" v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/>
|
<CPPageHeader v-if="isMobile && defaultStore.state.mobileHeaderChange" v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :disableFollowButton="(user && user.isBlocked) == true"/>
|
||||||
<MkPageHeader v-else v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/>
|
<MkPageHeader v-else v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :disableFollowButton="(user && user.isBlocked) == true"/>
|
||||||
</template>
|
</template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="user">
|
<div v-if="user">
|
||||||
@ -102,7 +102,7 @@ const headerTabs = computed(() => user.value ? [{
|
|||||||
key: 'home',
|
key: 'home',
|
||||||
title: i18n.ts.overview,
|
title: i18n.ts.overview,
|
||||||
icon: 'ti ti-home',
|
icon: 'ti ti-home',
|
||||||
}, {
|
}, ...(!user.value.isBlocked ? [{
|
||||||
key: 'notes',
|
key: 'notes',
|
||||||
title: i18n.ts.notes,
|
title: i18n.ts.notes,
|
||||||
icon: 'ti ti-pencil',
|
icon: 'ti ti-pencil',
|
||||||
@ -138,7 +138,7 @@ const headerTabs = computed(() => user.value ? [{
|
|||||||
key: 'gallery',
|
key: 'gallery',
|
||||||
title: i18n.ts.gallery,
|
title: i18n.ts.gallery,
|
||||||
icon: 'ti ti-icons',
|
icon: 'ti ti-icons',
|
||||||
}, {
|
}] : []), {
|
||||||
key: 'raw',
|
key: 'raw',
|
||||||
title: 'Raw',
|
title: 'Raw',
|
||||||
icon: 'ti ti-code',
|
icon: 'ti ti-code',
|
||||||
|
Loading…
Reference in New Issue
Block a user