Remove all right click context menu functionality

The context menus provided by Misskey, overriding the browser context menus
on right click, were driving me very angry. This makes it much easier to copy
image URLs or even just do a quick "Inspect element".

Side victims: the reaction picker context menu feature. I never used it, so
I am only guessing what it was doing, but since I removed the whole underlying
mechanic, it only felt right to yeet the feature too.
This commit is contained in:
Michcio 2022-08-09 14:36:46 +02:00
parent 92bfbc0bb6
commit f53ff2089b
42 changed files with 12 additions and 403 deletions

View file

@ -711,7 +711,6 @@ apply: "تطبيق"
receiveAnnouncementFromInstance: "استلم إشعارات من هذا المثيل" receiveAnnouncementFromInstance: "استلم إشعارات من هذا المثيل"
emailNotification: "إشعارات البريد الكتروني" emailNotification: "إشعارات البريد الكتروني"
inChannelSearch: "ابحث عن قناة" inChannelSearch: "ابحث عن قناة"
useReactionPickerForContextMenu: "افتح منتقي التفاعلات عند النقر بالزر الأيمن"
typingUsers: "{users} يكتب(ون)..." typingUsers: "{users} يكتب(ون)..."
jumpToSpecifiedDate: "انتقل إلى تاريخ محدد" jumpToSpecifiedDate: "انتقل إلى تاريخ محدد"
showingPastTimeline: "أنت تستعرض حاليًا خيطًا زمنيًا قديمًا" showingPastTimeline: "أنت تستعرض حاليًا خيطًا زمنيًا قديمًا"

View file

@ -773,7 +773,6 @@ receiveAnnouncementFromInstance: "এই ইন্সট্যান্স থ
emailNotification: "ইমেইল বিজ্ঞপ্তি" emailNotification: "ইমেইল বিজ্ঞপ্তি"
publish: "প্রকাশ" publish: "প্রকাশ"
inChannelSearch: "চ্যানেলে খুঁজুন" inChannelSearch: "চ্যানেলে খুঁজুন"
useReactionPickerForContextMenu: "রাইট ক্লিকের মাধ্যমে রিঅ্যাকশন পিকার খুলুন"
typingUsers: "{users} লেখছে" typingUsers: "{users} লেখছে"
jumpToSpecifiedDate: "একটি নির্দিষ্ট তারিখে যান" jumpToSpecifiedDate: "একটি নির্দিষ্ট তারিখে যান"
showingPastTimeline: "অতীতের টাইমলাইন দেখানো হচ্ছে" showingPastTimeline: "অতীতের টাইমলাইন দেখানো হচ্ছে"

View file

@ -793,7 +793,6 @@ receiveAnnouncementFromInstance: "Benachrichtigungen von dieser Instanz empfange
emailNotification: "Email-Benachrichtigungen" emailNotification: "Email-Benachrichtigungen"
publish: "Veröffentlichen" publish: "Veröffentlichen"
inChannelSearch: "In Kanal suchen" inChannelSearch: "In Kanal suchen"
useReactionPickerForContextMenu: "Reaktionsauswahl durch Rechtsklick öffnen"
typingUsers: "{users} ist/sind am schreiben …" typingUsers: "{users} ist/sind am schreiben …"
jumpToSpecifiedDate: "Zu bestimmtem Datum springen" jumpToSpecifiedDate: "Zu bestimmtem Datum springen"
showingPastTimeline: "Es wird eine alte Chronik angezeigt" showingPastTimeline: "Es wird eine alte Chronik angezeigt"

View file

@ -775,7 +775,6 @@ receiveAnnouncementFromInstance: "Receive notifications from this instance"
emailNotification: "Email notifications" emailNotification: "Email notifications"
publish: "Publish" publish: "Publish"
inChannelSearch: "Search in channel" inChannelSearch: "Search in channel"
useReactionPickerForContextMenu: "Open reaction picker on right-click"
typingUsers: "{users} is/are typing..." typingUsers: "{users} is/are typing..."
jumpToSpecifiedDate: "Jump to specific date" jumpToSpecifiedDate: "Jump to specific date"
showingPastTimeline: "Currently displaying an old timeline" showingPastTimeline: "Currently displaying an old timeline"

View file

@ -776,8 +776,6 @@ receiveAnnouncementFromInstance: "Recibir notificaciones de la instancia"
emailNotification: "Notificaciones por correo electrónico" emailNotification: "Notificaciones por correo electrónico"
publish: "Publicar" publish: "Publicar"
inChannelSearch: "Buscar en el canal" inChannelSearch: "Buscar en el canal"
useReactionPickerForContextMenu: "Haga clic con el botón derecho para abrir el menu\
\ de reacciones"
typingUsers: "{users} está escribiendo" typingUsers: "{users} está escribiendo"
jumpToSpecifiedDate: "Saltar a una fecha específica" jumpToSpecifiedDate: "Saltar a una fecha específica"
showingPastTimeline: "Mostrar líneas de tiempo antiguas" showingPastTimeline: "Mostrar líneas de tiempo antiguas"

View file

@ -785,7 +785,6 @@ receiveAnnouncementFromInstance: "Recevoir les messages d'information de l'insta
emailNotification: "Notifications par mail" emailNotification: "Notifications par mail"
publish: "Public" publish: "Public"
inChannelSearch: "Chercher dans le canal" inChannelSearch: "Chercher dans le canal"
useReactionPickerForContextMenu: "Clic-droit pour ouvrir le panneau de réactions"
typingUsers: "{users} est en train d'écrire" typingUsers: "{users} est en train d'écrire"
jumpToSpecifiedDate: "Se rendre à la date" jumpToSpecifiedDate: "Se rendre à la date"
showingPastTimeline: "Un fil ancien est affiché" showingPastTimeline: "Un fil ancien est affiché"

View file

@ -780,7 +780,6 @@ receiveAnnouncementFromInstance: "Terima pemberitahuan surel dari instansi ini"
emailNotification: "Pemberitahuan surel" emailNotification: "Pemberitahuan surel"
publish: "Terbitkan" publish: "Terbitkan"
inChannelSearch: "Cari di kanal" inChannelSearch: "Cari di kanal"
useReactionPickerForContextMenu: "Buka pemilih reaksi dengan klik-kanan"
typingUsers: "{users} sedang mengetik..." typingUsers: "{users} sedang mengetik..."
jumpToSpecifiedDate: "Loncat ke tanggal spesifik" jumpToSpecifiedDate: "Loncat ke tanggal spesifik"
showingPastTimeline: "Sedang menampilkan linimasa lama" showingPastTimeline: "Sedang menampilkan linimasa lama"

View file

@ -762,8 +762,6 @@ receiveAnnouncementFromInstance: "Ricevi i messaggi informativi dall'istanza"
emailNotification: "Eventi per notifiche via mail" emailNotification: "Eventi per notifiche via mail"
publish: "Pubblico" publish: "Pubblico"
inChannelSearch: "Cerca in canale" inChannelSearch: "Cerca in canale"
useReactionPickerForContextMenu: "Cliccare sul tasto destro per aprire il pannello\
\ di reazioni"
typingUsers: "{users} sta(nno) scrivendo" typingUsers: "{users} sta(nno) scrivendo"
jumpToSpecifiedDate: "Vai alla data " jumpToSpecifiedDate: "Vai alla data "
showingPastTimeline: "Stai visualizzando una vecchia timeline" showingPastTimeline: "Stai visualizzando una vecchia timeline"

View file

@ -721,7 +721,6 @@ receiveAnnouncementFromInstance: "インスタンスからのお知らせを受
emailNotification: "メール通知" emailNotification: "メール通知"
publish: "公開" publish: "公開"
inChannelSearch: "チャンネル内検索" inChannelSearch: "チャンネル内検索"
useReactionPickerForContextMenu: "右クリックでリアクションピッカーを開く"
typingUsers: "{users}が入力中" typingUsers: "{users}が入力中"
jumpToSpecifiedDate: "特定の日付にジャンプ" jumpToSpecifiedDate: "特定の日付にジャンプ"
showingPastTimeline: "過去のタイムラインを表示しています" showingPastTimeline: "過去のタイムラインを表示しています"

View file

@ -633,7 +633,6 @@ apply: "適用"
receiveAnnouncementFromInstance: "インスタンスからのお知らせを受け取る" receiveAnnouncementFromInstance: "インスタンスからのお知らせを受け取る"
emailNotification: "メール通知" emailNotification: "メール通知"
inChannelSearch: "チャンネル内検索" inChannelSearch: "チャンネル内検索"
useReactionPickerForContextMenu: "右クリックでリアクションピッカーを開くようにする"
typingUsers: "{users}が今書きよるで" typingUsers: "{users}が今書きよるで"
jumpToSpecifiedDate: "特定の日付にジャンプ" jumpToSpecifiedDate: "特定の日付にジャンプ"
showingPastTimeline: "過去のタイムラインを表示してるで" showingPastTimeline: "過去のタイムラインを表示してるで"

View file

@ -716,7 +716,6 @@ receiveAnnouncementFromInstance: "이 인스턴스의 알림을 이메일로 수
emailNotification: "메일 알림" emailNotification: "메일 알림"
publish: "게시" publish: "게시"
inChannelSearch: "채널에서 검색" inChannelSearch: "채널에서 검색"
useReactionPickerForContextMenu: "우클릭하여 리액션 선택기 열기"
typingUsers: "{users} 님이 입력하고 있어요.." typingUsers: "{users} 님이 입력하고 있어요.."
jumpToSpecifiedDate: "특정 날짜로 이동" jumpToSpecifiedDate: "특정 날짜로 이동"
showingPastTimeline: "과거의 타임라인을 표시하고 있어요" showingPastTimeline: "과거의 타임라인을 표시하고 있어요"

View file

@ -737,7 +737,6 @@ receiveAnnouncementFromInstance: "Otrzymuj powiadomienia e-mail z tej instancji"
emailNotification: "Powiadomienia e-mail" emailNotification: "Powiadomienia e-mail"
publish: "Publikuj" publish: "Publikuj"
inChannelSearch: "Szukaj na kanale" inChannelSearch: "Szukaj na kanale"
useReactionPickerForContextMenu: "Otwórz wybornik reakcji prawym kliknięciem"
typingUsers: "{users} pisze(-ą)..." typingUsers: "{users} pisze(-ą)..."
jumpToSpecifiedDate: "Przejdź do określonej daty" jumpToSpecifiedDate: "Przejdź do określonej daty"
showingPastTimeline: "Obecnie wyświetla starą oś czasu" showingPastTimeline: "Obecnie wyświetla starą oś czasu"

View file

@ -770,7 +770,6 @@ receiveAnnouncementFromInstance: "Получать оповещения с ин
emailNotification: "Уведомления по электронной почте" emailNotification: "Уведомления по электронной почте"
publish: "Опубликовать" publish: "Опубликовать"
inChannelSearch: "Поиск по каналу" inChannelSearch: "Поиск по каналу"
useReactionPickerForContextMenu: "Открывать палитру реакций правой кнопкой"
typingUsers: "Стук клавиш. Это {users}…" typingUsers: "Стук клавиш. Это {users}…"
jumpToSpecifiedDate: "Перейти к заданной дате" jumpToSpecifiedDate: "Перейти к заданной дате"
showingPastTimeline: "Отображается старая лента" showingPastTimeline: "Отображается старая лента"

View file

@ -761,7 +761,6 @@ receiveAnnouncementFromInstance: "Prijať notifikácie z tohoto servera"
emailNotification: "Emailové upozornenia" emailNotification: "Emailové upozornenia"
publish: "Zverejniť" publish: "Zverejniť"
inChannelSearch: "Hľadať v kanáli" inChannelSearch: "Hľadať v kanáli"
useReactionPickerForContextMenu: "Otvoriť výber reakcií na pravý klik"
typingUsers: "{users} píše/u" typingUsers: "{users} píše/u"
jumpToSpecifiedDate: "Skočiť na konkrétny dátum" jumpToSpecifiedDate: "Skočiť na konkrétny dátum"
showingPastTimeline: "Práve vidíte starú časovú os" showingPastTimeline: "Práve vidíte starú časovú os"

View file

@ -768,7 +768,6 @@ receiveAnnouncementFromInstance: "Отримувати оповіщення з
emailNotification: "Сповіщення електронною поштою" emailNotification: "Сповіщення електронною поштою"
publish: "Опублікувати" publish: "Опублікувати"
inChannelSearch: "Пошук за каналом" inChannelSearch: "Пошук за каналом"
useReactionPickerForContextMenu: "Відкривати палітру реакцій правою кнопкою"
typingUsers: "Стук клавіш. Це {users}…" typingUsers: "Стук клавіш. Це {users}…"
goBack: "Назад" goBack: "Назад"
info: "Інформація" info: "Інформація"

View file

@ -767,7 +767,6 @@ receiveAnnouncementFromInstance: "Nhận thông báo từ máy chủ này"
emailNotification: "Thông báo email" emailNotification: "Thông báo email"
publish: "Đăng" publish: "Đăng"
inChannelSearch: "Tìm trong kênh" inChannelSearch: "Tìm trong kênh"
useReactionPickerForContextMenu: "Nhấn chuột phải để mở bộ chọn biểu cảm"
typingUsers: "{users} đang nhập…" typingUsers: "{users} đang nhập…"
jumpToSpecifiedDate: "Đến một ngày cụ thể" jumpToSpecifiedDate: "Đến một ngày cụ thể"
showingPastTimeline: "Hiện đang hiển thị dòng thời gian cũ" showingPastTimeline: "Hiện đang hiển thị dòng thời gian cũ"

View file

@ -717,7 +717,6 @@ receiveAnnouncementFromInstance: "从实例接收通知"
emailNotification: "邮件通知" emailNotification: "邮件通知"
publish: "发布" publish: "发布"
inChannelSearch: "频道内搜索" inChannelSearch: "频道内搜索"
useReactionPickerForContextMenu: "单击右键打开回应工具栏"
typingUsers: "{users}正在输入" typingUsers: "{users}正在输入"
jumpToSpecifiedDate: "跳转到特定日期" jumpToSpecifiedDate: "跳转到特定日期"
showingPastTimeline: "显示过去的时间线" showingPastTimeline: "显示过去的时间线"

View file

@ -716,7 +716,6 @@ receiveAnnouncementFromInstance: "接收由本實例發出的電郵通知"
emailNotification: "郵件通知" emailNotification: "郵件通知"
publish: "發佈" publish: "發佈"
inChannelSearch: "頻道内搜尋" inChannelSearch: "頻道内搜尋"
useReactionPickerForContextMenu: "點擊右鍵開啟回應工具欄"
typingUsers: "{users}輸入中..." typingUsers: "{users}輸入中..."
jumpToSpecifiedDate: "跳轉到特定日期" jumpToSpecifiedDate: "跳轉到特定日期"
showingPastTimeline: "顯示過往的時間線" showingPastTimeline: "顯示過往的時間線"

View file

@ -1,5 +1,5 @@
<template> <template>
<div ref="rootEl" class="swhvrteh _popup _shadow" :style="{ zIndex }" @contextmenu.prevent="() => {}"> <div ref="rootEl" class="swhvrteh _popup _shadow" :style="{ zIndex }">
<ol v-if="type === 'user'" ref="suggests" class="users"> <ol v-if="type === 'user'" ref="suggests" class="users">
<li v-for="user in users" tabindex="-1" class="user" @click="complete(type, user)" @keydown="onKeydown"> <li v-for="user in users" tabindex="-1" class="user" @click="complete(type, user)" @keydown="onKeydown">
<img class="avatar" :src="user.avatarUrl"/> <img class="avatar" :src="user.avatarUrl"/>

View file

@ -5,7 +5,6 @@
draggable="true" draggable="true"
:title="title" :title="title"
@click="onClick" @click="onClick"
@contextmenu.stop="onContextmenu"
@dragstart="onDragstart" @dragstart="onDragstart"
@dragend="onDragend" @dragend="onDragend"
> >
@ -101,10 +100,6 @@ function onClick(ev: MouseEvent): void {
} }
} }
function onContextmenu(ev: MouseEvent): void {
os.contextMenu(getMenu(), ev);
}
function onDragstart(ev: DragEvent): void { function onDragstart(ev: DragEvent): void {
if (ev.dataTransfer) { if (ev.dataTransfer) {
ev.dataTransfer.effectAllowed = 'move'; ev.dataTransfer.effectAllowed = 'move';

View file

@ -5,7 +5,6 @@
draggable="true" draggable="true"
:title="title" :title="title"
@click="onClick" @click="onClick"
@contextmenu.stop="onContextmenu"
@mouseover="onMouseover" @mouseover="onMouseover"
@mouseout="onMouseout" @mouseout="onMouseout"
@dragover.prevent.stop="onDragover" @dragover.prevent.stop="onDragover"
@ -218,27 +217,6 @@ function deleteFolder() {
}); });
} }
function onContextmenu(ev: MouseEvent) {
os.contextMenu([{
text: i18n.ts.openInWindow,
icon: 'fas fa-window-restore',
action: () => {
os.popup(defineAsyncComponent(() => import('./drive-window.vue')), {
initialFolder: props.folder,
}, {
}, 'closed');
},
}, null, {
text: i18n.ts.rename,
icon: 'fas fa-i-cursor',
action: rename,
}, null, {
text: i18n.ts.delete,
icon: 'fas fa-trash-alt',
danger: true,
action: deleteFolder,
}], ev);
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="yfudmmck"> <div class="yfudmmck">
<nav> <nav>
<div class="path" @contextmenu.prevent.stop="() => {}"> <div class="path">
<XNavFolder <XNavFolder
:class="{ current: folder == null }" :class="{ current: folder == null }"
:parent-folder="folder" :parent-folder="folder"
@ -33,7 +33,6 @@
@dragenter="onDragenter" @dragenter="onDragenter"
@dragleave="onDragleave" @dragleave="onDragleave"
@drop.prevent.stop="onDrop" @drop.prevent.stop="onDrop"
@contextmenu.stop="onContextmenu"
> >
<div ref="contents" class="contents"> <div ref="contents" class="contents">
<div v-show="folders.length > 0" ref="foldersContainer" class="folders"> <div v-show="folders.length > 0" ref="foldersContainer" class="folders">
@ -601,10 +600,6 @@ function showMenu(ev: MouseEvent) {
os.popupMenu(getMenu(), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined); os.popupMenu(getMenu(), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
} }
function onContextmenu(ev: MouseEvent) {
os.contextMenu(getMenu(), ev);
}
onMounted(() => { onMounted(() => {
if (defaultStore.state.enableInfiniteScroll && loadMoreFiles.value) { if (defaultStore.state.enableInfiniteScroll && loadMoreFiles.value) {
nextTick(() => { nextTick(() => {

View file

@ -1,5 +1,5 @@
<template> <template>
<a :href="to" :class="active ? activeClass : null" @click.prevent="nav" @contextmenu.prevent.stop="onContextmenu"> <a :href="to" :class="active ? activeClass : null" @click.prevent="nav">
<slot></slot> <slot></slot>
</a> </a>
</template> </template>
@ -32,39 +32,6 @@ const active = $computed(() => {
return resolved.route.name === router.currentRoute.value.name; return resolved.route.name === router.currentRoute.value.name;
}); });
function onContextmenu(ev) {
const selection = window.getSelection();
if (selection && selection.toString() !== '') return;
os.contextMenu([{
type: 'label',
text: props.to,
}, {
icon: 'fas fa-window-maximize',
text: i18n.ts.openInWindow,
action: () => {
os.pageWindow(props.to);
},
}, {
icon: 'fas fa-expand-alt',
text: i18n.ts.showInPage,
action: () => {
router.push(props.to);
},
}, null, {
icon: 'fas fa-external-link-alt',
text: i18n.ts.openInNewTab,
action: () => {
window.open(props.to, '_blank');
},
}, {
icon: 'fas fa-link',
text: i18n.ts.copyLink,
action: () => {
copyToClipboard(`${url}${props.to}`);
},
}], ev);
}
function nav() { function nav() {
if (props.behavior === 'browser') { if (props.behavior === 'browser') {
location.href = props.to; location.href = props.to;

View file

@ -1,7 +1,6 @@
<template> <template>
<component <component
:is="self ? 'MkA' : 'a'" ref="el" class="ieqqeuvs _link" :[attr]="self ? url.slice(local.length) : url" :rel="rel" :target="target" :is="self ? 'MkA' : 'a'" ref="el" class="ieqqeuvs _link" :[attr]="self ? url.slice(local.length) : url" :rel="rel" :target="target"
@contextmenu.stop="() => {}"
> >
<template v-if="!self"> <template v-if="!self">
<span class="schema">{{ schema }}//</span> <span class="schema">{{ schema }}//</span>

View file

@ -12,7 +12,6 @@
:alt="video.comment" :alt="video.comment"
preload="none" preload="none"
controls controls
@contextmenu.stop
> >
<source <source
:src="video.url" :src="video.url"

View file

@ -1,7 +1,7 @@
<template> <template>
<MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')"> <MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')">
<div ref="rootEl" class="hrmcaedk _narrow_" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }"> <div ref="rootEl" class="hrmcaedk _narrow_" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }">
<div class="header" @contextmenu="onContextmenu"> <div class="header">
<button v-if="history.length > 0" v-tooltip="i18n.ts.goBack" class="_button" @click="back()"><i class="fas fa-arrow-left"></i></button> <button v-if="history.length > 0" v-tooltip="i18n.ts.goBack" class="_button" @click="back()"><i class="fas fa-arrow-left"></i></button>
<span v-else style="display: inline-block; width: 20px"></span> <span v-else style="display: inline-block; width: 20px"></span>
<span v-if="pageMetadata?.value" class="title"> <span v-if="pageMetadata?.value" class="title">
@ -59,33 +59,6 @@ provide('shouldOmitHeaderTitle', true);
provide('shouldHeaderThin', true); provide('shouldHeaderThin', true);
const pageUrl = $computed(() => url + path); const pageUrl = $computed(() => url + path);
const contextmenu = $computed(() => {
return [{
type: 'label',
text: path,
}, {
icon: 'fas fa-expand-alt',
text: i18n.ts.showInPage,
action: expand,
}, {
icon: 'fas fa-external-link-alt',
text: i18n.ts.popout,
action: popout,
}, null, {
icon: 'fas fa-external-link-alt',
text: i18n.ts.openInNewTab,
action: () => {
window.open(pageUrl, '_blank');
modal.close();
},
}, {
icon: 'fas fa-link',
text: i18n.ts.copyLink,
action: () => {
copyToClipboard(pageUrl);
},
}];
});
function navigate(path, record = true) { function navigate(path, record = true) {
if (record) history.push(router.getCurrentPath()); if (record) history.push(router.getCurrentPath());
@ -105,10 +78,6 @@ function popout() {
_popout(path, rootEl); _popout(path, rootEl);
modal.close(); modal.close();
} }
function onContextmenu(ev: MouseEvent) {
os.contextMenu(contextmenu, ev);
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View file

@ -29,7 +29,7 @@
<MkVisibility :note="note"/> <MkVisibility :note="note"/>
</div> </div>
</div> </div>
<article class="article" @contextmenu.stop="onContextmenu"> <article class="article">
<header class="header"> <header class="header">
<MkAvatar class="avatar" :user="appearNote.user" :show-indicator="true"/> <MkAvatar class="avatar" :user="appearNote.user" :show-indicator="true"/>
<div class="body"> <div class="body">
@ -230,24 +230,6 @@ function undoReact(note): void {
}); });
} }
function onContextmenu(ev: MouseEvent): void {
const isLink = (el: HTMLElement) => {
if (el.tagName === 'A') return true;
if (el.parentElement) {
return isLink(el.parentElement);
}
};
if (isLink(ev.target)) return;
if (window.getSelection().toString() !== '') return;
if (defaultStore.state.useReactionPickerForContextMenu) {
ev.preventDefault();
react();
} else {
os.contextMenu(getNoteMenu({ note, translating, translation, menuButton, isDeleted }), ev).then(focus);
}
}
function menu(viaKeyboard = false): void { function menu(viaKeyboard = false): void {
os.popupMenu(getNoteMenu({ note, translating, translation, menuButton, isDeleted }), menuButton.value, { os.popupMenu(getNoteMenu({ note, translating, translation, menuButton, isDeleted }), menuButton.value, {
viaKeyboard, viaKeyboard,

View file

@ -30,7 +30,7 @@
<MkVisibility :note="note"/> <MkVisibility :note="note"/>
</div> </div>
</div> </div>
<article class="article" @contextmenu.stop="onContextmenu"> <article class="article">
<MkAvatar class="avatar" :user="appearNote.user"/> <MkAvatar class="avatar" :user="appearNote.user"/>
<div class="main"> <div class="main">
<XNoteHeader class="header" :note="appearNote" :mini="true"/> <XNoteHeader class="header" :note="appearNote" :mini="true"/>
@ -224,24 +224,6 @@ function undoReact(): void {
const currentClipPage = inject<Ref<foundkey.entities.Clip> | null>('currentClipPage', null); const currentClipPage = inject<Ref<foundkey.entities.Clip> | null>('currentClipPage', null);
function onContextmenu(ev: MouseEvent): void {
const isLink = (el: HTMLElement) => {
if (el.tagName === 'A') return true;
if (el.parentElement) {
return isLink(el.parentElement);
}
};
if (isLink(ev.target)) return;
if (window.getSelection().toString() !== '') return;
if (defaultStore.state.useReactionPickerForContextMenu) {
ev.preventDefault();
react();
} else {
os.contextMenu(getNoteMenu({ note, translating, translation, menuButton, isDeleted, currentClipPage }), ev).then(focus);
}
}
function menu(viaKeyboard = false): void { function menu(viaKeyboard = false): void {
os.popupMenu(getNoteMenu({ note, translating, translation, menuButton, isDeleted, currentClipPage }), menuButton.value, { os.popupMenu(getNoteMenu({ note, translating, translation, menuButton, isDeleted, currentClipPage }), menuButton.value, {
viaKeyboard, viaKeyboard,

View file

@ -7,7 +7,6 @@
:close-button="true" :close-button="true"
:buttons-left="buttonsLeft" :buttons-left="buttonsLeft"
:buttons-right="buttonsRight" :buttons-right="buttonsRight"
:contextmenu="contextmenu"
@closed="$emit('closed')" @closed="$emit('closed')"
> >
<template #header> <template #header>
@ -84,28 +83,6 @@ provideMetadataReceiver((info) => {
provide('shouldOmitHeaderTitle', true); provide('shouldOmitHeaderTitle', true);
provide('shouldHeaderThin', true); provide('shouldHeaderThin', true);
const contextmenu = $computed(() => ([{
icon: 'fas fa-expand-alt',
text: i18n.ts.showInPage,
action: expand,
}, {
icon: 'fas fa-external-link-alt',
text: i18n.ts.popout,
action: popout,
}, {
icon: 'fas fa-external-link-alt',
text: i18n.ts.openInNewTab,
action: () => {
window.open(url + router.getCurrentPath(), '_blank');
windowEl.close();
},
}, {
icon: 'fas fa-link',
text: i18n.ts.copyLink,
action: () => {
copyToClipboard(url + router.getCurrentPath());
},
}]));
function back() { function back() {
history.pop(); history.pop();

View file

@ -2,7 +2,7 @@
<div v-show="files.length != 0" class="skeikyzd"> <div v-show="files.length != 0" class="skeikyzd">
<XDraggable v-model="_files" class="files" item-key="id" animation="150" delay="100" delay-on-touch-only="true"> <XDraggable v-model="_files" class="files" item-key="id" animation="150" delay="100" delay-on-touch-only="true">
<template #item="{element}"> <template #item="{element}">
<div @click="showFileMenu(element, $event)" @contextmenu.prevent="showFileMenu(element, $event)"> <div @click="showFileMenu(element, $event)">
<MkDriveFileThumbnail :data-id="element.id" class="thumbnail" :file="element" fit="cover"/> <MkDriveFileThumbnail :data-id="element.id" class="thumbnail" :file="element" fit="cover"/>
<div v-if="element.isSensitive" class="sensitive"> <div v-if="element.isSensitive" class="sensitive">
<i class="fas fa-exclamation-triangle icon"></i> <i class="fas fa-exclamation-triangle icon"></i>

View file

@ -1,85 +0,0 @@
<template>
<transition :name="$store.state.animation ? 'fade' : ''" appear>
<div ref="rootEl" class="nvlagfpb" :style="{ zIndex }" @contextmenu.prevent.stop="() => {}">
<MkMenu :items="items" class="_popup _shadow" :align="'left'" @close="$emit('closed')"/>
</div>
</transition>
</template>
<script lang="ts" setup>
import { onMounted, onBeforeUnmount } from 'vue';
import MkMenu from './menu.vue';
import { MenuItem } from './types/menu.vue';
import contains from '@/scripts/contains';
import * as os from '@/os';
const props = defineProps<{
items: MenuItem[];
ev: MouseEvent;
}>();
const emit = defineEmits<{
(ev: 'closed'): void;
}>();
let rootEl = $ref<HTMLDivElement>();
let zIndex = $ref<number>(os.claimZIndex('high'));
onMounted(() => {
let left = props.ev.pageX + 1; // + 1
let top = props.ev.pageY + 1; // + 1
const width = rootEl.offsetWidth;
const height = rootEl.offsetHeight;
if (left + width - window.pageXOffset > window.innerWidth) {
left = window.innerWidth - width + window.pageXOffset;
}
if (top + height - window.pageYOffset > window.innerHeight) {
top = window.innerHeight - height + window.pageYOffset;
}
if (top < 0) {
top = 0;
}
if (left < 0) {
left = 0;
}
rootEl.style.top = `${top}px`;
rootEl.style.left = `${left}px`;
for (const el of Array.from(document.querySelectorAll('body *'))) {
el.addEventListener('mousedown', onMousedown);
}
});
onBeforeUnmount(() => {
for (const el of Array.from(document.querySelectorAll('body *'))) {
el.removeEventListener('mousedown', onMousedown);
}
});
function onMousedown(evt: Event) {
if (!contains(rootEl, evt.target) && (rootEl !== evt.target)) emit('closed');
}
</script>
<style lang="scss" scoped>
.nvlagfpb {
position: absolute;
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s cubic-bezier(0.16, 1, 0.3, 1), transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
transform-origin: left top;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
transform: scale(0.9);
}
</style>

View file

@ -4,7 +4,6 @@
class="rrevdjwt" class="rrevdjwt"
:class="{ center: align === 'center', asDrawer }" :class="{ center: align === 'center', asDrawer }"
:style="{ width: (width && !asDrawer) ? width + 'px' : '', maxHeight: maxHeight ? maxHeight + 'px' : '' }" :style="{ width: (width && !asDrawer) ? width + 'px' : '', maxHeight: maxHeight ? maxHeight + 'px' : '' }"
@contextmenu.self="e => e.preventDefault()"
> >
<template v-for="(item, i) in items2"> <template v-for="(item, i) in items2">
<div v-if="item === null" class="divider"></div> <div v-if="item === null" class="divider"></div>

View file

@ -1,7 +1,7 @@
<template> <template>
<transition :name="$store.state.animation ? (type === 'drawer') ? 'modal-drawer' : (type === 'popup') ? 'modal-popup' : 'modal' : ''" :duration="$store.state.animation ? 200 : 0" appear @after-leave="emit('closed')" @enter="emit('opening')" @after-enter="onOpened"> <transition :name="$store.state.animation ? (type === 'drawer') ? 'modal-drawer' : (type === 'popup') ? 'modal-popup' : 'modal' : ''" :duration="$store.state.animation ? 200 : 0" appear @after-leave="emit('closed')" @enter="emit('opening')" @after-enter="onOpened">
<div v-show="manualShowing != null ? manualShowing : showing" v-hotkey.global="keymap" class="qzhlnise" :class="{ drawer: type === 'drawer', dialog: type === 'dialog' || type === 'dialog:top', popup: type === 'popup' }" :style="{ zIndex, pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }"> <div v-show="manualShowing != null ? manualShowing : showing" v-hotkey.global="keymap" class="qzhlnise" :class="{ drawer: type === 'drawer', dialog: type === 'dialog' || type === 'dialog:top', popup: type === 'popup' }" :style="{ zIndex, pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
<div class="bg _modalBg" :class="{ transparent: transparentBg && (type === 'popup') }" :style="{ zIndex }" @click="onBgClick" @contextmenu.prevent.stop="() => {}"></div> <div class="bg _modalBg" :class="{ transparent: transparentBg && (type === 'popup') }" :style="{ zIndex }" @click="onBgClick"></div>
<div ref="content" class="content" :class="{ fixed, top: type === 'dialog:top' }" :style="{ zIndex }" @click.self="onBgClick"> <div ref="content" class="content" :class="{ fixed, top: type === 'dialog:top' }" :style="{ zIndex }" @click.self="onBgClick">
<slot :max-height="maxHeight" :type="type"></slot> <slot :max-height="maxHeight" :type="type"></slot>
</div> </div>

View file

@ -2,7 +2,7 @@
<transition :name="$store.state.animation ? 'window' : ''" appear @after-leave="emit('closed')"> <transition :name="$store.state.animation ? 'window' : ''" appear @after-leave="emit('closed')">
<div v-if="showing" ref="main" class="ebkgocck"> <div v-if="showing" ref="main" class="ebkgocck">
<div class="body _shadow _narrow_" @mousedown="moveToTop" @keydown="onKeydown"> <div class="body _shadow _narrow_" @mousedown="moveToTop" @keydown="onKeydown">
<div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu"> <div class="header" :class="{ mini }">
<span class="left"> <span class="left">
<button v-for="button in buttonsLeft" v-tooltip="button.title" class="button _button" :class="{ highlighted: button.highlighted }" @click="button.onClick"><i :class="button.icon"></i></button> <button v-for="button in buttonsLeft" v-tooltip="button.title" class="button _button" :class="{ highlighted: button.highlighted }" @click="button.onClick"><i :class="button.icon"></i></button>
</span> </span>
@ -70,7 +70,6 @@ const props = withDefaults(defineProps<{
closeButton?: boolean; closeButton?: boolean;
mini?: boolean; mini?: boolean;
front?: boolean; front?: boolean;
contextmenu?: MenuItem[];
buttonsLeft?: any[]; buttonsLeft?: any[];
buttonsRight?: any[]; buttonsRight?: any[];
}>(), { }>(), {
@ -79,7 +78,6 @@ const props = withDefaults(defineProps<{
closeButton: true, closeButton: true,
mini: false, mini: false,
front: false, front: false,
contextmenu: () => [] as MenuItem[],
buttonsLeft: () => [], buttonsLeft: () => [],
buttonsRight: () => [], buttonsRight: () => [],
}); });
@ -121,12 +119,6 @@ function onKeydown(evt: KeyboardEvent): void {
} }
} }
function onContextmenu(ev: MouseEvent): void {
if (props.contextmenu) {
os.contextMenu(props.contextmenu, ev);
}
}
function moveToTop(): void { function moveToTop(): void {
main.style.zIndex = os.claimZIndex(props.front ? 'middle' : 'low').toString(); main.style.zIndex = os.claimZIndex(props.front ? 'middle' : 'low').toString();
} }
@ -139,9 +131,6 @@ function getClickPos(evt: MouseEvent | TouchEvent): [number, number] {
} }
function onHeaderMousedown(evt: MouseEvent | TouchEvent): void { function onHeaderMousedown(evt: MouseEvent | TouchEvent): void {
// Right-click ignored as it is likely to have attempted to open a context menu
if (evt instanceof MouseEvent && evt.button === 2) return;
if (!contains(main, document.activeElement)) main.focus(); if (!contains(main, document.activeElement)) main.focus();
const position = main.getBoundingClientRect(); const position = main.getBoundingClientRect();

View file

@ -527,24 +527,6 @@ export function popupMenu(items: MenuItem[] | Ref<MenuItem[]>, src?: HTMLElement
}); });
} }
export function contextMenu(items: MenuItem[] | Ref<MenuItem[]>, ev: MouseEvent) {
ev.preventDefault();
return new Promise((resolve) => {
let dispose;
popup(defineAsyncComponent(() => import('@/components/ui/context-menu.vue')), {
items,
ev,
}, {
closed: () => {
resolve();
dispose();
},
}).then(res => {
dispose = res.dispose;
});
});
}
export function post(props: Record<string, any> = {}) { export function post(props: Record<string, any> = {}) {
return new Promise((resolve) => { return new Promise((resolve) => {
// NOTE: MkPostFormDialogをdynamic importするとiOSでテキストエリアに自動フォーカスできない // NOTE: MkPostFormDialogをdynamic importするとiOSでテキストエリアに自動フォーカスできない

View file

@ -26,7 +26,6 @@
<template #label>{{ i18n.ts.behavior }}</template> <template #label>{{ i18n.ts.behavior }}</template>
<FormSwitch v-model="imageNewTab" class="_formBlock">{{ i18n.ts.openImageInNewTab }}</FormSwitch> <FormSwitch v-model="imageNewTab" class="_formBlock">{{ i18n.ts.openImageInNewTab }}</FormSwitch>
<FormSwitch v-model="enableInfiniteScroll" class="_formBlock">{{ i18n.ts.enableInfiniteScroll }}</FormSwitch> <FormSwitch v-model="enableInfiniteScroll" class="_formBlock">{{ i18n.ts.enableInfiniteScroll }}</FormSwitch>
<FormSwitch v-model="useReactionPickerForContextMenu" class="_formBlock">{{ i18n.ts.useReactionPickerForContextMenu }}</FormSwitch>
<FormSelect v-model="serverDisconnectedBehavior" class="_formBlock"> <FormSelect v-model="serverDisconnectedBehavior" class="_formBlock">
<template #label>{{ i18n.ts.whenServerDisconnected }}</template> <template #label>{{ i18n.ts.whenServerDisconnected }}</template>
@ -141,7 +140,6 @@ const showFixedPostForm = computed(defaultStore.makeGetterSetter('showFixedPostF
const numberOfPageCache = computed(defaultStore.makeGetterSetter('numberOfPageCache')); const numberOfPageCache = computed(defaultStore.makeGetterSetter('numberOfPageCache'));
const instanceTicker = computed(defaultStore.makeGetterSetter('instanceTicker')); const instanceTicker = computed(defaultStore.makeGetterSetter('instanceTicker'));
const enableInfiniteScroll = computed(defaultStore.makeGetterSetter('enableInfiniteScroll')); const enableInfiniteScroll = computed(defaultStore.makeGetterSetter('enableInfiniteScroll'));
const useReactionPickerForContextMenu = computed(defaultStore.makeGetterSetter('useReactionPickerForContextMenu'));
const squareAvatars = computed(defaultStore.makeGetterSetter('squareAvatars')); const squareAvatars = computed(defaultStore.makeGetterSetter('squareAvatars'));
/* /*

View file

@ -152,10 +152,6 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device', where: 'device',
default: true, default: true,
}, },
useReactionPickerForContextMenu: {
where: 'device',
default: false,
},
showGapBetweenNotesInTimeline: { showGapBetweenNotesInTimeline: {
where: 'device', where: 'device',
default: false, default: false,

View file

@ -10,7 +10,7 @@
<XWidgets place="left" @mounted="attachSticky(widgetsLeft)"/> <XWidgets place="left" @mounted="attachSticky(widgetsLeft)"/>
</div> </div>
<main class="main" :style="{ background: pageMetadata?.value?.bg }" @contextmenu.stop="onContextmenu"> <main class="main" :style="{ background: pageMetadata?.value?.bg }">
<div class="content"> <div class="content">
<RouterView/> <RouterView/>
</div> </div>
@ -83,39 +83,6 @@ function attachSticky(el) {
}, { passive: true }); }, { passive: true });
} }
function top() {
window.scroll({ top: 0, behavior: 'smooth' });
}
function onContextmenu(ev: MouseEvent) {
const isLink = (el: HTMLElement) => {
if (el.tagName === 'A') return true;
if (el.parentElement) {
return isLink(el.parentElement);
}
};
if (isLink(ev.target)) return;
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return;
if (window.getSelection().toString() !== '') return;
const path = mainRouter.getCurrentPath();
os.contextMenu([{
type: 'label',
text: path,
}, {
icon: fullView ? 'fas fa-compress' : 'fas fa-expand',
text: fullView ? i18n.ts.quitFullView : i18n.ts.fullView,
action: () => {
fullView = !fullView;
},
}, {
icon: 'fas fa-window-maximize',
text: i18n.ts.openInWindow,
action: () => {
os.pageWindow(path);
},
}], ev);
}
if (window.innerWidth < 1024) { if (window.innerWidth < 1024) {
localStorage.setItem('ui', 'default'); localStorage.setItem('ui', 'default');
location.reload(); location.reload();

View file

@ -1,7 +1,6 @@
<template> <template>
<div <div
class="mk-deck" :class="[{ isMobile }, `${deckStore.reactiveState.columnAlign.value}`]" :style="{ '--deckMargin': deckStore.reactiveState.columnMargin.value + 'px' }" class="mk-deck" :class="[{ isMobile }, `${deckStore.reactiveState.columnAlign.value}`]" :style="{ '--deckMargin': deckStore.reactiveState.columnMargin.value + 'px' }"
@contextmenu.self.prevent="onContextmenu"
> >
<XSidebar v-if="!isMobile"/> <XSidebar v-if="!isMobile"/>
@ -122,13 +121,6 @@ const addColumn = async (ev) => {
}); });
}; };
const onContextmenu = (ev) => {
os.contextMenu([{
text: i18n.ts._deck.addColumn,
action: addColumn,
}], ev);
};
provide('shouldSpacerMin', true); provide('shouldSpacerMin', true);
document.documentElement.style.overflowY = 'hidden'; document.documentElement.style.overflowY = 'hidden';

View file

@ -14,7 +14,6 @@
@click="goTop" @click="goTop"
@dragstart="onDragstart" @dragstart="onDragstart"
@dragend="onDragend" @dragend="onDragend"
@contextmenu.prevent.stop="onContextmenu"
> >
<button v-if="isStacked && !isMainColumn" class="toggleActive _button" @click="toggleActive"> <button v-if="isStacked && !isMainColumn" class="toggleActive _button" @click="toggleActive">
<template v-if="active"><i class="fas fa-angle-up"></i></template> <template v-if="active"><i class="fas fa-angle-up"></i></template>
@ -183,10 +182,6 @@ function getMenu() {
return items; return items;
} }
function onContextmenu(ev: MouseEvent) {
os.contextMenu(getMenu(), ev);
}
function goTop() { function goTop() {
body.scrollTo({ body.scrollTo({
top: 0, top: 0,

View file

@ -7,7 +7,7 @@
</template> </template>
</template> </template>
<RouterView @contextmenu.stop="onContextmenu"/> <RouterView />
</XColumn> </XColumn>
</template> </template>
@ -41,28 +41,4 @@ function back() {
history.back(); history.back();
} }
*/ */
function onContextmenu(ev: MouseEvent) {
if (!ev.target) return;
const isLink = (el: HTMLElement) => {
if (el.tagName === 'A') return true;
if (el.parentElement) {
return isLink(el.parentElement);
}
};
if (isLink(ev.target as HTMLElement)) return;
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes((ev.target as HTMLElement).tagName) || (ev.target as HTMLElement).attributes['contenteditable']) return;
if (window.getSelection()?.toString() !== '') return;
const path = mainRouter.currentRoute.value.path;
os.contextMenu([{
type: 'label',
text: path,
}, {
icon: 'fas fa-window-maximize',
text: i18n.ts.openInWindow,
action: () => {
os.pageWindow(path);
},
}], ev);
}
</script> </script>

View file

@ -2,7 +2,7 @@
<div class="dkgtipfy" :class="{ wallpaper }"> <div class="dkgtipfy" :class="{ wallpaper }">
<XSidebar v-if="!isMobile" class="sidebar"/> <XSidebar v-if="!isMobile" class="sidebar"/>
<div class="contents" :style="{ background: pageMetadata?.value?.bg }" @contextmenu.stop="onContextmenu"> <div class="contents" :style="{ background: pageMetadata?.value?.bg }">
<main> <main>
<div class="content"> <div class="content">
<RouterView/> <RouterView/>
@ -131,29 +131,6 @@ onMounted(() => {
} }
}); });
const onContextmenu = (ev) => {
const isLink = (el: HTMLElement) => {
if (el.tagName === 'A') return true;
if (el.parentElement) {
return isLink(el.parentElement);
}
};
if (isLink(ev.target)) return;
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return;
if (window.getSelection()?.toString() !== '') return;
const path = mainRouter.getCurrentPath();
os.contextMenu([{
type: 'label',
text: path,
}, {
icon: 'fas fa-window-maximize',
text: i18n.ts.openInWindow,
action: () => {
os.pageWindow(path);
},
}], ev);
};
const attachSticky = (el) => { const attachSticky = (el) => {
const sticky = new StickySidebar(widgetsEl); const sticky = new StickySidebar(widgetsEl);
window.addEventListener('scroll', () => { window.addEventListener('scroll', () => {