feat: Added media right-click prevention function
This commit is contained in:
parent
ed56415407
commit
fc0d8238e3
|
@ -16,6 +16,7 @@
|
|||
- 클라이언트: Enter 키를 눌러 보내기 옵션 추가
|
||||
- 클라이언트: 서버와 연결이 끊어졌을 때 경고를 표시하지 않는 옵션 추가
|
||||
- 클라이언트: (friendly) 모바일 환경에서 서버와 연결이 끊어졌을 때 표시되는 경고창의 UI 개선
|
||||
- 클라이언트: 미디어 우클릭 방지 기능 추가
|
||||
|
||||
## 12.x.x-cp-2.x.x (unreleased)_legacy
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
_lang_: "English"
|
||||
disableRightClick: "Prohibit right click"
|
||||
useEnterToSend: "Press Enter to send"
|
||||
useEnterToSendDescription: "When the option is enabled, you can use the Shift+Enter key for line break."
|
||||
headlineMisskey: "A network connected by notes"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
_lang_: "日本語"
|
||||
|
||||
disableRightClick: "右クリックを禁止"
|
||||
useEnterToSend: "Enterキーを押して送信"
|
||||
useEnterToSendDescription: "オプションを有効にすると、行替えはShift+Enterキーでできます。"
|
||||
headlineMisskey: "ノートでつながるネットワーク"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
_lang_: "한국어"
|
||||
disableRightClick: "우클릭 방지"
|
||||
useEnterToSend: "Enter 키를 눌러 보내기"
|
||||
useEnterToSendDescription: "옵션을 활성화하면 줄 바꿈은 Shift + Enter 키로 할 수 있어요."
|
||||
headlineMisskey: "노트로 연결되는 네트워크"
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
|
||||
export class disableRightClick1629387925000 {
|
||||
constructor() {
|
||||
this.name = 'disableRightClick1629387925000';
|
||||
}
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "note" ADD "disableRightClick" boolean NOT NULL DEFAULT false`);
|
||||
}
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "disableRIghtClick"`);
|
||||
}
|
||||
}
|
|
@ -86,6 +86,11 @@ export class Note {
|
|||
})
|
||||
public localOnly: boolean;
|
||||
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
})
|
||||
public disableRightClick: boolean;
|
||||
|
||||
@Column('smallint', {
|
||||
default: 0,
|
||||
})
|
||||
|
|
|
@ -234,6 +234,7 @@ export const NoteRepository = db.getRepository(Note).extend({
|
|||
visibility: note.visibility,
|
||||
localOnly: note.localOnly || undefined,
|
||||
visibleUserIds: note.visibility === 'specified' ? note.visibleUserIds : undefined,
|
||||
disableRightClick: note.disableRightClick || undefined,
|
||||
renoteCount: note.renoteCount,
|
||||
repliesCount: note.repliesCount,
|
||||
reactions: convertLegacyReactions(note.reactions),
|
||||
|
|
|
@ -52,6 +52,10 @@ export const packedNoteSchema = {
|
|||
optional: true, nullable: true,
|
||||
ref: 'Note',
|
||||
},
|
||||
disableRightClick: {
|
||||
type: 'boolean',
|
||||
optional: true, nullable: false,
|
||||
},
|
||||
isHidden: {
|
||||
type: 'boolean',
|
||||
optional: true, nullable: false,
|
||||
|
|
|
@ -253,6 +253,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s
|
|||
cw,
|
||||
text,
|
||||
localOnly: false,
|
||||
disableRightClick: false,
|
||||
visibility,
|
||||
visibleUsers,
|
||||
apMentions,
|
||||
|
|
|
@ -90,6 +90,7 @@ export const paramDef = {
|
|||
text: { type: 'string', maxLength: MAX_NOTE_TEXT_LENGTH, nullable: true },
|
||||
cw: { type: 'string', nullable: true, maxLength: 100 },
|
||||
localOnly: { type: 'boolean', default: false },
|
||||
disableRightClick: { type: 'boolean', default: false },
|
||||
noExtractMentions: { type: 'boolean', default: false },
|
||||
noExtractHashtags: { type: 'boolean', default: false },
|
||||
noExtractEmojis: { type: 'boolean', default: false },
|
||||
|
@ -261,6 +262,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
renote,
|
||||
cw: ps.cw,
|
||||
localOnly: ps.localOnly,
|
||||
disableRightClick: ps.disableRightClick,
|
||||
visibility: ps.visibility,
|
||||
visibleUsers,
|
||||
channel,
|
||||
|
|
|
@ -114,6 +114,7 @@ type Option = {
|
|||
files?: DriveFile[] | null;
|
||||
poll?: IPoll | null;
|
||||
localOnly?: boolean | null;
|
||||
disableRightClick?: boolean | null;
|
||||
cw?: string | null;
|
||||
visibility?: string;
|
||||
visibleUsers?: MinimumUser[] | null;
|
||||
|
@ -146,6 +147,7 @@ export default async (user: { id: User['id']; username: User['username']; host:
|
|||
if (data.createdAt == null) data.createdAt = new Date();
|
||||
if (data.visibility == null) data.visibility = 'public';
|
||||
if (data.localOnly == null) data.localOnly = false;
|
||||
if (data.disableRightClick == null) data.disableRightClick = false;
|
||||
if (data.channel != null) data.visibility = 'public';
|
||||
if (data.channel != null) data.visibleUsers = [];
|
||||
if (data.channel != null) data.localOnly = true;
|
||||
|
@ -520,6 +522,7 @@ async function insertNote(user: { id: User['id']; host: User['host']; }, data: O
|
|||
emojis,
|
||||
userId: user.id,
|
||||
localOnly: data.localOnly!,
|
||||
disableRightClick: data.disableRightClick!,
|
||||
visibility: data.visibility as any,
|
||||
visibleUserIds: data.visibility === 'specified'
|
||||
? data.visibleUsers
|
||||
|
|
|
@ -67,7 +67,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div v-if="appearNote.files.length > 0" class="files">
|
||||
<XMediaList :media-list="appearNote.files"/>
|
||||
<XMediaList v-if="appearNote.disableRightClick" :media-list="appearNote.files" @contextmenu.prevent/>
|
||||
<XMediaList v-else :media-list="appearNote.files"/>
|
||||
</div>
|
||||
<XPoll v-if="appearNote.poll" ref="pollViewer" :note="appearNote" class="poll"/>
|
||||
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" class="url-preview"/>
|
||||
|
|
|
@ -56,7 +56,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div v-if="appearNote.files.length > 0" class="files">
|
||||
<XMediaList :media-list="appearNote.files"/>
|
||||
<XMediaList v-if="appearNote.disableRightClick" :media-list="appearNote.files" @contextmenu.prevent/>
|
||||
<XMediaList v-else :media-list="appearNote.files"/>
|
||||
</div>
|
||||
<XPoll v-if="appearNote.poll" ref="pollViewer" :note="appearNote" class="poll"/>
|
||||
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="false" class="url-preview"/>
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
<button v-tooltip="i18n.ts.mention" class="_button" @click="insertMention"><i class="fas fa-at"></i></button>
|
||||
<button v-tooltip="i18n.ts.hashtags" class="_button" :class="{ active: withHashtags }" @click="withHashtags = !withHashtags"><i class="fas fa-hashtag"></i></button>
|
||||
<button v-tooltip="i18n.ts.emoji" class="_button" @click="insertEmoji"><i class="fas fa-laugh-squint"></i></button>
|
||||
<button v-tooltip="$ts.disableRightClick" class="_button" :class="{ active: disableRightClick }" @click="disableRightClick = !disableRightClick"><i class="fas fa-mouse"></i></button>
|
||||
<button v-if="postFormActions.length > 0" v-tooltip="i18n.ts.plugin" class="_button" @click="showActions"><i class="fas fa-plug"></i></button>
|
||||
</footer>
|
||||
<datalist id="hashtags">
|
||||
|
@ -149,6 +150,7 @@ let quoteId = $ref(null);
|
|||
let hasNotSpecifiedMentions = $ref(false);
|
||||
let recentHashtags = $ref(JSON.parse(localStorage.getItem('hashtags') || '[]'));
|
||||
let imeText = $ref('');
|
||||
let disableRightClick = $ref(false);
|
||||
|
||||
const typing = throttle(3000, () => {
|
||||
if (props.channel) {
|
||||
|
@ -294,6 +296,7 @@ function watchForDraft() {
|
|||
watch($$(text), () => saveDraft());
|
||||
watch($$(useCw), () => saveDraft());
|
||||
watch($$(cw), () => saveDraft());
|
||||
watch($$(disableRightClick), () => saveDraft());
|
||||
watch($$(poll), () => saveDraft());
|
||||
watch($$(files), () => saveDraft(), { deep: true });
|
||||
watch($$(visibility), () => saveDraft());
|
||||
|
@ -542,6 +545,7 @@ function saveDraft() {
|
|||
text: text,
|
||||
useCw: useCw,
|
||||
cw: cw,
|
||||
disableRightClick: disableRightClick,
|
||||
visibility: visibility,
|
||||
localOnly: localOnly,
|
||||
files: files,
|
||||
|
@ -572,6 +576,7 @@ async function post() {
|
|||
localOnly: localOnly,
|
||||
visibility: visibility,
|
||||
visibleUserIds: visibility === 'specified' ? visibleUsers.map(u => u.id) : undefined,
|
||||
disableRightClick: disableRightClick,
|
||||
};
|
||||
|
||||
if (withHashtags && hashtags && hashtags.trim() !== '') {
|
||||
|
@ -682,6 +687,7 @@ onMounted(() => {
|
|||
text = draft.data.text;
|
||||
useCw = draft.data.useCw;
|
||||
cw = draft.data.cw;
|
||||
disableRightClick = draft.data.disableRightClick;
|
||||
visibility = draft.data.visibility;
|
||||
localOnly = draft.data.localOnly;
|
||||
files = (draft.data.files || []).filter(draftFile => draftFile);
|
||||
|
@ -709,6 +715,7 @@ onMounted(() => {
|
|||
visibility = init.visibility;
|
||||
localOnly = init.localOnly;
|
||||
quoteId = init.renote ? init.renote.id : null;
|
||||
disableRightClick = init.disableRightClick != null;
|
||||
}
|
||||
|
||||
nextTick(() => watchForDraft());
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
</div>
|
||||
<details v-if="note.files.length > 0">
|
||||
<summary>({{ $t('withNFiles', { n: note.files.length }) }})</summary>
|
||||
<XMediaList v-if="note.disableRightClick" :media-list="note.files" @contextmenu.prevent/>
|
||||
<XMediaList :media-list="note.files"/>
|
||||
</details>
|
||||
<details v-if="note.poll">
|
||||
|
|
Loading…
Reference in a new issue