Skip to content

Commit

Permalink
feat(frontend): scheduled note delete
Browse files Browse the repository at this point in the history
  • Loading branch information
1673beta committed Mar 13, 2024
1 parent 1852a87 commit 2fe4215
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 0 deletions.
4 changes: 4 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4595,6 +4595,10 @@ export interface Locale extends ILocale {
* 非センシティブのみ (リモートはいいねのみ)
*/
"nonSensitiveOnlyForLocalLikeOnlyForRemote": string;
/**
* 時限消滅
*/
"scheduledNoteDelete"
/**
* 自分に割り当てられたロール
*/
Expand Down
25 changes: 25 additions & 0 deletions packages/frontend/src/components/MkPostForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<span v-else><i class="ti ti-icons"></i></span>
</button>
<button v-tooltip="i18n.ts._mfm.cheatSheet" class="_button" :class="$style.headerRightItem" @click="openMfmCheatSheet"><i class="ti ti-help-circle"></i></button>
<button v-tooltip="i18n.ts.scheduledNoteDelete" class="_button" :class="$style.headerRightItem" @click="openScheduledNoteDelete"><i class="ti ti-clock-hour-9"></i></button>
<button v-click-anime class="_button" :class="$style.submit" :disabled="!canPost" data-cy-open-post-form-submit @click="post">
<div :class="$style.submitInner">
<template v-if="posted"></template>
Expand Down Expand Up @@ -109,6 +110,7 @@ import * as mfm from 'cherrypick-mfm-js';
import * as Misskey from 'cherrypick-js';
import insertTextAtCursor from 'insert-text-at-cursor';
import { toASCII } from 'punycode/';
import MkScheduledNoteDeleteEditor, { type ScheduledDeleteDateModelValue } from '@/components/MkScheduledNoteDeleteEditor.vue';
import MkNoteSimple from '@/components/MkNoteSimple.vue';
import MkNotePreview from '@/components/MkNotePreview.vue';
import XPostFormAttaches from '@/components/MkPostFormAttaches.vue';
Expand Down Expand Up @@ -194,6 +196,7 @@ const event = ref<{
metadata: Record<string, string>;
} | null>(null);
const useCw = ref<boolean>(!!props.initialCw);
const scheduledDelete = ref<ScheduledDeleteDateModelValue | null>(null);
const showPreview = ref(defaultStore.state.showPreview);
const showProfilePreview = ref(defaultStore.state.showProfilePreview);
watch(showPreview, () => defaultStore.set('showPreview', showPreview.value));
Expand Down Expand Up @@ -727,6 +730,7 @@ function saveDraft() {
files: files.value,
poll: poll.value,
event: event.value,
scheduledDelete: scheduledDelete.value,
},
};
Expand Down Expand Up @@ -802,6 +806,7 @@ async function post(ev?: MouseEvent) {
channelId: props.channel ? props.channel.id : undefined,
poll: poll.value,
event: event.value,
scheduledDelete: scheduledDelete.value,
cw: useCw.value ? cw.value ?? '' : null,
localOnly: localOnly.value,
visibility: visibility.value,
Expand Down Expand Up @@ -976,6 +981,17 @@ async function openMfmCheatSheet() {
os.popup(defineAsyncComponent(() => import('@/components/MkMfmCheatSheetDialog.vue')), {}, {}, 'closed');
}
async function openScheduledNoteDelete() {
if (scheduledDelete.value) {
scheduledDelete.value = null;
} else {
scheduledDelete.value = {
deleteAt: null,
deleteAfter: null,
};
}
}
const postAccount = ref<Misskey.entities.UserDetailed | null>(null);
function openAccountMenu(ev: MouseEvent) {
Expand Down Expand Up @@ -1041,6 +1057,9 @@ onMounted(() => {
if (draft.data.event) {
event.value = draft.data.event;
}
if (draft.data.scheduledDelete) {
scheduledDelete.value = draft.data.scheduledDelete;
}
}
}
Expand All @@ -1067,6 +1086,12 @@ onMounted(() => {
metadata: init.event.metadata,
};
}
if (init.scheduledDelete) {
scheduledDelete.value = {
deleteAt: init.deleteAt ? (new Date(init.deleteAt)).getTime() : null,
deleteAfter: null,
};
}
visibility.value = init.visibility;
localOnly.value = init.localOnly ?? false;
quoteId.value = init.renote ? init.renote.id : null;
Expand Down
169 changes: 169 additions & 0 deletions packages/frontend/src/components/MkScheduledNoteDeleteEditor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<!--
SPDX-FIleCopyrightText: syuilo and misskey-project, noridev and cherrypick-project, esurio
SPDX-License-Identifer: AGPL-3.0-only
-->

<template>
<div class="zmdxowus">
<span>{{ i18n.ts.scheduledDelete }}</span>
<section>
<div>
<MkSelect v-model="expiration" small>
<template #label>{{ i18n.ts._poll.expiration }}</template>
<option value="at">{{ i18n.ts._poll.at }}</option>
<option value="after">{{ i18n.ts._poll.after }}</option>
</MkSelect>
<section v-if="expiration === 'at'">
<MkInput v-model="atDate" small type="date" class="input">
<template #label>{{ i18n.ts._poll.deadlineDate }}</template>
</MkInput>
<MkInput v-model="atTime" small type="time" class="input">
<template #label>{{ i18n.ts._poll.deadlineTime }}</template>
</MkInput>
</section>
<section v-if="expiration === 'after'">
<MkInput v-model="after" small type="number" class="input">
<template #label>{{ i18n.ts._poll.duration }}</template>
</MkInput>
<MkSelect v-model="unit" small>
<option value="second">{{ i18n.ts._time.second }}</option>
<option value="minute">{{ i18n.ts._time.minute }}</option>
<option value="hour">{{ i18n.ts._time.hour }}</option>
<option value="day">{{ i18n.ts._time.day }}</option>
</MkSelect>
</section>
</div>
</section>
</div>
</template>

<script lang="ts" setup>
import { ref, watch } from 'vue';
import MkSelect from './MkSelect.vue';
import MkInput from './MkInput.vue';
import { i18n } from '@/i18n.js';
import { formatDateTimeString } from '@/scripts/format-time-string';
import { addTime } from '@/scripts/time';
export type ScheduledDeleteDateModelValue = {
deleteAt: number | null;
deleteAfter: number | null;
};
const props = defineProps<{
modelValue: ScheduledDeleteDateModelValue;
}>();
const emit = defineEmits<{
(ev: 'update:modelValue', v: ScheduledDeleteDateModelValue): void;
}>();
const expiration = ref('at');
const atDate = ref(formatDateTimeString(addTime(new Date(), 1, 'day'), 'yyyy-MM-dd'));
const atTime = ref('00:00');
const after = ref(0);
const unit = ref('second');
if (props.modelValue.deleteAt) {
expiration.value = 'at';
const deleteAt = new Date(props.modelValue.deleteAt);
atDate.value = formatDateTimeString(deleteAt, 'yyyy-MM-dd');
atTime.value = formatDateTimeString(deleteAt, 'HH:mm');
} else if (typeof props.modelValue.deleteAfter === 'number') {
expiration.value = 'after';
after.value = props.modelValue.deleteAfter / 1000;
}
function get(): ScheduledDeleteDateModelValue {
const calcAt = () => {
return new Date(`${atDate.value}${atTime.value}`).getTime();
};
const calcAfter = () => {
let base = parseInt(after.value.toString());
switch (unit.value) {
// @ts-except-error fallthrough
case 'day': base *= 24;
// @ts-expect-error fallthrough
case 'hour': base *= 60;
// @ts-expect-error fallthrough
case 'minute': base *= 60;
// eslint-disable-next-line no-fallthrough
case 'second': return base *= 1000;
default: return null;
}
};
return {
deleteAt: expiration.value === 'at' ? calcAt() : null,
deleteAfter: expiration.value === 'after' ? calcAfter() : null,
};
}
watch([expiration, atDate, atTime, after, unit], () => emit('update:modelValue', get()), {
deep: true,
});
</script>

<style lang="scss" scoped>
.zmdxowus {
padding: 8px 16px;
>span {
opacity: 0.7;
}
>ul{
display: block;
margin: 0;
padding: 0;
list-style: none;
>li {
display: flex;
margin: 8px 0;
padding: 0;
width: 100%;
>.input {
flex: 1;
}
>button {
width: 32px;
padding: 4px;
}
}
}
>section {
margin: 16px 0 0 0;
>div {
margin: 0 8px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 12px;
&:last-child {
flex: 1 0 auto;
>div {
flex-grow: 1;
}
>section {
flex-grow: 9999;
align-items: end;
display: flex;
gap: 4px;
>.input {
flex: 1 1 auto;
}
}
}
}
}
}
</style>

0 comments on commit 2fe4215

Please sign in to comment.