Merge pull request #10814 from misskey-dev/develop

Release: 13.12.1
This commit is contained in:
syuilo 2023-05-09 15:38:17 +09:00 committed by GitHub
commit 9ad57324db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 54 additions and 10 deletions

View File

@ -11,6 +11,18 @@
- -
--> -->
## 13.12.1
### Client
- プロフィール画面におけるモデレーションノートの表示を調整
- Fix: 一部ダイアログが表示されない問題を修正
- Fix: MkUserInfoのフォローボタンが変な位置にある問題を修正
### Server
- Fix: リモートサーバーの情報が更新できない問題を修正
- Fix: 13.11を経験しない状態で13.12にアップデートした場合ユーザープロフィール関連の画像が消失する問題を修正
## 13.12.0 ## 13.12.0
### NOTE ### NOTE

View File

@ -1040,6 +1040,7 @@ initialAccountSetting: "초기 설정"
youFollowing: "팔로잉" youFollowing: "팔로잉"
_initialAccountSetting: _initialAccountSetting:
accountCreated: "계정 생성이 완료되었습니다!" accountCreated: "계정 생성이 완료되었습니다!"
letsStartAccountSetup: "계정의 초기 설정을 진행합니다."
letsFillYourProfile: "우선 나의 프로필을 설정해 보아요." letsFillYourProfile: "우선 나의 프로필을 설정해 보아요."
profileSetting: "프로필 설정" profileSetting: "프로필 설정"
theseSettingsCanEditLater: "이 설정들은 나중에도 변경할 수 있습니다." theseSettingsCanEditLater: "이 설정들은 나중에도 변경할 수 있습니다."
@ -1049,6 +1050,7 @@ _initialAccountSetting:
initialAccountSettingCompleted: "초기 설정을 모두 마쳤습니다!" initialAccountSettingCompleted: "초기 설정을 모두 마쳤습니다!"
haveFun: "{name}와 함께 즐거운 시간 보내세요!" haveFun: "{name}와 함께 즐거운 시간 보내세요!"
ifYouNeedLearnMore: "{name}(Misskey)의 사용 방법에 대해 자세히 알아보려면 {link}를 참고해 주세요." ifYouNeedLearnMore: "{name}(Misskey)의 사용 방법에 대해 자세히 알아보려면 {link}를 참고해 주세요."
skipAreYouSure: "초기 설정을 넘기시겠습니까?"
_serverRules: _serverRules:
description: "회원 가입 이전에 간단하게 표시할 서버 규칙입니다. 이용 약관의 요약으로 구성하는 것을 추천합니다." description: "회원 가입 이전에 간단하게 표시할 서버 규칙입니다. 이용 약관의 요약으로 구성하는 것을 추천합니다."
_accountMigration: _accountMigration:
@ -1597,6 +1599,16 @@ _time:
minute: "분" minute: "분"
hour: "시간" hour: "시간"
day: "일" day: "일"
_timelineTutorial:
title: "Misskey의 사용 방법"
step1_1: "이것은 '타임라인'입니다. {name}에 게시된 '노트'가 시간 순서대로 표시됩니다."
step1_2: "타임라인은 몇 가지 종류로 나뉩니다. 그 중에 '홈 타임라인'은 내가 팔로우한 사람의 노트가 표시되며, '로컬 타임라인'에는 {name} 의 모든 노트가 표시됩니다."
step2_1: "그럼 시험삼아 노트를 작성해 봅시다. 화면에 있는 연필 버튼을 눌러 보세요."
step2_2: "첫 노트이니까 자기소개, 혹은 가볍게 \"안녕 {name}\"라고 올려 보는 건 어떨까요?"
step3_1: "노트 작성을 끝내셨나요?"
step3_2: "당신의 노트가 타임라인에 표시되어 있다면 성공입니다."
step4_1: "노트에는 '리액션'을 붙일 수 있습니다."
step4_2: "리액션을 붙이려면, 노트의 \"+\" 버튼을 클릭하고 원하는 이모지를 선택합니다."
_2fa: _2fa:
alreadyRegistered: "이미 설정이 완료되었습니다." alreadyRegistered: "이미 설정이 완료되었습니다."
registerTOTP: "인증 앱 설정 시작" registerTOTP: "인증 앱 설정 시작"

View File

@ -1,6 +1,6 @@
{ {
"name": "misskey", "name": "misskey",
"version": "13.12.0", "version": "13.12.1",
"codename": "nasubi", "codename": "nasubi",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -75,8 +75,6 @@ export class FederatedInstanceService {
return response.raw[0]; return response.raw[0];
}); });
const updated = result.raw[0]; this.federatedInstanceCache.set(result.host, result);
this.federatedInstanceCache.set(updated.host, updated);
} }
} }

View File

@ -306,6 +306,24 @@ export class UserEntityService implements OnModuleInit {
const user = typeof src === 'object' ? src : await this.usersRepository.findOneByOrFail({ id: src }); const user = typeof src === 'object' ? src : await this.usersRepository.findOneByOrFail({ id: src });
// migration
if (user.avatarId != null && user.avatarUrl === null) {
const avatar = await this.driveFilesRepository.findOneByOrFail({ id: user.avatarId });
user.avatarUrl = this.driveFileEntityService.getPublicUrl(avatar, 'avatar');
this.usersRepository.update(user.id, {
avatarUrl: user.avatarUrl,
avatarBlurhash: avatar.blurhash,
});
}
if (user.bannerId != null && user.bannerUrl === null) {
const banner = await this.driveFilesRepository.findOneByOrFail({ id: user.bannerId });
user.bannerUrl = this.driveFileEntityService.getPublicUrl(banner);
this.usersRepository.update(user.id, {
bannerUrl: user.bannerUrl,
bannerBlurhash: banner.blurhash,
});
}
const meId = me ? me.id : null; const meId = me ? me.id : null;
const isMe = meId === user.id; const isMe = meId === user.id;
const iAmModerator = me ? await this.roleService.isModerator(me as User) : false; const iAmModerator = me ? await this.roleService.isModerator(me as User) : false;

View File

@ -1,6 +1,6 @@
<template> <template>
<MkModal ref="modal" :prefer-type="'dialog'" @click="onBgClick" @closed="$emit('closed')"> <MkModal ref="modal" :prefer-type="'dialog'" @click="onBgClick" @closed="$emit('closed')">
<div ref="rootEl" class="ebkgoccj" :style="{ width: `${width}px`, height: height ? `${height}px` : null }" @keydown="onKeydown"> <div ref="rootEl" class="ebkgoccj" :style="{ width: `${width}px`, height: `min(${height}px, 100%)` }" @keydown="onKeydown">
<div ref="headerEl" class="header"> <div ref="headerEl" class="header">
<button v-if="withOkButton" class="_button" @click="$emit('close')"><i class="ti ti-x"></i></button> <button v-if="withOkButton" class="_button" @click="$emit('close')"><i class="ti ti-x"></i></button>
<span class="title"> <span class="title">
@ -24,12 +24,12 @@ const props = withDefaults(defineProps<{
withOkButton: boolean; withOkButton: boolean;
okButtonDisabled: boolean; okButtonDisabled: boolean;
width: number; width: number;
height: number | null; height: number;
}>(), { }>(), {
withOkButton: false, withOkButton: false,
okButtonDisabled: false, okButtonDisabled: false,
width: 400, width: 400,
height: null, height: 500,
}); });
const emit = defineEmits<{ const emit = defineEmits<{
@ -84,7 +84,6 @@ defineExpose({
<style lang="scss" scoped> <style lang="scss" scoped>
.ebkgoccj { .ebkgoccj {
margin: auto; margin: auto;
max-height: 100%;
overflow: hidden; overflow: hidden;
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -131,7 +131,7 @@ defineProps<{
} }
.follow { .follow {
position: absolute; position: absolute !important;
top: 8px; top: 8px;
right: 8px; right: 8px;
} }

View File

@ -49,9 +49,12 @@
</span> </span>
</div> </div>
<div v-if="iAmModerator" class="moderationNote"> <div v-if="iAmModerator" class="moderationNote">
<MkTextarea v-model="moderationNote" manual-save> <MkTextarea v-if="editModerationNote || (moderationNote != null && moderationNote !== '')" v-model="moderationNote" manual-save>
<template #label>Moderation note</template> <template #label>Moderation note</template>
</MkTextarea> </MkTextarea>
<div v-else>
<MkButton small @click="editModerationNote = true">Add moderation note</MkButton>
</div>
</div> </div>
<div v-if="isEditingMemo || memoDraft" class="memo" :class="{'no-memo': !memoDraft}"> <div v-if="isEditingMemo || memoDraft" class="memo" :class="{'no-memo': !memoDraft}">
<div class="heading" v-text="i18n.ts.memo"/> <div class="heading" v-text="i18n.ts.memo"/>
@ -142,6 +145,7 @@ import MkRemoteCaution from '@/components/MkRemoteCaution.vue';
import MkTextarea from '@/components/MkTextarea.vue'; import MkTextarea from '@/components/MkTextarea.vue';
import MkOmit from '@/components/MkOmit.vue'; import MkOmit from '@/components/MkOmit.vue';
import MkInfo from '@/components/MkInfo.vue'; import MkInfo from '@/components/MkInfo.vue';
import MkButton from '@/components/MkButton.vue';
import { getScrollPosition } from '@/scripts/scroll'; import { getScrollPosition } from '@/scripts/scroll';
import { getUserMenu } from '@/scripts/get-user-menu'; import { getUserMenu } from '@/scripts/get-user-menu';
import number from '@/filters/number'; import number from '@/filters/number';
@ -176,6 +180,7 @@ let memoTextareaEl = $ref<null | HTMLElement>(null);
let memoDraft = $ref(props.user.memo); let memoDraft = $ref(props.user.memo);
let isEditingMemo = $ref(false); let isEditingMemo = $ref(false);
let moderationNote = $ref(props.user.moderationNote); let moderationNote = $ref(props.user.moderationNote);
let editModerationNote = $ref(false);
watch($$(moderationNote), async () => { watch($$(moderationNote), async () => {
await os.api('admin/update-user-note', { userId: props.user.id, text: moderationNote }); await os.api('admin/update-user-note', { userId: props.user.id, text: moderationNote });