summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorおさむのひと <46447427+samunohito@users.noreply.github.com>2023-11-30 08:15:13 +0900
committerGitHub <noreply@github.com>2023-11-30 08:15:13 +0900
commit413f7bfb44e885c82ba49fc098b620831830d0c5 (patch)
tree00b51ac3e8eaf26fac3eea24aa8f2f204aae7b6e
parentenhance(frontend): Shareページでの投稿完了時にpostMessageを発火... (diff)
downloadsharkey-413f7bfb44e885c82ba49fc098b620831830d0c5.tar.gz
sharkey-413f7bfb44e885c82ba49fc098b620831830d0c5.tar.bz2
sharkey-413f7bfb44e885c82ba49fc098b620831830d0c5.zip
Fix: navigator.share未サポートの場合は共有ボタンを非表示にする(+URLのコピーボタンを設置) (#12506)
* navigator.share未サポートの場合は共有ボタンを非表示にする * fix CHANGELOG.md * ライセンス表示追加 * URLのコピーボタンを設置
-rw-r--r--CHANGELOG.md2
-rw-r--r--packages/frontend/src/components/global/MkPageHeader.vue8
-rw-r--r--packages/frontend/src/pages/channel.vue49
-rw-r--r--packages/frontend/src/pages/clip.vue9
-rw-r--r--packages/frontend/src/pages/flash/flash.vue10
-rw-r--r--packages/frontend/src/pages/gallery/post.vue10
-rw-r--r--packages/frontend/src/pages/page.vue10
-rw-r--r--packages/frontend/src/scripts/get-note-menu.ts7
-rw-r--r--packages/frontend/src/scripts/navigator.ts8
-rw-r--r--packages/frontend/src/types/page-header.ts11
10 files changed, 97 insertions, 27 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ed930437e..d2e6702a92 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,11 +26,13 @@
- Enhance: リアクション選択時に音を鳴らせるように
- Enhance: サウンドにドライブのファイルを使用できるように
- Enhance: Shareページで投稿を完了すると、親ウィンドウ(親フレーム)にpostMessageするように
+- Enhance: チャンネル、クリップ、ページ、Play、ギャラリーにURLのコピーボタンを設置 #11305
- fix: 「設定のバックアップ」で一部の項目がバックアップに含まれていなかった問題を修正
- Fix: ウィジェットのジョブキューにて音声の発音方法変更に追従できていなかったのを修正 #12367
- Fix: コードエディタが正しく表示されない問題を修正
- Fix: プロフィールの「ファイル」にセンシティブな画像がある際のデザインを修正
- Fix: 一度に大量の通知が入った際に通知音が音割れする問題を修正
+- Fix: 共有機能をサポートしていないブラウザの場合は共有ボタンを非表示にする #11305
- Fix: 通知のグルーピング設定を変更してもリロードされるまで表示が変わらない問題を修正 #12470
### Server
diff --git a/packages/frontend/src/components/global/MkPageHeader.vue b/packages/frontend/src/components/global/MkPageHeader.vue
index 580816abaa..935ca33eb5 100644
--- a/packages/frontend/src/components/global/MkPageHeader.vue
+++ b/packages/frontend/src/components/global/MkPageHeader.vue
@@ -48,16 +48,12 @@ import { scrollToTop } from '@/scripts/scroll.js';
import { globalEvents } from '@/events.js';
import { injectPageMetadata } from '@/scripts/page-metadata.js';
import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js';
+import { PageHeaderItem } from '@/types/page-header.js';
const props = withDefaults(defineProps<{
tabs?: Tab[];
tab?: string;
- actions?: {
- text: string;
- icon: string;
- highlighted?: boolean;
- handler: (ev: MouseEvent) => void;
- }[];
+ actions?: PageHeaderItem[];
thin?: boolean;
displayMyAvatar?: boolean;
}>(), {
diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue
index 1d41fe7529..dc374e2925 100644
--- a/packages/frontend/src/pages/channel.vue
+++ b/packages/frontend/src/pages/channel.vue
@@ -86,6 +86,9 @@ import { defaultStore } from '@/store.js';
import MkNote from '@/components/MkNote.vue';
import MkInfo from '@/components/MkInfo.vue';
import MkFoldableSection from '@/components/MkFoldableSection.vue';
+import { PageHeaderItem } from '@/types/page-header.js';
+import { isSupportShare } from '@/scripts/navigator.js';
+import copyToClipboard from '@/scripts/copy-to-clipboard.js';
const router = useRouter();
@@ -167,24 +170,40 @@ async function search() {
const headerActions = $computed(() => {
if (channel && channel.userId) {
- const share = {
- icon: 'ti ti-share',
- text: i18n.ts.share,
+ const headerItems: PageHeaderItem[] = [];
+
+ headerItems.push({
+ icon: 'ti ti-link',
+ text: i18n.ts.copyUrl,
handler: async (): Promise<void> => {
- navigator.share({
- title: channel.name,
- text: channel.description,
- url: `${url}/channels/${channel.id}`,
- });
+ copyToClipboard(`${url}/channels/${channel.id}`);
+ os.success();
},
- };
+ });
+
+ if (isSupportShare()) {
+ headerItems.push({
+ icon: 'ti ti-share',
+ text: i18n.ts.share,
+ handler: async (): Promise<void> => {
+ navigator.share({
+ title: channel.name,
+ text: channel.description,
+ url: `${url}/channels/${channel.id}`,
+ });
+ },
+ });
+ }
+
+ if (($i && $i.id === channel.userId) || iAmModerator) {
+ headerItems.push({
+ icon: 'ti ti-settings',
+ text: i18n.ts.edit,
+ handler: edit,
+ });
+ }
- const canEdit = ($i && $i.id === channel.userId) || iAmModerator;
- return canEdit ? [share, {
- icon: 'ti ti-settings',
- text: i18n.ts.edit,
- handler: edit,
- }] : [share];
+ return headerItems.length > 0 ? headerItems : null;
} else {
return null;
}
diff --git a/packages/frontend/src/pages/clip.vue b/packages/frontend/src/pages/clip.vue
index 4573bbb81c..b32c8a3864 100644
--- a/packages/frontend/src/pages/clip.vue
+++ b/packages/frontend/src/pages/clip.vue
@@ -36,6 +36,8 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
import { url } from '@/config.js';
import MkButton from '@/components/MkButton.vue';
import { clipsCache } from '@/cache';
+import { isSupportShare } from '@/scripts/navigator.js';
+import copyToClipboard from '@/scripts/copy-to-clipboard.js';
const props = defineProps<{
clipId: string,
@@ -118,6 +120,13 @@ const headerActions = $computed(() => clip && isOwned ? [{
clipsCache.delete();
},
}, ...(clip.isPublic ? [{
+ icon: 'ti ti-link',
+ text: i18n.ts.copyUrl,
+ handler: async (): Promise<void> => {
+ copyToClipboard(`${url}/clips/${clip.id}`);
+ os.success();
+ },
+}] : []), ...(clip.isPublic && isSupportShare() ? [{
icon: 'ti ti-share',
text: i18n.ts.share,
handler: async (): Promise<void> => {
diff --git a/packages/frontend/src/pages/flash/flash.vue b/packages/frontend/src/pages/flash/flash.vue
index ebf117ffbf..4755eb5062 100644
--- a/packages/frontend/src/pages/flash/flash.vue
+++ b/packages/frontend/src/pages/flash/flash.vue
@@ -18,7 +18,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton v-if="flash.isLiked" v-tooltip="i18n.ts.unlike" asLike class="button" rounded primary @click="unlike()"><i class="ti ti-heart"></i><span v-if="flash.likedCount > 0" style="margin-left: 6px;">{{ flash.likedCount }}</span></MkButton>
<MkButton v-else v-tooltip="i18n.ts.like" asLike class="button" rounded @click="like()"><i class="ti ti-heart"></i><span v-if="flash.likedCount > 0" style="margin-left: 6px;">{{ flash.likedCount }}</span></MkButton>
<MkButton v-tooltip="i18n.ts.shareWithNote" class="button" rounded @click="shareWithNote"><i class="ti ti-repeat ti-fw"></i></MkButton>
- <MkButton v-tooltip="i18n.ts.share" class="button" rounded @click="share"><i class="ti ti-share ti-fw"></i></MkButton>
+ <MkButton v-tooltip="i18n.ts.copyLink" class="button" rounded @click="copyLink"><i class="ti ti-link ti-fw"></i></MkButton>
+ <MkButton v-if="isSupportShare()" v-tooltip="i18n.ts.share" class="button" rounded @click="share"><i class="ti ti-share ti-fw"></i></MkButton>
</div>
</div>
<div v-else :class="$style.ready">
@@ -70,6 +71,8 @@ import MkFolder from '@/components/MkFolder.vue';
import MkCode from '@/components/MkCode.vue';
import { defaultStore } from '@/store.js';
import { $i } from '@/account.js';
+import { isSupportShare } from '@/scripts/navigator.js';
+import copyToClipboard from '@/scripts/copy-to-clipboard.js';
const props = defineProps<{
id: string;
@@ -89,6 +92,11 @@ function fetchFlash() {
});
}
+function copyLink() {
+ copyToClipboard(`${url}/play/${flash.id}`);
+ os.success();
+}
+
function share() {
navigator.share({
title: flash.title,
diff --git a/packages/frontend/src/pages/gallery/post.vue b/packages/frontend/src/pages/gallery/post.vue
index 3863348eae..5b551f75b5 100644
--- a/packages/frontend/src/pages/gallery/post.vue
+++ b/packages/frontend/src/pages/gallery/post.vue
@@ -29,7 +29,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="other">
<button v-if="$i && $i.id === post.user.id" v-tooltip="i18n.ts.edit" v-click-anime class="_button" @click="edit"><i class="ti ti-pencil ti-fw"></i></button>
<button v-tooltip="i18n.ts.shareWithNote" v-click-anime class="_button" @click="shareWithNote"><i class="ti ti-repeat ti-fw"></i></button>
- <button v-tooltip="i18n.ts.share" v-click-anime class="_button" @click="share"><i class="ti ti-share ti-fw"></i></button>
+ <button v-tooltip="i18n.ts.copyLink" v-click-anime class="_button" @click="copyLink"><i class="ti ti-link ti-fw"></i></button>
+ <button v-if="isSupportShare()" v-tooltip="i18n.ts.share" v-click-anime class="_button" @click="share"><i class="ti ti-share ti-fw"></i></button>
</div>
</div>
<div class="user">
@@ -74,6 +75,8 @@ import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import { defaultStore } from '@/store.js';
import { $i } from '@/account.js';
+import { isSupportShare } from '@/scripts/navigator.js';
+import copyToClipboard from '@/scripts/copy-to-clipboard.js';
const router = useRouter();
@@ -102,6 +105,11 @@ function fetchPost() {
});
}
+function copyLink() {
+ copyToClipboard(`${url}/gallery/${post.id}`);
+ os.success();
+}
+
function share() {
navigator.share({
title: post.title,
diff --git a/packages/frontend/src/pages/page.vue b/packages/frontend/src/pages/page.vue
index 98cbaab2bb..2bc053ccfe 100644
--- a/packages/frontend/src/pages/page.vue
+++ b/packages/frontend/src/pages/page.vue
@@ -34,7 +34,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<div class="other">
<button v-tooltip="i18n.ts.shareWithNote" v-click-anime class="_button" @click="shareWithNote"><i class="ti ti-repeat ti-fw"></i></button>
- <button v-tooltip="i18n.ts.share" v-click-anime class="_button" @click="share"><i class="ti ti-share ti-fw"></i></button>
+ <button v-tooltip="i18n.ts.copyLink" v-click-anime class="_button" @click="copyLink"><i class="ti ti-link ti-fw"></i></button>
+ <button v-if="isSupportShare()" v-tooltip="i18n.ts.share" v-click-anime class="_button" @click="share"><i class="ti ti-share ti-fw"></i></button>
</div>
</div>
<div class="user">
@@ -90,6 +91,8 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
import { pageViewInterruptors, defaultStore } from '@/store.js';
import { deepClone } from '@/scripts/clone.js';
import { $i } from '@/account.js';
+import { isSupportShare } from '@/scripts/navigator.js';
+import copyToClipboard from '@/scripts/copy-to-clipboard.js';
const props = defineProps<{
pageName: string;
@@ -136,6 +139,11 @@ function share() {
});
}
+function copyLink() {
+ copyToClipboard(`${url}/@${page.user.username}/pages/${page.name}`);
+ os.success();
+}
+
function shareWithNote() {
os.post({
initialText: `${page.title || page.name} ${url}/@${page.user.username}/pages/${page.name}`,
diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts
index d0753872ff..763f6ff513 100644
--- a/packages/frontend/src/scripts/get-note-menu.ts
+++ b/packages/frontend/src/scripts/get-note-menu.ts
@@ -18,6 +18,7 @@ import { getUserMenu } from '@/scripts/get-user-menu.js';
import { clipsCache } from '@/cache.js';
import { MenuItem } from '@/types/menu.js';
import MkRippleEffect from '@/components/MkRippleEffect.vue';
+import { isSupportShare } from '@/scripts/navigator.js';
export async function getNoteClipMenu(props: {
note: Misskey.entities.Note;
@@ -280,11 +281,11 @@ export function getNoteMenu(props: {
window.open(appearNote.url ?? appearNote.uri, '_blank');
},
} : undefined,
- {
+ ...(isSupportShare() ? [{
icon: 'ti ti-share',
text: i18n.ts.share,
action: share,
- },
+ }] : []),
$i && $i.policies.canUseTranslator && instance.translatorAvailable ? {
icon: 'ti ti-language-hiragana',
text: i18n.ts.translate,
@@ -484,7 +485,7 @@ export function getRenoteMenu(props: {
}]);
}
- if (!appearNote.channel || appearNote.channel?.allowRenoteToExternal) {
+ if (!appearNote.channel || appearNote.channel.allowRenoteToExternal) {
normalRenoteItems.push(...[{
text: i18n.ts.renote,
icon: 'ti ti-repeat',
diff --git a/packages/frontend/src/scripts/navigator.ts b/packages/frontend/src/scripts/navigator.ts
new file mode 100644
index 0000000000..b13186a10e
--- /dev/null
+++ b/packages/frontend/src/scripts/navigator.ts
@@ -0,0 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export function isSupportShare(): boolean {
+ return 'share' in navigator;
+}
diff --git a/packages/frontend/src/types/page-header.ts b/packages/frontend/src/types/page-header.ts
new file mode 100644
index 0000000000..295b97a7fd
--- /dev/null
+++ b/packages/frontend/src/types/page-header.ts
@@ -0,0 +1,11 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export type PageHeaderItem = {
+ text: string;
+ icon: string;
+ highlighted?: boolean;
+ handler: (ev: MouseEvent) => void;
+};