Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(frontend):同じノートを連続してリノートしようとしたときに警告する設定を追加 #409

Merged
merged 4 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG_YOJO.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
### Client
- Fix: 非ログインでリバーシの戦績が見れない不具合の修正 [#404](https://github.com/yojo-art/cherrypick/pull/404)
- Fix: 翻訳に失敗したとき読み込み中のままになるのを修正
- Enhance: ユーザー概要の...からサーバー情報にリンクを追加 [#406](https://github.com/yojo-art/cherrypick/pull/406)
- Fix: ノート詳細の本文表示優先度を変更
- Feat: 同じノートを連続してリノートしようとしたときに警告する設定を追加(設定→全般)
- Enhance: ユーザー概要の...からサーバー情報にリンクを追加 [#406](https://github.com/yojo-art/cherrypick/pull/406)

### Server
-
Expand Down
18 changes: 18 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ export interface Locale extends ILocale {
* この作業は最初一度だけ行われます。
*/
"cherrypickMigratedCacheClear": string;
/**
* 同じノートを連続してリノートしようとしたときに警告する
*/
"showMultipleRenoteWarning": string;
/**
* リノートの公開範囲オプションを表示
*/
Expand Down Expand Up @@ -11932,6 +11936,20 @@ export interface Locale extends ILocale {
*/
"notificationDeleteTitle": string;
};
"_renoteConfirm": {
/**
* このノートはリノートしたばかりです
*/
"title": string;
/**
* リノートしますか?
*/
"caption": string;
/**
* リノートする
*/
"confirm": string;
};
}
declare const locales: {
[lang: string]: Locale;
Expand Down
6 changes: 6 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ welcome: "ようこそ!"
cherrypickMigrated: "CherryPickへの移行が完了しました!"
cherrypickMigratedCacheClearTitle: "キャッシュクリアのご案内"
cherrypickMigratedCacheClear: "このサーバーは<b>Misskey</b>または<b>CherryPick v4.3.0以前</b>のバージョンから移行されました。\nバージョン管理方式が異なり、残っているキャッシュが問題を引き起こす可能性があるため、移行後、最初の接続時にキャッシュを削除する作業を行う必要があります。\n\nこの作業は最初一度だけ行われます。"
showMultipleRenoteWarning: "同じノートを連続してリノートしようとしたときに警告する"
showRenoteVisibilitySelector: "リノートの公開範囲オプションを表示"
cannotBeUsedFunc: "この機能は現在使用できません。"
scale: "大きさ"
Expand Down Expand Up @@ -3188,3 +3189,8 @@ _dice:
_deleteConfirm:
delete: "削除する"
notificationDeleteTitle: "通知を削除しますか?"

_renoteConfirm:
title: "このノートはリノートしたばかりです"
caption: "リノートしますか?"
confirm: 'リノートする'
2 changes: 2 additions & 0 deletions packages/frontend/src/pages/settings/general.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSwitch v-model="infoButtonForNoteActionsEnabled">{{ i18n.ts.infoButtonForNoteActions }}<template #caption>{{ i18n.ts.infoButtonForNoteActionsDescription }}</template> <span class="_beta">CherryPick</span></MkSwitch>
<MkSwitch v-model="showReplyInNotification">{{ i18n.ts.showReplyInNotification }} <span class="_beta">CherryPick</span></MkSwitch>
<MkSwitch v-model="renoteQuoteButtonSeparation">{{ i18n.ts.renoteQuoteButtonSeparation }} <span class="_beta">CherryPick</span></MkSwitch>
<MkSwitch v-model="checkMultipleRenote">{{ i18n.ts.showMultipleRenoteWarning }} <span class="_beta">yojo-art</span></MkSwitch>
<MkSwitch v-model="renoteVisibilitySelection">{{ i18n.ts.showRenoteVisibilitySelector }} <span class="_beta">CherryPick</span></MkSwitch>
<MkSelect v-if="!renoteVisibilitySelection" v-model="forceRenoteVisibilitySelection">
<template #label>{{ i18n.ts.forceRenoteVisibilitySelector }}</template>
Expand Down Expand Up @@ -468,6 +469,7 @@ const showFixedPostFormInReplies = computed(defaultStore.makeGetterSetter('showF
const showingAnimatedImages = computed(defaultStore.makeGetterSetter('showingAnimatedImages'));
const allMediaNoteCollapse = computed(defaultStore.makeGetterSetter('allMediaNoteCollapse'));
const nsfwOpenBehavior = computed(defaultStore.makeGetterSetter('nsfwOpenBehavior'));
const checkMultipleRenote = computed(defaultStore.makeGetterSetter('checkMultipleRenote'));
const renoteVisibilitySelection = computed(defaultStore.makeGetterSetter('renoteVisibilitySelection'));
const forceRenoteVisibilitySelection = computed(defaultStore.makeGetterSetter('forceRenoteVisibilitySelection'));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ const defaultStoreSaveKeys: (keyof typeof defaultStore['state'])[] = [
'useEnterToSend',
'postFormVisibilityHotkey',
'showRenoteConfirmPopup',
'checkMultipleRenote',
'displayHeaderNavBarWhenScroll',
'infoButtonForNoteActionsEnabled',
'reactableRemoteReactionEnabled',
Expand Down
26 changes: 26 additions & 0 deletions packages/frontend/src/scripts/check-last-renote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project, yojo-art team
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
import { defaultStore } from '@/store.js';

export async function confirmRenote(renoteId:string) : Promise<boolean> {
if (defaultStore.state.checkMultipleRenote === false ) return false;
const lastRenoteId = localStorage.getItem('lastRenoteId');
if (lastRenoteId) {
if (lastRenoteId === renoteId) {
const { canceled } = await os.confirm({
type: 'warning',
title: i18n.ts._renoteConfirm.title,
caption: i18n.ts._renoteConfirm.caption,
okText: i18n.ts._renoteConfirm.confirm,
cancelText: i18n.ts.thisPostMayBeAnnoyingCancel,
});
return canceled;
}
}
localStorage.setItem('lastRenoteId', renoteId);
return false;
}
24 changes: 20 additions & 4 deletions packages/frontend/src/scripts/get-note-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { defineAsyncComponent, Ref, ShallowRef } from 'vue';
import * as Misskey from 'cherrypick-js';
import { claimAchievement } from './achievements.js';
import { confirmRenote } from './check-last-renote.js';
import { $i } from '@/account.js';
import { i18n } from '@/i18n.js';
import { instance } from '@/instance.js';
Expand Down Expand Up @@ -669,7 +670,7 @@ export function getRenoteMenu(props: {
normalRenoteItems.push({
text: i18n.ts.renote,
icon: 'ti ti-repeat',
action: () => {
action: async () => {
const el = props.renoteButton.value;
if (el) {
const rect = el.getBoundingClientRect();
Expand All @@ -689,6 +690,9 @@ export function getRenoteMenu(props: {
visibility = smallerVisibility(visibility, 'home');
}

const result = await confirmRenote(appearNote.id);
if (result) return;

if (!props.mock) {
misskeyApi('notes/create', {
localOnly,
Expand Down Expand Up @@ -726,7 +730,10 @@ export function getRenoteMenu(props: {
visibilityRenoteItems.push({
text: `${i18n.ts.renote} (${i18n.ts._visibility.public})`,
icon: 'ti ti-world',
action: () => {
action: async () => {
const result = await confirmRenote(appearNote.id);
if (result) return;

misskeyApi('notes/create', {
localOnly,
visibility: 'public',
Expand All @@ -743,7 +750,9 @@ export function getRenoteMenu(props: {
visibilityRenoteItems.push({
text: `${i18n.ts.renote} (${i18n.ts._visibility.home})`,
icon: 'ti ti-home',
action: () => {
action: async () => {
const result = await confirmRenote(appearNote.id);
if (result) return;
misskeyApi('notes/create', {
localOnly,
visibility: 'home',
Expand All @@ -759,7 +768,9 @@ export function getRenoteMenu(props: {
visibilityRenoteItems.push({
text: `${i18n.ts.renote} (${i18n.ts._visibility.followers})`,
icon: 'ti ti-lock',
action: () => {
action: async () => {
const result = await confirmRenote(appearNote.id);
if (result) return;
misskeyApi('notes/create', {
localOnly,
visibility: 'followers',
Expand Down Expand Up @@ -836,6 +847,9 @@ export async function getRenoteOnly(props: {
}

if (!props.mock && defaultStore.state.renoteVisibilitySelection) {
const result = await confirmRenote(appearNote.id);
if (result) return;

misskeyApi('notes/create', {
localOnly,
visibility,
Expand All @@ -850,6 +864,8 @@ export async function getRenoteOnly(props: {
!defaultStore.state.renoteVisibilitySelection &&
appearNote.visibility !== 'specified'
) {
const result = await confirmRenote(appearNote.id);
if (result) return;
if (defaultStore.state.forceRenoteVisibilitySelection !== 'none') {
if (appearNote.visibility === 'public' && defaultStore.state.forceRenoteVisibilitySelection === 'public') { // renote to public
misskeyApi('notes/create', {
Expand Down
4 changes: 4 additions & 0 deletions packages/frontend/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,10 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device',
default: 'none' as 'none' | 'public' | 'home' | 'followers',
},
checkMultipleRenote: {
where: 'device',
default: false,
},
showFixedPostFormInReplies: {
where: 'device',
default: true,
Expand Down
Loading