diff --git a/packages/frontend/src/directives/flip-on-device-orientation.ts b/packages/frontend/src/directives/flip-on-device-orientation.ts index 767d42a480..234ba93c1d 100644 --- a/packages/frontend/src/directives/flip-on-device-orientation.ts +++ b/packages/frontend/src/directives/flip-on-device-orientation.ts @@ -2,19 +2,21 @@ import type { Directive } from 'vue'; let initialized = false; let styleEl: HTMLStyleElement | null = null; -const elements = new Set(); +const canUseDeviceOrientation = !window.DeviceOrientationEvent; const className = '_flipOnDeviceOrientation'; -const variableName = `--flip_on_device_orientation_transform`; +const variableName = `--MI-flip_on_device_orientation_transform`; -function handleOrientationChange() { - const isUpsideDown = window.screen.orientation.type === 'landscape-secondary'; +function handleOrientationChange(event: DeviceOrientationEvent) { + const isUpsideDown = event.beta ? event.beta < -15 : false; const transform = isUpsideDown ? 'scale(-1, -1)' : ''; window.document.body.style.setProperty(variableName, transform); } function registerListener() { + if (!canUseDeviceOrientation) return; + if (!initialized) { - screen.orientation.addEventListener('change', handleOrientationChange); + window.addEventListener('deviceorientation', handleOrientationChange); if (!styleEl) { styleEl = window.document.createElement('style'); styleEl.textContent = `.${className} { transform: var(${variableName}); }`; @@ -22,7 +24,7 @@ function registerListener() { } initialized = true; } else if (window.document.getElementsByClassName(className).length === 0) { - screen.orientation.removeEventListener('change', handleOrientationChange); + window.removeEventListener('deviceorientation', handleOrientationChange); if (styleEl) { window.document.head.removeChild(styleEl); styleEl = null; @@ -35,7 +37,6 @@ export default { mounted(el) { registerListener(); el.classList.add(className); - handleOrientationChange(); }, unmounted(el) { el.classList.remove(className); diff --git a/packages/frontend/src/pages/qr.show.vue b/packages/frontend/src/pages/qr.show.vue index 94874717d9..26e0b71b15 100644 --- a/packages/frontend/src/pages/qr.show.vue +++ b/packages/frontend/src/pages/qr.show.vue @@ -42,6 +42,8 @@ import { ensureSignin } from '@/i.js'; import { userPage, userName } from '@/filters/user.js'; import misskeysvg from '/client-assets/misskey.svg'; import MkAnimBg from '@/components/MkAnimBg.vue'; +import { getStaticImageUrl } from '@/utility/media-proxy.js'; +import { i18n } from '@/i18n.js'; const $i = ensureSignin(); @@ -62,7 +64,8 @@ const avatarHsl = computed(() => avatarColor.value.toHsl()); const bgColor = tinycolor(`hsl(${avatarHsl.value.h}, 60, 46)`).toRgbString(); function share() { - return navigator.share?.({ + if (!canShare.value) return; + return navigator.share({ title: i18n.tsx._qr.shareTitle({ name: userName($i), acct: acct.value }), text: i18n.tsx._qr.shareText({ name: userName($i), acct: acct.value }), url: url.value, @@ -76,7 +79,7 @@ watch([qrCodeEl, avatarHsl, url], () => { margin: 40, type: 'canvas', data: url.value, - image: instance.iconUrl ?? '/favicon.ico', + image: instance.iconUrl ? getStaticImageUrl(instance.iconUrl) : '/favicon.ico', qrOptions: { typeNumber: 0, mode: 'Byte', @@ -142,7 +145,7 @@ watch([qrCodeEl, avatarHsl, url], () => { .qrInner { width: 100%; max-height: 40dvh; - margin: 5dvh auto 2dvh; + margin: 58px auto 32px; > svg, > canvas { @@ -156,10 +159,10 @@ $avatarSize: 58px; .user { display: flex; - margin: 2dvh auto; + margin: 32px auto; justify-content: center; align-items: center; - overflow: clip; + overflow: visible; width: fit-content; max-width: 100%; } @@ -178,7 +181,8 @@ $avatarSize: 58px; align-items: start; margin-top: -4px; max-width: 100%; - overflow: hidden; + overflow-x: hidden; + overflow-y: visible; } .name { @@ -188,7 +192,8 @@ $avatarSize: 58px; line-height: 24px; width: fit-content; max-width: calc(100% - 16px); - overflow: hidden; + overflow-x: hidden; + overflow-y: visible; padding-right: 16px; mask-image: linear-gradient(90deg,#000,#000 calc(100% - 16px),#0000); } @@ -200,13 +205,14 @@ $avatarSize: 58px; line-height: 16px; width: fit-content; max-width: calc(100% - 16px); - overflow: hidden; + overflow-x: hidden; + overflow-y: visible; padding-right: 16px; mask-image: linear-gradient(90deg,#000,#000 calc(100% - 16px),#0000); } .logo { width: 30%; - margin: 2dvh auto 0; + margin: 32px auto 0; } diff --git a/packages/frontend/src/pages/qr.vue b/packages/frontend/src/pages/qr.vue index 123534ac2b..3db767f494 100644 --- a/packages/frontend/src/pages/qr.vue +++ b/packages/frontend/src/pages/qr.vue @@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only -->