summaryrefslogtreecommitdiff
path: root/packages/frontend/src
diff options
context:
space:
mode:
authorsyuilo <4439005+syuilo@users.noreply.github.com>2025-03-16 10:58:06 +0900
committersyuilo <4439005+syuilo@users.noreply.github.com>2025-03-16 10:58:06 +0900
commitc2940fd77cba7b0cf912db9fda92e66dbce9110f (patch)
tree1ac1df00c5ea467af720e2c96bf3517d4d1d59b3 /packages/frontend/src
parentrefactor (diff)
downloadsharkey-c2940fd77cba7b0cf912db9fda92e66dbce9110f.tar.gz
sharkey-c2940fd77cba7b0cf912db9fda92e66dbce9110f.tar.bz2
sharkey-c2940fd77cba7b0cf912db9fda92e66dbce9110f.zip
enhance(frontend): improve usability on touch device
Diffstat (limited to 'packages/frontend/src')
-rw-r--r--packages/frontend/src/boot/common.ts4
-rw-r--r--packages/frontend/src/components/MkDialog.vue4
-rw-r--r--packages/frontend/src/components/MkInfo.vue2
-rw-r--r--packages/frontend/src/components/MkInput.vue8
-rw-r--r--packages/frontend/src/components/MkInviteCode.vue2
-rw-r--r--packages/frontend/src/components/MkKeyValue.vue2
-rw-r--r--packages/frontend/src/components/MkNote.vue3
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue3
-rw-r--r--packages/frontend/src/components/MkTextarea.vue4
-rw-r--r--packages/frontend/src/pages/settings/accessibility.vue11
-rw-r--r--packages/frontend/src/preferences/def.ts3
-rw-r--r--packages/frontend/src/style.scss17
-rw-r--r--packages/frontend/src/utility/autogen/settings-search-index.ts13
13 files changed, 59 insertions, 17 deletions
diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts
index 73c4256c4b..10bcddbde7 100644
--- a/packages/frontend/src/boot/common.ts
+++ b/packages/frontend/src/boot/common.ts
@@ -234,6 +234,10 @@ export async function common(createVue: () => App<Element>) {
});
}
+ if (prefer.s.makeEveryTextElementsSelectable) {
+ document.documentElement.classList.add('forceSelectableAll');
+ }
+
//#region Fetch user
if ($i && $i.token) {
if (_DEV_) {
diff --git a/packages/frontend/src/components/MkDialog.vue b/packages/frontend/src/components/MkDialog.vue
index 6c9fa3167a..312c7ab58f 100644
--- a/packages/frontend/src/components/MkDialog.vue
+++ b/packages/frontend/src/components/MkDialog.vue
@@ -25,8 +25,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<i v-else-if="type === 'question'" :class="$style.iconInner" class="ti ti-help-circle"></i>
<MkLoading v-else-if="type === 'waiting'" :class="$style.iconInner" :em="true"/>
</div>
- <header v-if="title" :class="$style.title"><Mfm :text="title"/></header>
- <div v-if="text" :class="$style.text"><Mfm :text="text"/></div>
+ <header v-if="title" :class="$style.title" class="_selectable"><Mfm :text="title"/></header>
+ <div v-if="text" :class="$style.text" class="_selectable"><Mfm :text="text"/></div>
<MkInput v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder || undefined" :autocomplete="input.autocomplete" @keydown="onInputKeydown">
<template v-if="input.type === 'password'" #prefix><i class="ti ti-lock"></i></template>
<template #caption>
diff --git a/packages/frontend/src/components/MkInfo.vue b/packages/frontend/src/components/MkInfo.vue
index 90ca1b5a9d..f114ec8a71 100644
--- a/packages/frontend/src/components/MkInfo.vue
+++ b/packages/frontend/src/components/MkInfo.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div :class="[$style.root, { [$style.warn]: warn }]">
+<div :class="[$style.root, { [$style.warn]: warn }]" class="_selectable">
<i v-if="warn" class="ti ti-alert-triangle" :class="$style.i"></i>
<i v-else class="ti ti-info-circle" :class="$style.i"></i>
<div><slot></slot></div>
diff --git a/packages/frontend/src/components/MkInput.vue b/packages/frontend/src/components/MkInput.vue
index aff9a67020..a66e64311a 100644
--- a/packages/frontend/src/components/MkInput.vue
+++ b/packages/frontend/src/components/MkInput.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div>
+<div class="_selectable">
<div :class="$style.label" @click="focus"><slot name="label"></slot></div>
<div :class="[$style.input, { [$style.inline]: inline, [$style.disabled]: disabled, [$style.focused]: focused }]">
<div ref="prefixEl" :class="$style.prefix"><slot name="prefix"></slot></div>
@@ -45,13 +45,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { onMounted, onUnmounted, nextTick, ref, shallowRef, watch, computed, toRefs } from 'vue';
-import type { InputHTMLAttributes } from 'vue';
import { debounce } from 'throttle-debounce';
-import MkButton from '@/components/MkButton.vue';
import { useInterval } from '@@/js/use-interval.js';
+import type { InputHTMLAttributes } from 'vue';
+import type { SuggestionType } from '@/utility/autocomplete.js';
+import MkButton from '@/components/MkButton.vue';
import { i18n } from '@/i18n.js';
import { Autocomplete } from '@/utility/autocomplete.js';
-import type { SuggestionType } from '@/utility/autocomplete.js';
const props = defineProps<{
modelValue: string | number | null;
diff --git a/packages/frontend/src/components/MkInviteCode.vue b/packages/frontend/src/components/MkInviteCode.vue
index 08eddfc03c..0f53d1573d 100644
--- a/packages/frontend/src/components/MkInviteCode.vue
+++ b/packages/frontend/src/components/MkInviteCode.vue
@@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.items">
<div>
<div :class="$style.label">{{ i18n.ts.invitationCode }}</div>
- <div>{{ invite.code }}</div>
+ <div class="_selectableAtomic">{{ invite.code }}</div>
</div>
<div v-if="moderator">
<div :class="$style.label">{{ i18n.ts.inviteCodeCreator }}</div>
diff --git a/packages/frontend/src/components/MkKeyValue.vue b/packages/frontend/src/components/MkKeyValue.vue
index 6a4b298523..275b153e4a 100644
--- a/packages/frontend/src/components/MkKeyValue.vue
+++ b/packages/frontend/src/components/MkKeyValue.vue
@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.key">
<slot name="key"></slot>
</div>
- <div :class="$style.value">
+ <div :class="$style.value" class="_selectable">
<slot name="value"></slot>
<button v-if="copy" v-tooltip="i18n.ts.copy" class="_textButton" style="margin-left: 0.5em;" @click="copy_"><i class="ti ti-copy"></i></button>
</div>
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index e08f5e6163..1f18b173a0 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -76,12 +76,13 @@ SPDX-License-Identifier: AGPL-3.0-only
:emojiUrls="appearNote.emojis"
:enableEmojiMenu="true"
:enableEmojiMenuReaction="true"
+ class="_selectable"
/>
<div v-if="translating || translation" :class="$style.translation">
<MkLoading v-if="translating" mini/>
<div v-else-if="translation">
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
- <Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis"/>
+ <Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis" class="_selectable"/>
</div>
</div>
</div>
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index dd8d3567b2..6af8acb2df 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -97,13 +97,14 @@ SPDX-License-Identifier: AGPL-3.0-only
:emojiUrls="appearNote.emojis"
:enableEmojiMenu="true"
:enableEmojiMenuReaction="true"
+ class="_selectable"
/>
<a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
<div v-if="translating || translation" :class="$style.translation">
<MkLoading v-if="translating" mini/>
<div v-else-if="translation">
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
- <Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis"/>
+ <Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis" class="_selectable"/>
</div>
</div>
<div v-if="appearNote.files && appearNote.files.length > 0">
diff --git a/packages/frontend/src/components/MkTextarea.vue b/packages/frontend/src/components/MkTextarea.vue
index eb47a8b858..c9da226734 100644
--- a/packages/frontend/src/components/MkTextarea.vue
+++ b/packages/frontend/src/components/MkTextarea.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div>
+<div class="_selectable">
<div :class="$style.label" @click="focus"><slot name="label"></slot></div>
<div :class="{ [$style.disabled]: disabled, [$style.focused]: focused, [$style.tall]: tall, [$style.pre]: pre }" style="position: relative;">
<textarea
@@ -38,10 +38,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs, shallowRef } from 'vue';
import { debounce } from 'throttle-debounce';
+import type { SuggestionType } from '@/utility/autocomplete.js';
import MkButton from '@/components/MkButton.vue';
import { i18n } from '@/i18n.js';
import { Autocomplete } from '@/utility/autocomplete.js';
-import type { SuggestionType } from '@/utility/autocomplete.js';
const props = defineProps<{
modelValue: string | null;
diff --git a/packages/frontend/src/pages/settings/accessibility.vue b/packages/frontend/src/pages/settings/accessibility.vue
index f7b1e7d2a0..e8268719f5 100644
--- a/packages/frontend/src/pages/settings/accessibility.vue
+++ b/packages/frontend/src/pages/settings/accessibility.vue
@@ -58,6 +58,15 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkSwitch>
</MkPreferenceContainer>
</SearchMarker>
+
+ <SearchMarker :keywords="['text', 'selectable']">
+ <MkPreferenceContainer k="makeEveryTextElementsSelectable">
+ <MkSwitch v-model="makeEveryTextElementsSelectable">
+ <template #label><SearchLabel>{{ i18n.ts._settings.makeEveryTextElementsSelectable }}</SearchLabel></template>
+ <template #caption>{{ i18n.ts._settings.makeEveryTextElementsSelectable_description }}</template>
+ </MkSwitch>
+ </MkPreferenceContainer>
+ </SearchMarker>
</div>
<SearchMarker :keywords="['menu', 'style', 'popup', 'drawer']">
@@ -122,6 +131,7 @@ const enableHorizontalSwipe = prefer.model('enableHorizontalSwipe');
const useNativeUiForVideoAudioPlayer = prefer.model('useNativeUiForVideoAudioPlayer');
const contextMenu = prefer.model('contextMenu');
const menuStyle = prefer.model('menuStyle');
+const makeEveryTextElementsSelectable = prefer.model('makeEveryTextElementsSelectable');
const fontSize = ref(miLocalStorage.getItem('fontSize'));
const useSystemFont = ref(miLocalStorage.getItem('useSystemFont') != null);
@@ -147,6 +157,7 @@ watch([
contextMenu,
fontSize,
useSystemFont,
+ makeEveryTextElementsSelectable,
], async () => {
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
});
diff --git a/packages/frontend/src/preferences/def.ts b/packages/frontend/src/preferences/def.ts
index e460359acd..048392ef49 100644
--- a/packages/frontend/src/preferences/def.ts
+++ b/packages/frontend/src/preferences/def.ts
@@ -313,6 +313,9 @@ export const PREF_DEF = {
defaultFollowWithReplies: {
default: false,
},
+ makeEveryTextElementsSelectable: {
+ default: DEFAULT_DEVICE_KIND === 'desktop',
+ },
plugins: {
default: [] as Plugin[],
},
diff --git a/packages/frontend/src/style.scss b/packages/frontend/src/style.scss
index 5308c312bb..43aff3012e 100644
--- a/packages/frontend/src/style.scss
+++ b/packages/frontend/src/style.scss
@@ -81,6 +81,11 @@ html {
&.useSystemFont {
font-family: system-ui;
}
+
+ &:not(.forceSelectableAll) {
+ user-select: none;
+ -webkit-user-select: none;
+ }
}
html._themeChanging_ {
@@ -120,6 +125,8 @@ a {
textarea, input {
tap-highlight-color: transparent;
-webkit-tap-highlight-color: transparent;
+ user-select: text;
+ -webkit-user-select: text;
}
optgroup, option {
@@ -184,6 +191,16 @@ rt {
padding: 0.3em 0.5em;
}
+._selectable {
+ user-select: text;
+ -webkit-user-select: text;
+}
+
+._selectableAtomic {
+ user-select: all;
+ -webkit-user-select: all;
+}
+
._noSelect {
user-select: none;
-webkit-user-select: none;
diff --git a/packages/frontend/src/utility/autogen/settings-search-index.ts b/packages/frontend/src/utility/autogen/settings-search-index.ts
index ab26d671a2..2a0a4c1857 100644
--- a/packages/frontend/src/utility/autogen/settings-search-index.ts
+++ b/packages/frontend/src/utility/autogen/settings-search-index.ts
@@ -897,22 +897,27 @@ export const searchIndexes: SearchIndexItem[] = [
keywords: ['native', 'system', 'video', 'audio', 'player', 'media'],
},
{
- id: '1fV9WINCQ',
+ id: 'b1GYEEJeh',
+ label: i18n.ts._settings.makeEveryTextElementsSelectable,
+ keywords: ['text', 'selectable'],
+ },
+ {
+ id: 'vVLxwINTJ',
label: i18n.ts.menuStyle,
keywords: ['menu', 'style', 'popup', 'drawer'],
},
{
- id: 'mLQzlKUNu',
+ id: '14cMhMLHL',
label: i18n.ts._contextMenu.title,
keywords: ['contextmenu', 'system', 'native'],
},
{
- id: 'yP96aA3j9',
+ id: 'oSo4LXMX9',
label: i18n.ts.fontSize,
keywords: ['font', 'size'],
},
{
- id: 'jQeiMopFE',
+ id: '7LQSAThST',
label: i18n.ts.useSystemFont,
keywords: ['font', 'system', 'native'],
},