Skip to content

Commit

Permalink
Merge pull request #115 from Sayamame-beans/picks
Browse files Browse the repository at this point in the history
Picks
  • Loading branch information
Sayamame-beans authored Nov 30, 2023
2 parents 9e45adb + 4464ed8 commit be5e0aa
Show file tree
Hide file tree
Showing 17 changed files with 141 additions and 33 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
- Fix: 全体ハイライトでユーザーミュートが正常に機能しない問題

### Client
- Enhance: チャンネル、クリップ、ページ、Play、ギャラリーにURLのコピーボタンを設置 #11305
- Enhance: サウンド設定に「サウンドを出力しない」と「Misskeyがアクティブな時のみサウンドを出力する」を追加
- Fix: 共有機能をサポートしていないブラウザの場合は共有ボタンを非表示にする #11305
- Fix: 通知のグルーピング設定を変更してもリロードされるまで表示が変わらない問題を修正 #12470

### Server
- Fix: includeSensitiveChannelがfunout timelineの範囲では機能しない問題
Expand Down
2 changes: 2 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,8 @@ export interface Locale {
"popout": string;
"volume": string;
"masterVolume": string;
"notUseSound": string;
"useSoundOnlyWhenActive": string;
"details": string;
"chooseEmoji": string;
"unableToProcess": string;
Expand Down
2 changes: 2 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,8 @@ showInPage: "ページで表示"
popout: "ポップアウト"
volume: "音量"
masterVolume: "マスター音量"
notUseSound: "サウンドを出力しない"
useSoundOnlyWhenActive: "Misskeyがアクティブな時のみサウンドを出力する"
details: "詳細"
chooseEmoji: "絵文字を選択"
unableToProcess: "操作を完了できません"
Expand Down
6 changes: 3 additions & 3 deletions packages/frontend/src/components/MkNotifications.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>

<script lang="ts" setup>
import { onUnmounted, onDeactivated, onMounted, computed, shallowRef, onActivated } from 'vue';
import { onUnmounted, onDeactivated, onMounted, computed, shallowRef, onActivated, watch } from 'vue';
import MkPagination, { Paging } from '@/components/MkPagination.vue';
import XNotification from '@/components/MkNotification.vue';
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
Expand All @@ -43,7 +43,7 @@ const props = defineProps<{

const pagingComponent = shallowRef<InstanceType<typeof MkPagination>>();

const pagination: Paging = defaultStore.state.useGroupedNotifications ? {
let pagination = $computed(() => defaultStore.reactiveState.useGroupedNotifications.value ? {
endpoint: 'i/notifications-grouped' as const,
limit: 20,
params: computed(() => ({
Expand All @@ -55,7 +55,7 @@ const pagination: Paging = defaultStore.state.useGroupedNotifications ? {
params: computed(() => ({
excludeTypes: props.excludeTypes ?? undefined,
})),
};
});

function onNotification(notification) {
const isMuted = props.excludeTypes ? props.excludeTypes.includes(notification.type) : false;
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/components/MkPagination.vue
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ watch([$$(backed), $$(contentEl)], () => {
});

// パラメータに何らかの変更があった際、再読込したい(チャンネル等のIDが変わったなど)
watch(() => props.pagination.params, init, { deep: true });
watch(() => [props.pagination.endpoint, props.pagination.params], init, { deep: true });

watch(queue, (a, b) => {
if (a.size === 0 && b.size === 0) return;
Expand Down
8 changes: 2 additions & 6 deletions packages/frontend/src/components/global/MkPageHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}>(), {
Expand Down
51 changes: 35 additions & 16 deletions packages/frontend/src/pages/channel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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();
},
};

const canEdit = ($i && $i.id === channel.userId) || iAmModerator;
return canEdit ? [share, {
icon: 'ti ti-settings',
text: i18n.ts.edit,
handler: edit,
}] : [share];
});

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,
});
}

return headerItems.length > 0 ? headerItems : null;
} else {
return null;
}
Expand Down
9 changes: 9 additions & 0 deletions packages/frontend/src/pages/clip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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> => {
Expand Down
10 changes: 9 additions & 1 deletion packages/frontend/src/pages/flash/flash.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down Expand Up @@ -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;
Expand All @@ -89,6 +92,11 @@ function fetchFlash() {
});
}

function copyLink() {
copyToClipboard(`${url}/play/${flash.id}`);
os.success();
}

function share() {
navigator.share({
title: flash.title,
Expand Down
10 changes: 9 additions & 1 deletion packages/frontend/src/pages/gallery/post.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -102,6 +105,11 @@ function fetchPost() {
});
}

function copyLink() {
copyToClipboard(`${url}/gallery/${post.id}`);
os.success();
}

function share() {
navigator.share({
title: post.title,
Expand Down
10 changes: 9 additions & 1 deletion packages/frontend/src/pages/page.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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}`,
Expand Down
9 changes: 9 additions & 0 deletions packages/frontend/src/pages/settings/sounds.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ SPDX-License-Identifier: AGPL-3.0-only

<template>
<div class="_gaps_m">
<MkSwitch v-model="notUseSound">
<template #label>{{ i18n.ts.notUseSound }}</template>
</MkSwitch>
<MkSwitch v-model="useSoundOnlyWhenActive">
<template #label>{{ i18n.ts.useSoundOnlyWhenActive }}</template>
</MkSwitch>
<MkRange v-model="masterVolume" :min="0" :max="1" :step="0.05" :textConverter="(v) => `${Math.floor(v * 100)}%`">
<template #label>{{ i18n.ts.masterVolume }}</template>
</MkRange>
Expand Down Expand Up @@ -35,7 +41,10 @@ import MkFolder from '@/components/MkFolder.vue';
import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import { defaultStore } from '@/store.js';
import MkSwitch from '@/components/MkSwitch.vue';

const notUseSound = computed(defaultStore.makeGetterSetter('sound_notUseSound'));
const useSoundOnlyWhenActive = computed(defaultStore.makeGetterSetter('sound_useSoundOnlyWhenActive'));
const masterVolume = computed(defaultStore.makeGetterSetter('sound_masterVolume'));

const soundsKeys = ['note', 'noteMy', 'notification', 'antenna', 'channel'] as const;
Expand Down
7 changes: 4 additions & 3 deletions packages/frontend/src/scripts/get-note-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -291,11 +292,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,
Expand Down Expand Up @@ -501,7 +502,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',
Expand Down
8 changes: 8 additions & 0 deletions packages/frontend/src/scripts/navigator.ts
Original file line number Diff line number Diff line change
@@ -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;
}
17 changes: 16 additions & 1 deletion packages/frontend/src/scripts/sound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export async function playFile(file: string, volume: number) {

export function createSourceNode(buffer: AudioBuffer, volume: number) : AudioBufferSourceNode | null {
const masterVolume = defaultStore.state.sound_masterVolume;
if (masterVolume === 0 || volume === 0) {
if (isMute() || masterVolume === 0 || volume === 0) {
return null;
}

Expand All @@ -112,3 +112,18 @@ export function createSourceNode(buffer: AudioBuffer, volume: number) : AudioBuf

return soundSource;
}

export function isMute(): boolean {
if (defaultStore.state.sound_notUseSound) {
// サウンドを出力しない
return true;
}

// noinspection RedundantIfStatementJS
if (defaultStore.state.sound_useSoundOnlyWhenActive && document.visibilityState === 'hidden') {
// ブラウザがアクティブな時のみサウンドを出力する
return true;
}

return false;
}
8 changes: 8 additions & 0 deletions packages/frontend/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,14 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device',
default: 0.3,
},
sound_notUseSound: {
where: 'device',
default: false,
},
sound_useSoundOnlyWhenActive: {
where: 'device',
default: false,
},
sound_note: {
where: 'device',
default: { type: 'syuilo/n-aec', volume: 1 },
Expand Down
11 changes: 11 additions & 0 deletions packages/frontend/src/types/page-header.ts
Original file line number Diff line number Diff line change
@@ -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;
};

0 comments on commit be5e0aa

Please sign in to comment.