mirror of
https://github.com/kokonect-link/cherrypick
synced 2024-11-27 14:28:53 +09:00
enhance(frontend): 링크 또는 내용을 복사할 때 토스트 알림 표시
This commit is contained in:
parent
485de41483
commit
1f50926912
@ -63,6 +63,7 @@ Misskey의 전체 변경 사항을 확인하려면, [CHANGELOG.md#2023xx](CHANGE
|
||||
- Enhance: 액세스 토큰 개선
|
||||
- 토큰 생성 시, 토큰을 복사할 필요없이 '확인' 버튼을 누르면 자동으로 클립보드에 토큰이 복사됨
|
||||
- 토큰 삭제 시, 삭제 전 대화 상자가 표시됨
|
||||
- Enhance: 링크 또는 내용을 복사할 때 토스트 알림 표시
|
||||
- Fix: '모달 배경색 제거' 옵션이 이모지 피커에 반영되지 않음
|
||||
- Fix: 열람 주의로 설정된 노트의 리액션이 '더 보기'를 눌러야 표시됨
|
||||
- Fix: 채널 이름이 긴 경우 게시 양식 표시가 깨지는 문제 (misskey-dev/misskey#12524)
|
||||
|
@ -1,5 +1,8 @@
|
||||
---
|
||||
_lang_: "English"
|
||||
copiedLink: "링크를 복사했어요!"
|
||||
copiedContent: "내용을 복사했어요!"
|
||||
copied: "복사했어요!"
|
||||
welcome: "Welcome!"
|
||||
cherrypickMigrated: "The migration to CherryPick is complete!"
|
||||
cherrypickMigratedCacheClearTitle: "The cache must be cleared."
|
||||
|
3
locales/index.d.ts
vendored
3
locales/index.d.ts
vendored
@ -3,6 +3,9 @@
|
||||
// Do not edit this file directly.
|
||||
export interface Locale {
|
||||
"_lang_": string;
|
||||
"copiedLink": string;
|
||||
"copiedContent": string;
|
||||
"copied": string;
|
||||
"welcome": string;
|
||||
"cherrypickMigrated": string;
|
||||
"cherrypickMigratedCacheClearTitle": string;
|
||||
|
@ -1,5 +1,8 @@
|
||||
_lang_: "日本語"
|
||||
|
||||
copiedLink: "링크를 복사했어요!"
|
||||
copiedContent: "내용을 복사했어요!"
|
||||
copied: "복사했어요!"
|
||||
welcome: "ようこそ!"
|
||||
cherrypickMigrated: "CherryPickへの移行が完了しました!"
|
||||
cherrypickMigratedCacheClearTitle: "キャッシュクリアのご案内"
|
||||
|
@ -1,5 +1,8 @@
|
||||
---
|
||||
_lang_: "한국어"
|
||||
copiedLink: "링크를 복사했어요!"
|
||||
copiedContent: "내용을 복사했어요!"
|
||||
copied: "복사했어요!"
|
||||
welcome: "환영합니다!"
|
||||
cherrypickMigrated: "CherryPick으로 마이그레이션이 완료되었어요!"
|
||||
cherrypickMigratedCacheClearTitle: "캐시 삭제 안내"
|
||||
|
@ -277,6 +277,7 @@ function onContextmenu(ev: MouseEvent) {
|
||||
text: i18n.ts.copyFolderId,
|
||||
action: () => {
|
||||
copyToClipboard(props.folder.id);
|
||||
os.toast(i18n.ts.copied, 'copied');
|
||||
},
|
||||
}]);
|
||||
}
|
||||
|
@ -1,81 +0,0 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and noridev and other misskey, cherrypick contributors
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Transition
|
||||
:enterActiveClass="defaultStore.state.animation ? $style.transition_toast_enterActive : ''"
|
||||
:leaveActiveClass="defaultStore.state.animation ? $style.transition_toast_leaveActive : ''"
|
||||
:enterFromClass="defaultStore.state.animation ? $style.transition_toast_enterFrom : ''"
|
||||
:leaveToClass="defaultStore.state.animation ? $style.transition_toast_leaveTo : ''"
|
||||
appear @afterLeave="emit('closed')"
|
||||
>
|
||||
<div v-if="showing" class="_acrylic" :class="[$style.root, { [$style.reduceBlurEffect]: !defaultStore.state.useBlurEffect }]" :style="{ zIndex }">
|
||||
<div style="padding: 16px 24px;">
|
||||
<i :class="icon === 'posted' ? 'ti-check' : icon === 'reply' ? 'ti-arrow-back-up' : icon === 'renote' ? 'ti-repeat' : icon === 'quote' ? 'ti-quote' : icon === 'edited' ? 'ti ti-pencil' : 'ti-check'" class="ti"></i>
|
||||
{{ message }}
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import * as os from '@/os.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
|
||||
defineProps<{
|
||||
message: string;
|
||||
icon: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const zIndex = os.claimZIndex('high');
|
||||
const showing = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
window.setTimeout(() => {
|
||||
showing.value = false;
|
||||
}, 4000);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.transition_toast_enterActive,
|
||||
.transition_toast_leaveActive {
|
||||
transition: opacity 0.3s, transform 0.3s !important;
|
||||
}
|
||||
.transition_toast_enterFrom,
|
||||
.transition_toast_leaveTo {
|
||||
opacity: 0;
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
.root {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 50px;
|
||||
margin: 16px auto 0;
|
||||
min-width: 300px;
|
||||
max-width: calc(100% - 32px);
|
||||
width: min-content;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
||||
border-radius: 8px;
|
||||
overflow: clip;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
|
||||
@media (max-width: 500px) {
|
||||
&.reduceBlurEffect {
|
||||
background: var(--panel);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -43,6 +43,7 @@ import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.j
|
||||
import { openingWindowsCount } from '@/os.js';
|
||||
import { claimAchievement } from '@/scripts/achievements.js';
|
||||
import { getScrollContainer } from '@/scripts/scroll.js';
|
||||
import * as os from "@/os.js";
|
||||
|
||||
const props = defineProps<{
|
||||
initialPath: string;
|
||||
@ -120,6 +121,7 @@ const contextmenu = computed(() => ([{
|
||||
text: i18n.ts.copyLink,
|
||||
action: () => {
|
||||
copyToClipboard(url + router.getCurrentPath());
|
||||
os.toast(i18n.ts.copiedLink, 'copied');
|
||||
},
|
||||
}]));
|
||||
|
||||
|
@ -835,10 +835,10 @@ async function post(ev?: MouseEvent) {
|
||||
clear();
|
||||
}
|
||||
nextTick(() => {
|
||||
if (props.reply) os.noteToast(i18n.ts.replied, 'reply');
|
||||
else if (props.renote) os.noteToast(i18n.ts.quoted, 'quote');
|
||||
else if (props.updateMode) os.noteToast(i18n.ts.noteEdited, 'edited');
|
||||
else os.noteToast(i18n.ts.posted, 'posted');
|
||||
if (props.reply) os.toast(i18n.ts.replied, 'reply');
|
||||
else if (props.renote) os.toast(i18n.ts.quoted, 'quote');
|
||||
else if (props.updateMode) os.toast(i18n.ts.noteEdited, 'edited');
|
||||
else os.toast(i18n.ts.posted, 'posted');
|
||||
|
||||
deleteDraft();
|
||||
emit('posted');
|
||||
|
@ -828,10 +828,10 @@ async function post(ev?: MouseEvent) {
|
||||
clear();
|
||||
}
|
||||
nextTick(() => {
|
||||
if (props.reply) os.noteToast(i18n.ts.replied, 'reply');
|
||||
else if (props.renote) os.noteToast(i18n.ts.quoted, 'quote');
|
||||
else if (props.updateMode) os.noteToast(i18n.ts.noteEdited, 'edited');
|
||||
else os.noteToast(i18n.ts.posted, 'posted');
|
||||
if (props.reply) os.toast(i18n.ts.replied, 'reply');
|
||||
else if (props.renote) os.toast(i18n.ts.quoted, 'quote');
|
||||
else if (props.updateMode) os.toast(i18n.ts.noteEdited, 'edited');
|
||||
else os.toast(i18n.ts.posted, 'posted');
|
||||
|
||||
deleteDraft();
|
||||
emit('posted');
|
||||
|
@ -14,6 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
>
|
||||
<div v-if="showing" class="_acrylic" :class="[$style.root, { [$style.reduceBlurEffect]: !defaultStore.state.useBlurEffect }]" :style="{ zIndex }">
|
||||
<div style="padding: 16px 24px;">
|
||||
<i v-if="icon" :class="icon === 'posted' ? 'ti-check' : icon === 'reply' ? 'ti-arrow-back-up' : icon === 'renote' ? 'ti-repeat' : icon === 'quote' ? 'ti-quote' : icon === 'edited' ? 'ti ti-pencil' : icon === 'copied' ? 'ti-copy' : 'ti-check'" class="ti"></i>
|
||||
{{ message }}
|
||||
</div>
|
||||
</div>
|
||||
@ -28,6 +29,7 @@ import { defaultStore } from '@/store.js';
|
||||
|
||||
defineProps<{
|
||||
message: string;
|
||||
icon?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -68,6 +68,7 @@ function onContextmenu(ev) {
|
||||
text: i18n.ts.copyLink,
|
||||
action: () => {
|
||||
copyToClipboard(`${url}${props.to}`);
|
||||
os.toast(i18n.ts.copiedLink, 'copied');
|
||||
},
|
||||
}], ev);
|
||||
}
|
||||
|
@ -92,6 +92,7 @@ function onClick(ev: MouseEvent) {
|
||||
icon: 'ti ti-copy',
|
||||
action: () => {
|
||||
copyToClipboard(`:${props.name}:`);
|
||||
os.toast(i18n.ts.copied, 'copied');
|
||||
},
|
||||
}] : []), ...(props.host && $i && ($i.isAdmin || $i.policies.canManageCustomEmojis) ? [{
|
||||
text: i18n.ts.import,
|
||||
|
@ -16,7 +16,6 @@ import MkPostFormDialog from '@/components/MkPostFormDialog.vue';
|
||||
import MkWaitingDialog from '@/components/MkWaitingDialog.vue';
|
||||
import MkPageWindow from '@/components/MkPageWindow.vue';
|
||||
import MkToast from '@/components/MkToast.vue';
|
||||
import MkNoteToast from '@/components/MkNoteToast.vue';
|
||||
import MkWelcomeToast from '@/components/MkWelcomeToast.vue';
|
||||
import MkDialog from '@/components/MkDialog.vue';
|
||||
import MkPasswordDialog from '@/components/MkPasswordDialog.vue';
|
||||
@ -179,15 +178,9 @@ export function pageWindow(path: string) {
|
||||
}, {}, 'closed');
|
||||
}
|
||||
|
||||
export function toast(message: string) {
|
||||
export function toast(message: string, icon?: string) {
|
||||
popup(MkToast, {
|
||||
message,
|
||||
}, {}, 'closed');
|
||||
}
|
||||
|
||||
export function noteToast(message: string, icon: string) {
|
||||
popup(MkNoteToast, {
|
||||
message,
|
||||
icon,
|
||||
}, {}, 'closed');
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ function generateToken() {
|
||||
text: token,
|
||||
}).then(() => {
|
||||
copyToClipboard(token);
|
||||
os.toast(i18n.ts.copied, 'copied');
|
||||
});
|
||||
},
|
||||
}, 'closed');
|
||||
|
@ -131,6 +131,7 @@ export function getDriveFileMenu(file: Misskey.entities.DriveFile, folder?: Miss
|
||||
text: i18n.ts.copyFileId,
|
||||
action: () => {
|
||||
copyToClipboard(file.id);
|
||||
os.toast(i18n.ts.copied, 'copied');
|
||||
},
|
||||
}]);
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ export function getCopyNoteLinkMenu(note: Misskey.entities.Note, text: string):
|
||||
text,
|
||||
action: (): void => {
|
||||
copyToClipboard(`${url}/notes/${note.id}`);
|
||||
os.success();
|
||||
os.toast(i18n.ts.copiedLink, 'copied');
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -241,12 +241,12 @@ export function getNoteMenu(props: {
|
||||
|
||||
function copyContent(): void {
|
||||
copyToClipboard(appearNote.text);
|
||||
os.success();
|
||||
os.toast(i18n.ts.copiedContent, 'copied');
|
||||
}
|
||||
|
||||
function copyLink(): void {
|
||||
copyToClipboard(`${url}/notes/${appearNote.id}`);
|
||||
os.success();
|
||||
os.toast(i18n.ts.copiedLink, 'copied');
|
||||
}
|
||||
|
||||
function togglePin(pin: boolean): void {
|
||||
@ -521,6 +521,7 @@ export function getNoteMenu(props: {
|
||||
text: i18n.ts.copyNoteId,
|
||||
action: () => {
|
||||
copyToClipboard(appearNote.id);
|
||||
os.toast(i18n.ts.copied, 'copied');
|
||||
},
|
||||
}]);
|
||||
}
|
||||
@ -629,7 +630,7 @@ export function getRenoteMenu(props: {
|
||||
renoteId: appearNote.id,
|
||||
channelId: appearNote.channelId,
|
||||
}).then(() => {
|
||||
os.noteToast(i18n.ts.renoted, 'renote');
|
||||
os.toast(i18n.ts.renoted, 'renote');
|
||||
});
|
||||
}
|
||||
},
|
||||
@ -685,7 +686,7 @@ export function getRenoteMenu(props: {
|
||||
visibility,
|
||||
renoteId: appearNote.id,
|
||||
}).then(() => {
|
||||
os.noteToast(i18n.ts.renoted, 'renote');
|
||||
os.toast(i18n.ts.renoted, 'renote');
|
||||
});
|
||||
}
|
||||
},
|
||||
@ -723,7 +724,7 @@ export function getRenoteMenu(props: {
|
||||
visibility: 'public',
|
||||
renoteId: appearNote.id,
|
||||
}).then(() => {
|
||||
os.noteToast(i18n.ts.renoted, 'renote');
|
||||
os.toast(i18n.ts.renoted, 'renote');
|
||||
});
|
||||
},
|
||||
});
|
||||
@ -741,7 +742,7 @@ export function getRenoteMenu(props: {
|
||||
visibility: 'home',
|
||||
renoteId: appearNote.id,
|
||||
}).then(() => {
|
||||
os.noteToast(i18n.ts.renoted, 'renote');
|
||||
os.toast(i18n.ts.renoted, 'renote');
|
||||
});
|
||||
},
|
||||
});
|
||||
@ -758,7 +759,7 @@ export function getRenoteMenu(props: {
|
||||
visibility: 'followers',
|
||||
renoteId: appearNote.id,
|
||||
}).then(() => {
|
||||
os.noteToast(i18n.ts.renoted, 'renote');
|
||||
os.toast(i18n.ts.renoted, 'renote');
|
||||
});
|
||||
},
|
||||
});
|
||||
@ -812,7 +813,7 @@ export async function getRenoteOnly(props: {
|
||||
renoteId: appearNote.id,
|
||||
channelId: appearNote.channelId,
|
||||
}).then(() => {
|
||||
os.noteToast(i18n.ts.renoted, 'renote');
|
||||
os.toast(i18n.ts.renoted, 'renote');
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -841,7 +842,7 @@ export async function getRenoteOnly(props: {
|
||||
visibility,
|
||||
renoteId: appearNote.id,
|
||||
}).then(() => {
|
||||
os.noteToast(i18n.ts.renoted, 'renote');
|
||||
os.toast(i18n.ts.renoted, 'renote');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -184,6 +184,7 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
|
||||
text: i18n.ts.copyUsername,
|
||||
action: () => {
|
||||
copyToClipboard(`@${user.username}@${user.host ?? host}`);
|
||||
os.toast(i18n.ts.copied, 'copied');
|
||||
},
|
||||
}, ...(iAmModerator ? [{
|
||||
icon: 'ti ti-user-exclamation',
|
||||
@ -196,6 +197,7 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
|
||||
text: i18n.ts.copyRSS,
|
||||
action: () => {
|
||||
copyToClipboard(`${user.host ?? host}/@${user.username}.atom`);
|
||||
os.toast(i18n.ts.copied, 'copied');
|
||||
},
|
||||
}, {
|
||||
icon: 'ti ti-share',
|
||||
@ -203,6 +205,7 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
|
||||
action: () => {
|
||||
const canonical = user.host === null ? `@${user.username}` : `@${user.username}@${toUnicode(user.host)}`;
|
||||
copyToClipboard(`${url}/${canonical}`);
|
||||
os.toast(i18n.ts.copiedLink, 'copied');
|
||||
},
|
||||
}, {
|
||||
icon: 'ti ti-mail',
|
||||
@ -391,6 +394,7 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
|
||||
text: i18n.ts.copyUserId,
|
||||
action: () => {
|
||||
copyToClipboard(user.id);
|
||||
os.toast(i18n.ts.copied, 'copied');
|
||||
},
|
||||
}]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user