diff --git a/CHANGELOG.md b/CHANGELOG.md index 2951a46c836097bdf43b56be7743dc35cdb3d929..540726ae7d74ee4a528defba5d0e103d929c2133 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ - Enhance: ノート検索ã«ãƒãƒ¼ã‚«ãƒ«ã®ã¿æ¤œç´¢å¯èƒ½ãªã‚ªãƒ—ションã®è¿½åŠ - Enhance: AiScriptã§`LOCALE`ã¨ã—ã¦ç¾åœ¨ã®è¨å®šè¨€èªžã‚’å–å¾—ã§ãるよã†ã« - Enhance: Renoteè‡ªä½“ã‚’é€šå ±ã§ãるよã†ã« +- Enhance: データセーãƒãƒ¼ãƒ¢ãƒ¼ãƒ‰ã®å¼·åŒ– - Enhance: Renoteを管ç†è€…権é™ã§å‰Šé™¤å¯èƒ½ã« - `$[rainbow ]`記法ãŒã€å‹•ãã®ã‚ã‚‹MFMãŒç„¡åŠ¹ã«ãªã£ã¦ã„ã¦ã‚‚使用ã§ãるよã†ã«ãªã‚Šã¾ã—㟠- Playã®æ“作を行ã†API Tokenã‚’APIコンソールã‹ã‚‰ç™ºè¡Œã§ãるよã†ã« diff --git a/packages/frontend/src/components/MkMediaImage.vue b/packages/frontend/src/components/MkMediaImage.vue index edfd6a72e8ea0e6a50672a3d271bafb06e142d48..fbdf8777cc37782902dcd9c3ef9db85609c9eefb 100644 --- a/packages/frontend/src/components/MkMediaImage.vue +++ b/packages/frontend/src/components/MkMediaImage.vue @@ -4,34 +4,41 @@ SPDX-License-Identifier: AGPL-3.0-only --> <template> -<div :class="hide ? $style.hidden : $style.visible" :style="darkMode ? '--c: rgb(255 255 255 / 2%);' : '--c: rgb(0 0 0 / 2%);'" @click="onclick"> - <a - :class="$style.imageContainer" - :href="image.url" - :title="image.name" +<div :class="hide ? $style.hidden : $style.visible" :style="darkMode ? '--c: rgb(255 255 255 / 2%);' : '--c: rgb(0 0 0 / 2%);'" @click.stop="onclick"> + <component + :is="disableImageLink ? 'div' : 'a'" + v-bind="disableImageLink ? { + title: image.name, + class: $style.imageContainer, + } : { + title: image.name, + class: $style.imageContainer, + href: image.url, + style: 'cursor: zoom-in;' + }" > <ImgWithBlurhash :hash="image.blurhash" :src="(defaultStore.state.enableDataSaverMode && hide) ? null : url" :forceBlurhash="hide" - :cover="hide" + :cover="hide || cover" :alt="image.comment || image.name" :title="image.comment || image.name" :width="image.properties.width" :height="image.properties.height" :style="hide ? 'filter: brightness(0.5);' : null" /> - </a> + </component> <template v-if="hide"> <div :class="$style.hiddenText"> <div :class="$style.hiddenTextWrapper"> <b v-if="image.isSensitive" style="display: block;"><i class="ti ti-eye-exclamation"></i> {{ i18n.ts.sensitive }}{{ defaultStore.state.enableDataSaverMode ? ` (${i18n.ts.image}${image.size ? ' ' + bytes(image.size) : ''})` : '' }}</b> <b v-else style="display: block;"><i class="ti ti-photo"></i> {{ defaultStore.state.enableDataSaverMode && image.size ? bytes(image.size) : i18n.ts.image }}</b> - <span style="display: block;">{{ i18n.ts.clickToShow }}</span> + <span v-if="controls" style="display: block;">{{ i18n.ts.clickToShow }}</span> </div> </div> </template> - <template v-else> + <template v-else-if="controls"> <div :class="$style.indicators"> <div v-if="['image/gif', 'image/apng'].includes(image.type)" :class="$style.indicator">GIF</div> <div v-if="image.comment" :class="$style.indicator">ALT</div> @@ -54,10 +61,17 @@ import { i18n } from '@/i18n'; import * as os from '@/os'; import { iAmModerator } from '@/account'; -const props = defineProps<{ +const props = withDefaults(defineProps<{ image: Misskey.entities.DriveFile; raw?: boolean; -}>(); + cover?: boolean; + disableImageLink?: boolean; + controls?: boolean; +}>(), { + cover: false, + disableImageLink: false, + controls: true, +}); let hide = $ref(true); let darkMode: boolean = $ref(defaultStore.state.darkMode); @@ -70,6 +84,9 @@ const url = $computed(() => (props.raw || defaultStore.state.loadRawImages) ); function onclick() { + if (!props.controls) { + return; + } if (hide) { hide = false; } @@ -167,7 +184,6 @@ function showMenu(ev: MouseEvent) { .imageContainer { display: block; - cursor: zoom-in; overflow: hidden; width: 100%; height: 100%; diff --git a/packages/frontend/src/components/MkPagePreview.vue b/packages/frontend/src/components/MkPagePreview.vue index 53920da50dd0cb7ff3a2b98739c84d8ea6f78ee0..65464956be667b5d0dc0548c83fe21d15aa8ac08 100644 --- a/packages/frontend/src/components/MkPagePreview.vue +++ b/packages/frontend/src/components/MkPagePreview.vue @@ -5,7 +5,15 @@ SPDX-License-Identifier: AGPL-3.0-only <template> <MkA :to="`/@${page.user.username}/pages/${page.name}`" class="vhpxefrj" tabindex="-1"> - <div v-if="page.eyeCatchingImage" class="thumbnail" :style="`background-image: url('${page.eyeCatchingImage.thumbnailUrl}')`"></div> + <div v-if="page.eyeCatchingImage" class="thumbnail"> + <MediaImage + :image="page.eyeCatchingImage" + :disableImageLink="true" + :controls="false" + :cover="true" + :class="$style.eyeCatchingImageRoot" + /> + </div> <article> <header> <h1 :title="page.title">{{ page.title }}</h1> @@ -23,12 +31,22 @@ SPDX-License-Identifier: AGPL-3.0-only import { } from 'vue'; import * as Misskey from 'misskey-js'; import { userName } from '@/filters/user'; +import MediaImage from '@/components/MkMediaImage.vue'; const props = defineProps<{ page: Misskey.entities.Page; }>(); </script> +<style module> +.eyeCatchingImageRoot { + width: 100%; + height: 200px; + border-radius: var(--radius) var(--radius) 0 0; + overflow: hidden; +} +</style> + <style lang="scss" scoped> .vhpxefrj { display: block; @@ -39,32 +57,15 @@ const props = defineProps<{ } > .thumbnail { - width: 100%; - height: 200px; - background-position: center; - background-size: cover; - display: flex; - justify-content: center; - align-items: center; - - > button { - font-size: 3.5em; - opacity: 0.7; - - &:hover { - font-size: 4em; - opacity: 0.9; - } - } - & + article { - left: 100px; - width: calc(100% - 100px); + border-radius: 0 0 var(--radius) var(--radius); } } > article { + background-color: var(--panel); padding: 16px; + border-radius: var(--radius); > header { margin-bottom: 8px; diff --git a/packages/frontend/src/components/MkUrlPreview.vue b/packages/frontend/src/components/MkUrlPreview.vue index bac7f1e3100b58df54c529fdf42b79cc9f403205..77c62ae0b9df29a99803dc8117683fc4956f3f9e 100644 --- a/packages/frontend/src/components/MkUrlPreview.vue +++ b/packages/frontend/src/components/MkUrlPreview.vue @@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only </template> <div v-else> <component :is="self ? 'MkA' : 'a'" :class="[$style.link, { [$style.compact]: compact }]" :[attr]="self ? url.substring(local.length) : url" rel="nofollow noopener" :target="target" :title="url"> - <div v-if="thumbnail" :class="$style.thumbnail" :style="`background-image: url('${thumbnail}')`"> + <div v-if="thumbnail" :class="$style.thumbnail" :style="defaultStore.state.enableDataSaverMode ? '' : `background-image: url('${thumbnail}')`"> </div> <article :class="$style.body"> <header :class="$style.header"> @@ -260,6 +260,7 @@ onUnmounted(() => { height: 100%; background-position: center; background-size: cover; + background-color: var(--bg); display: flex; justify-content: center; align-items: center; diff --git a/packages/frontend/src/components/page/page.image.vue b/packages/frontend/src/components/page/page.image.vue index 3d6417145156c4264bc8978877706bc7109610b3..80a75f02a58928681d3e35162918aa0ab65be70e 100644 --- a/packages/frontend/src/components/page/page.image.vue +++ b/packages/frontend/src/components/page/page.image.vue @@ -5,20 +5,24 @@ SPDX-License-Identifier: AGPL-3.0-only <template> <div> - <ImgWithBlurhash v-if="image" style="max-width: 100%;" :hash="image.blurhash" :src="image.url" :alt="image.comment" :title="image.comment" :width="image.properties.width" :height="image.properties.height" :cover="false"/> + <MediaImage + v-if="image" + :image="image" + :disableImageLink="true" + /> </div> </template> <script lang="ts" setup> -import { } from 'vue'; +import { ref } from 'vue'; import * as Misskey from 'misskey-js'; import { ImageBlock } from './block.type'; -import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue'; +import MediaImage from '@/components/MkMediaImage.vue'; const props = defineProps<{ block: ImageBlock, page: Misskey.entities.Page, }>(); -const image = props.page.attachedFiles.find(x => x.id === props.block.fileId); +const image = ref<Misskey.entities.DriveFile>(props.page.attachedFiles.find(x => x.id === props.block.fileId)); </script> diff --git a/packages/frontend/src/components/page/page.vue b/packages/frontend/src/components/page/page.vue index 265ee7146d8d3571eaf47e49b6c2459b19fd40ce..ab37ca69ad30ab3b41f695d6f0defefbe15b4306 100644 --- a/packages/frontend/src/components/page/page.vue +++ b/packages/frontend/src/components/page/page.vue @@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only --> <template> -<div :class="{ [$style.center]: page.alignCenter, [$style.serif]: page.font === 'serif' }"> +<div :class="{ [$style.center]: page.alignCenter, [$style.serif]: page.font === 'serif' }" class="_gaps_s"> <XBlock v-for="child in page.content" :key="child.id" :page="page" :block="child" :h="2"/> </div> </template> diff --git a/packages/frontend/src/pages/page.vue b/packages/frontend/src/pages/page.vue index efd63bafcec287ef6d54fe8b9fedf27492fd2ec6..c20bbb4793cc9f645af4605e1c0c744924ef9187 100644 --- a/packages/frontend/src/pages/page.vue +++ b/packages/frontend/src/pages/page.vue @@ -16,7 +16,13 @@ SPDX-License-Identifier: AGPL-3.0-only </div> --> <div class="banner"> - <img v-if="page.eyeCatchingImageId" :src="page.eyeCatchingImage.url"/> + <MkMediaImage + v-if="page.eyeCatchingImageId" + :image="page.eyeCatchingImage" + :cover="true" + :disableImageLink="true" + class="thumbnail" + /> </div> <div class="content"> <XPage :page="page"/> @@ -74,6 +80,7 @@ import XPage from '@/components/page/page.vue'; import MkButton from '@/components/MkButton.vue'; import * as os from '@/os'; import { url } from '@/config'; +import MkMediaImage from '@/components/MkMediaImage.vue'; import MkFollowButton from '@/components/MkFollowButton.vue'; import MkContainer from '@/components/MkContainer.vue'; import MkPagination from '@/components/MkPagination.vue'; @@ -204,11 +211,14 @@ definePageMetadata(computed(() => page ? { } > .banner { - > img { + > .thumbnail { // TODO: 良ã„æ„Ÿã˜ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆæ¯”ã§è¡¨ç¤º display: block; width: 100%; - height: 150px; + height: auto; + aspect-ratio: 3/1; + border-radius: var(--radius); + overflow: hidden; object-fit: cover; } }