enhance(frontend): 노트를 편집한 시간이 개별적으로 표시됨
This commit is contained in:
commit
526565db72
|
@ -32,6 +32,7 @@ Misskey의 전체 변경 사항을 확인하려면, [CHANGELOG.md#2023xx](CHANGE
|
||||||
- Feat: 노트 편집 시 토스트 알림을 표시하고 사운드를 재생
|
- Feat: 노트 편집 시 토스트 알림을 표시하고 사운드를 재생
|
||||||
- Enhance: 노트를 편집할 때 편집 중인 노트임을 강조함
|
- Enhance: 노트를 편집할 때 편집 중인 노트임을 강조함
|
||||||
- Enhance: 타임라인에서 새 노트가 20개 이상이면 '20+'로 표기
|
- Enhance: 타임라인에서 새 노트가 20개 이상이면 '20+'로 표기
|
||||||
|
- Enhance: 노트를 편집한 시간이 개별적으로 표시됨
|
||||||
- Fix: '새 노트 알림'을 '노트 수 표시'로 설정했을 때 한국어 이외의 언어에서 내용이 표시되지 않음
|
- Fix: '새 노트 알림'을 '노트 수 표시'로 설정했을 때 한국어 이외의 언어에서 내용이 표시되지 않음
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and other misskey, cherrypick contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class NoteUpdateAtHistory1696318192428 {
|
||||||
|
name = 'NoteUpdateAtHistory1696318192428'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "note" ADD "updatedAtHistory" TIMESTAMP WITH TIME ZONE array`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "note" DROP "updatedAtHistory"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -339,6 +339,7 @@ export class NoteEntityService implements OnModuleInit {
|
||||||
id: note.id,
|
id: note.id,
|
||||||
createdAt: this.idService.parse(note.id).date.toISOString(),
|
createdAt: this.idService.parse(note.id).date.toISOString(),
|
||||||
updatedAt: note.updatedAt ? note.updatedAt.toISOString() : undefined,
|
updatedAt: note.updatedAt ? note.updatedAt.toISOString() : undefined,
|
||||||
|
updatedAtHistory: note.updatedAtHistory ? note.updatedAtHistory.map(x => x.toISOString()) : undefined,
|
||||||
noteEditHistory: note.noteEditHistory.length ? note.noteEditHistory : undefined,
|
noteEditHistory: note.noteEditHistory.length ? note.noteEditHistory : undefined,
|
||||||
userId: note.userId,
|
userId: note.userId,
|
||||||
user: this.userEntityService.pack(note.user ?? note.userId, me, {
|
user: this.userEntityService.pack(note.user ?? note.userId, me, {
|
||||||
|
|
|
@ -23,6 +23,12 @@ export class MiNote {
|
||||||
})
|
})
|
||||||
public updatedAt: Date | null;
|
public updatedAt: Date | null;
|
||||||
|
|
||||||
|
@Column('timestamp with time zone', {
|
||||||
|
array: true,
|
||||||
|
default: null,
|
||||||
|
})
|
||||||
|
public updatedAtHistory: Date[] | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column('varchar', {
|
||||||
length: 3000,
|
length: 3000,
|
||||||
array: true,
|
array: true,
|
||||||
|
|
|
@ -22,6 +22,15 @@ export const packedNoteSchema = {
|
||||||
optional: true, nullable: true,
|
optional: true, nullable: true,
|
||||||
format: 'date-time',
|
format: 'date-time',
|
||||||
},
|
},
|
||||||
|
updatedAtHistory: {
|
||||||
|
type: 'array',
|
||||||
|
optional: true, nullable: true,
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
format: 'date-time',
|
||||||
|
},
|
||||||
|
},
|
||||||
noteEditHistory: {
|
noteEditHistory: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
optional: true, nullable: false,
|
optional: true, nullable: false,
|
||||||
|
|
|
@ -74,10 +74,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
throw new ApiError(meta.errors.noSuchNote);
|
throw new ApiError(meta.errors.noSuchNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updatedAtHistory = note.updatedAtHistory ? note.updatedAtHistory : [];
|
||||||
await this.notesRepository.update({ id: note.id }, {
|
await this.notesRepository.update({ id: note.id }, {
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
cw: ps.cw,
|
cw: ps.cw,
|
||||||
text: ps.text,
|
text: ps.text,
|
||||||
|
updatedAtHistory: [...updatedAtHistory, new Date()],
|
||||||
noteEditHistory: [...note.noteEditHistory, note.text!],
|
noteEditHistory: [...note.noteEditHistory, note.text!],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,7 @@ export type Note = {
|
||||||
id: ID;
|
id: ID;
|
||||||
createdAt: DateString;
|
createdAt: DateString;
|
||||||
updatedAt?: DateString | null;
|
updatedAt?: DateString | null;
|
||||||
|
updatedAtHistory: DateString[] | null;
|
||||||
noteEditHistory: string[];
|
noteEditHistory: string[];
|
||||||
text: string | null;
|
text: string | null;
|
||||||
cw: string | null;
|
cw: string | null;
|
||||||
|
|
|
@ -221,6 +221,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<div :class="$style.historyMain">
|
<div :class="$style.historyMain">
|
||||||
<div :class="$style.historyHeader">
|
<div :class="$style.historyHeader">
|
||||||
<MkUserName :user="appearNote.user" :nowrap="true"/>
|
<MkUserName :user="appearNote.user" :nowrap="true"/>
|
||||||
|
<MkTime :class="$style.updatedAt" :time="appearNote.updatedAtHistory![index]"/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -236,6 +237,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="appearNote.noteEditHistory == null" class="_fullinfo">
|
||||||
|
<img :src="infoImageUrl" class="_ghost"/>
|
||||||
|
<div>{{ i18n.ts.nothing }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -289,7 +294,7 @@ import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||||
import MkReactionIcon from '@/components/MkReactionIcon.vue';
|
import MkReactionIcon from '@/components/MkReactionIcon.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import { miLocalStorage } from '@/local-storage.js';
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
import { instance } from '@/instance.js';
|
import { infoImageUrl, instance } from '@/instance.js';
|
||||||
import MkPostForm from '@/components/MkPostFormSimple.vue';
|
import MkPostForm from '@/components/MkPostFormSimple.vue';
|
||||||
import { deviceKind } from '@/scripts/device-kind.js';
|
import { deviceKind } from '@/scripts/device-kind.js';
|
||||||
|
|
||||||
|
@ -1082,11 +1087,12 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.historyHeader {
|
.historyHeader {
|
||||||
|
display: flex;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: clip;
|
overflow: clip;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
.avatar {
|
.avatar {
|
||||||
flex-shrink: 0 !important;
|
flex-shrink: 0 !important;
|
||||||
|
@ -1098,6 +1104,12 @@ onMounted(() => {
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.updatedAt {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
.muted {
|
.muted {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
Loading…
Reference in a new issue