Skip to content

Commit

Permalink
release: v2024.5.0-kakurega.1.38.0 (#151)
Browse files Browse the repository at this point in the history
  • Loading branch information
hideki0403 authored Jun 29, 2024
2 parents 84a6a4b + 4221161 commit 93861ee
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 82 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG_KAKUREGA.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
## 1.38.0
Release: 2024/06/29
Base: 2024.5.0

### 新機能/機能改善

#### ノートの自己消滅の初期値を設定できるように
投稿フォームで「ノートの自己消滅」を有効にした際に設定される初期値を設定できます。
設定 → 全般 → 投稿フォーム から設定できます。
![image](https://media.kakurega.app/static/misskey/95d273de-8471-4d7d-997e-cd4307007e68.png)

#### ノートの自己消滅をデフォルトで有効にできるように
有効にすると、投稿フォームを開いた際にデフォルトで「ノートの自己消滅」が有効になります。
設定 → 全般 → 投稿フォーム から設定できます。

#### 投稿フォームのノート自己消滅のUIを改善
ノートの自己消滅の設定欄を折り畳めるようになりました。
ノートの自己消滅がデフォルトで有効になっている場合は、初期状態で折りたたまれた状態になります。
![image](https://media.kakurega.app/static/misskey/8f77388f-1c73-4e5d-9f7d-9d6d0e6359c1.png)

#### ミュート期限を追加
これまでの項目に加え、「6時間」「12時間」が追加されました。

## 1.37.0
Release: 2024/05/22
Base: 2024.3.1
Expand Down
8 changes: 8 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5364,6 +5364,14 @@ export interface Locale extends ILocale {
* デフォルトでノートが自己消滅するように
*/
"defaultScheduledNoteDelete": string;
/**
* ノートの自己消滅の初期値
*/
"defaultScheduledNoteDeleteTime": string;
/**
* ノートの自己消滅が有効になっています
*/
"scheduledNoteDeleteEnabled": string;
/**
* 使用しない場合は空欄にしてください
*/
Expand Down
2 changes: 2 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,8 @@ draftSavingBehavior: "下書きの保存に関する動作"
saveAsDraft: "下書きとして保存"
draftOverwriteConfirm: "下書きを適用すると現在入力されている内容はリセットされます。よろしいですか?"
defaultScheduledNoteDelete: "デフォルトでノートが自己消滅するように"
defaultScheduledNoteDeleteTime: "ノートの自己消滅の初期値"
scheduledNoteDeleteEnabled: "ノートの自己消滅が有効になっています"
notUsePleaseLeaveBlank: "使用しない場合は空欄にしてください"
useTotp: "ワンタイムパスワードを使う"
useBackupCode: "バックアップコードを使う"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "misskey",
"version": "2024.5.0-kakurega.1.37.0",
"version": "2024.5.0-kakurega.1.38.0",
"codename": "nasubi",
"repository": {
"type": "git",
Expand Down
79 changes: 69 additions & 10 deletions packages/frontend/src/components/MkDeleteScheduleEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ SPDX-License-Identifier: AGPL-3.0-only
-->

<template>
<div :class="$style.root">
<span v-if="!afterOnly">{{ i18n.ts.scheduledNoteDelete }}</span>
<div :class="[$style.root, { [$style.padding]: !afterOnly }]">
<div v-if="!afterOnly" :class="[$style.label, { [$style.withAccent]: !showDetail }]" @click="showDetail = !showDetail"><i class="ti" :class="showDetail ? 'ti-chevron-up' : 'ti-chevron-down'"></i> {{ summaryText }}</div>
<MkInfo v-if="!isValid" warn>{{ i18n.ts.cannotScheduleLaterThanOneYear }}</MkInfo>
<section>
<section v-if="afterOnly || showDetail">
<div>
<MkSelect v-if="!afterOnly" v-model="expiration" small>
<template #label>{{ i18n.ts._poll.expiration }}</template>
Expand Down Expand Up @@ -39,12 +39,13 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>

<script lang="ts" setup>
import { ref, watch } from 'vue';
import { computed, ref, watch } from 'vue';
import MkInput from './MkInput.vue';
import MkSelect from './MkSelect.vue';
import MkInfo from './MkInfo.vue';
import { formatDateTimeString } from '@/scripts/format-time-string.js';
import { addTime } from '@/scripts/time.js';
import { defaultStore } from '@/store.js';
import { i18n } from '@/i18n.js';
export type DeleteScheduleEditorModelValue = {
Expand All @@ -61,21 +62,62 @@ const emit = defineEmits<{
(ev: 'update:modelValue', v: DeleteScheduleEditorModelValue): void;
}>();
const expiration = ref<'at' | 'after'>(props.afterOnly ? 'after' : 'at');
const expiration = ref<'at' | 'after'>('after');
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');
const unit = ref<'second' | 'minute' | 'hour' | 'day'>('second');
const isValid = ref(true);
const showDetail = ref(!defaultStore.state.defaultScheduledNoteDelete);
const summaryText = computed(() => {
if (showDetail.value) {
return i18n.ts.scheduledNoteDelete;
}
if (expiration.value === 'at') {
return `${i18n.ts.scheduledNoteDeleteEnabled} (${formatDateTimeString(new Date(calcAt()), 'yyyy/MM/dd HH:mm')})`;
} else {
const time = unit.value === 'second' ? i18n.tsx._timeIn.seconds({ n: (after.value).toString() })
: unit.value === 'minute' ? i18n.tsx._timeIn.minutes({ n: (after.value).toString() })
: unit.value === 'hour' ? i18n.tsx._timeIn.hours({ n: (after.value).toString() })
: i18n.tsx._timeIn.days({ n: (after.value).toString() });
return `${i18n.ts.scheduledNoteDeleteEnabled} (${time})`;
}
});
const beautifyAfter = (base: number) => {
let time = base;
if (time % 60 === 0) {
unit.value = 'minute';
time /= 60;
}
if (time % 60 === 0) {
unit.value = 'hour';
time /= 60;
}
if (time % 24 === 0) {
unit.value = 'day';
time /= 24;
}
after.value = time;
};
beautifyAfter(defaultStore.state.defaultScheduledNoteDeleteTime / 1000);
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;
beautifyAfter(props.modelValue.deleteAfter / 1000);
}
const calcAt = () => {
Expand Down Expand Up @@ -127,8 +169,8 @@ watch([expiration, atDate, atTime, after, unit, isValid], () => {
.root {
display: flex;
flex-direction: column;
gap: 16px;
padding: 8px 16px;
gap: 8px;
padding: 8px 0px;
>span {
opacity: 0.7;
Expand Down Expand Up @@ -159,7 +201,6 @@ watch([expiration, atDate, atTime, after, unit, isValid], () => {
>section {
>div {
margin: 0 8px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
Expand Down Expand Up @@ -187,4 +228,22 @@ watch([expiration, atDate, atTime, after, unit, isValid], () => {
}
}
}
.padding {
padding: 8px 24px;
}
.label {
font-size: 0.85em;
padding: 0 0 8px 0;
user-select: none;
}
.withAccent {
color: var(--accent);
}
.chevronOpening {
transform: rotateX(180deg);
}
</style>
8 changes: 7 additions & 1 deletion packages/frontend/src/pages/settings/post-form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,17 @@
{{ i18n.ts.disableNoteDrafting }}
<span class="_beta">{{ i18n.ts.originalFeature }}</span>
</MkSwitch>
<div>
<div :class="$style.label">
{{ i18n.ts.defaultScheduledNoteDeleteTime }}
<span class="_beta">{{ i18n.ts.originalFeature }}</span>
</div>
<MkDeleteScheduleEditor v-model="scheduledNoteDelete" :afterOnly="true"/>
</div>
<MkSwitch v-model="defaultScheduledNoteDelete">
{{ i18n.ts.defaultScheduledNoteDelete }}
<span class="_beta">{{ i18n.ts.originalFeature }}</span>
</MkSwitch>
<MkDeleteScheduleEditor v-if="defaultScheduledNoteDelete" v-model="scheduledNoteDelete" :afterOnly="true"/>
</div>
</template>

Expand Down
128 changes: 58 additions & 70 deletions packages/frontend/src/scripts/get-user-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,58 @@ import { IRouter } from '@/nirax.js';
import { antennasCache, rolesCache, userListsCache } from '@/cache.js';
import { mainRouter } from '@/router/main.js';

type PeriodType = {
key: string;
time: number | null;
text: string;
};

const period: PeriodType[] = [{
key: 'indefinitely',
time: null,
text: i18n.ts.indefinitely,
}, {
key: 'tenMinutes',
time: 1000 * 60 * 10,
text: i18n.tsx._timeIn.minutes({ n: (10).toString() }),
}, {
key: 'oneHour',
time: 1000 * 60 * 60,
text: i18n.tsx._timeIn.hours({ n: (1).toString() }),
}, {
key: 'sixHours',
time: 1000 * 60 * 60 * 6,
text: i18n.tsx._timeIn.hours({ n: (6).toString() }),
}, {
key: 'twelveHours',
time: 1000 * 60 * 60 * 12,
text: i18n.tsx._timeIn.hours({ n: (12).toString() }),
}, {
key: 'oneDay',
time: 1000 * 60 * 60 * 24,
text: i18n.tsx._timeIn.days({ n: (1).toString() }),
}, {
key: 'oneWeek',
time: 1000 * 60 * 60 * 24 * 7,
text: i18n.tsx._timeIn.weeks({ n: (1).toString() }),
}];

async function getPeriod(title: string, text?: string) {
const { canceled, result } = await os.select({
title,
text,
items: period.map(x => ({
value: x.key,
text: x.text,
})),
default: 'indefinitely',
});
if (canceled) return false;

const periodTime = period.find(x => x.key === result)?.time;
return periodTime == null ? null : Date.now() + periodTime;
}

export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter = mainRouter) {
const meId = $i ? $i.id : null;

Expand All @@ -30,29 +82,8 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
user.isMuted = false;
});
} else {
const { canceled, result: period } = await os.select({
title: i18n.ts.mutePeriod,
items: [{
value: 'indefinitely', text: i18n.ts.indefinitely,
}, {
value: 'tenMinutes', text: i18n.ts.tenMinutes,
}, {
value: 'oneHour', text: i18n.ts.oneHour,
}, {
value: 'oneDay', text: i18n.ts.oneDay,
}, {
value: 'oneWeek', text: i18n.ts.oneWeek,
}],
default: 'indefinitely',
});
if (canceled) return;

const expiresAt = period === 'indefinitely' ? null
: period === 'tenMinutes' ? Date.now() + (1000 * 60 * 10)
: period === 'oneHour' ? Date.now() + (1000 * 60 * 60)
: period === 'oneDay' ? Date.now() + (1000 * 60 * 60 * 24)
: period === 'oneWeek' ? Date.now() + (1000 * 60 * 60 * 24 * 7)
: null;
const expiresAt = await getPeriod(i18n.ts.mutePeriod);
if (expiresAt === false) return;

os.apiWithDialog('mute/create', {
userId: user.id,
Expand Down Expand Up @@ -103,30 +134,8 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
if (user.isMuted) return toggleBlock();
if (user.isBlocking) return toggleMute();

const { canceled, result: period } = await os.select({
title: i18n.ts.muteAndBlockConfirm,
text: i18n.ts.mutePeriod,
items: [{
value: 'indefinitely', text: i18n.ts.indefinitely,
}, {
value: 'tenMinutes', text: i18n.ts.tenMinutes,
}, {
value: 'oneHour', text: i18n.ts.oneHour,
}, {
value: 'oneDay', text: i18n.ts.oneDay,
}, {
value: 'oneWeek', text: i18n.ts.oneWeek,
}],
default: 'indefinitely',
});
if (canceled) return;

const expiresAt = period === 'indefinitely' ? null
: period === 'tenMinutes' ? Date.now() + (1000 * 60 * 10)
: period === 'oneHour' ? Date.now() + (1000 * 60 * 60)
: period === 'oneDay' ? Date.now() + (1000 * 60 * 60 * 24)
: period === 'oneWeek' ? Date.now() + (1000 * 60 * 60 * 24 * 7)
: null;
const expiresAt = await getPeriod(i18n.ts.muteAndBlockConfirm, i18n.ts.mutePeriod);
if (expiresAt === false) return;

await os.apiWithDialog('mute/create', {
userId: user.id,
Expand Down Expand Up @@ -314,29 +323,8 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
return roles.filter(r => r.target === 'manual').map(r => ({
text: r.name,
action: async () => {
const { canceled, result: period } = await os.select({
title: i18n.ts.period + ': ' + r.name,
items: [{
value: 'indefinitely', text: i18n.ts.indefinitely,
}, {
value: 'oneHour', text: i18n.ts.oneHour,
}, {
value: 'oneDay', text: i18n.ts.oneDay,
}, {
value: 'oneWeek', text: i18n.ts.oneWeek,
}, {
value: 'oneMonth', text: i18n.ts.oneMonth,
}],
default: 'indefinitely',
});
if (canceled) return;

const expiresAt = period === 'indefinitely' ? null
: period === 'oneHour' ? Date.now() + (1000 * 60 * 60)
: period === 'oneDay' ? Date.now() + (1000 * 60 * 60 * 24)
: period === 'oneWeek' ? Date.now() + (1000 * 60 * 60 * 24 * 7)
: period === 'oneMonth' ? Date.now() + (1000 * 60 * 60 * 24 * 30)
: null;
const expiresAt = await getPeriod(i18n.ts.period + ': ' + r.name);
if (expiresAt === false) return;

os.apiWithDialog('admin/roles/assign', { roleId: r.id, userId: user.id, expiresAt });
},
Expand Down

0 comments on commit 93861ee

Please sign in to comment.