From 42b2aea53364c57c39ebb953359ece4b7b0017a5 Mon Sep 17 00:00:00 2001
From: tamaina <tamaina@hotmail.co.jp>
Date: Fri, 19 Sep 2025 21:02:30 +0900
Subject: feat(frontend):
 自分のプロフィールページの二次元コード(QRコード)を表示し、他の人のコードを読み取りするページを追加
 (#16456)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* wip (qr.show.vue)

* added to navbar

* qr.show.vue

* fix

* added to navbar

* fix size

* :art:

* :art:

* fix div warn

* fix

* use * 0.25

* fix??

* fix lint

* clean up

* ???

* ?

* fix

* :art:

* :art:

* refactor

* :art:

* :art:

* :ar:t

* :art:

* iphone flip

* no lazy import

* :art:

* :art:

* :art:

* ユーザー全部flipでいいや

* :v:

* fix

* fix

* fix lint

* :art:

* fix type

* fix: local user profile url cannot be resolved with ap/show

* fix: local user url with hostname could not be resolved

* chore: use common utility for checking self host

* wip

* :art:

* :art:

* fix imports

* fix

* fix

* fix

* :art:

* fix...

* set spacer-w

* :v:

* 全画面でQRを読むように

* fix

* :art:

* modify navbar.ts

* start/stop on vue activation

* display raw content read from qr

* 端末のQRをスキャンするボタンを追加

* chore

* やっぱりmfmを先に表示する

* :art:

* fix 18n

* QRの内容は/users/:userIdにする

* add spdx

* use cqh

* `defineProps` is a compiler macro and no longer needs to be imported.

* use MkUserName

* 🎨

* 🎨

* refactor

* clean up

* refactor

* 🎨

* Update qr.show.vue

* Misskeyロゴにdrop-shadowを追加

* clean up: do not use empty css

* fix os.select usage

* Update qr.vue

* Update qr.show.vue

* Update qr.show.vue

* Update get-user-menu.ts

* ✌️

* Update show.ts

* Update ja-JP.yml

* watermark

* Update CHANGELOG.md

* Update qr.read.vue

* Update qr.read.vue

* wip

* Update MkWatermarkEditorDialog.Layer.vue

---------

Co-authored-by: anatawa12 <anatawa12@icloud.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 .../src/components/MkWatermarkEditorDialog.vue     | 58 ++++++++--------------
 1 file changed, 21 insertions(+), 37 deletions(-)

(limited to 'packages/frontend/src/components/MkWatermarkEditorDialog.vue')

diff --git a/packages/frontend/src/components/MkWatermarkEditorDialog.vue b/packages/frontend/src/components/MkWatermarkEditorDialog.vue
index 75a45548fd..0d0488d9bc 100644
--- a/packages/frontend/src/components/MkWatermarkEditorDialog.vue
+++ b/packages/frontend/src/components/MkWatermarkEditorDialog.vue
@@ -30,22 +30,12 @@ SPDX-License-Identifier: AGPL-3.0-only
 			</div>
 			<div :class="$style.controls">
 				<div class="_spacer _gaps">
-					<MkSelect v-model="type" :items="typeDef">
-						<template #label>{{ i18n.ts._watermarkEditor.type }}</template>
-					</MkSelect>
-
-					<div v-if="type === 'text' || type === 'image'">
-						<XLayer
-							v-for="(layer, i) in preset.layers"
-							:key="layer.id"
-							v-model:layer="preset.layers[i]"
-						></XLayer>
-					</div>
-					<div v-else-if="type === 'advanced'" class="_gaps_s">
+					<div class="_gaps_s">
 						<MkFolder v-for="(layer, i) in preset.layers" :key="layer.id" :defaultOpen="false" :canPage="false">
 							<template #label>
 								<div v-if="layer.type === 'text'">{{ i18n.ts._watermarkEditor.text }}</div>
 								<div v-if="layer.type === 'image'">{{ i18n.ts._watermarkEditor.image }}</div>
+								<div v-if="layer.type === 'qr'">{{ i18n.ts._watermarkEditor.qr }}</div>
 								<div v-if="layer.type === 'stripe'">{{ i18n.ts._watermarkEditor.stripe }}</div>
 								<div v-if="layer.type === 'polkadot'">{{ i18n.ts._watermarkEditor.polkadot }}</div>
 								<div v-if="layer.type === 'checker'">{{ i18n.ts._watermarkEditor.checker }}</div>
@@ -95,7 +85,7 @@ function createTextLayer(): WatermarkPreset['layers'][number] {
 		id: genId(),
 		type: 'text',
 		text: `(c) @${$i.username}`,
-		align: { x: 'right', y: 'bottom' },
+		align: { x: 'right', y: 'bottom', margin: 0 },
 		scale: 0.3,
 		angle: 0,
 		opacity: 0.75,
@@ -109,7 +99,7 @@ function createImageLayer(): WatermarkPreset['layers'][number] {
 		type: 'image',
 		imageId: null,
 		imageUrl: null,
-		align: { x: 'right', y: 'bottom' },
+		align: { x: 'right', y: 'bottom', margin: 0 },
 		scale: 0.3,
 		angle: 0,
 		opacity: 0.75,
@@ -118,6 +108,17 @@ function createImageLayer(): WatermarkPreset['layers'][number] {
 	};
 }
 
+function createQrLayer(): WatermarkPreset['layers'][number] {
+	return {
+		id: genId(),
+		type: 'qr',
+		data: '',
+		align: { x: 'right', y: 'bottom', margin: 0 },
+		scale: 0.3,
+		opacity: 1,
+	};
+}
+
 function createStripeLayer(): WatermarkPreset['layers'][number] {
 	return {
 		id: genId(),
@@ -165,7 +166,7 @@ const props = defineProps<{
 const preset = reactive<WatermarkPreset>(deepClone(props.preset) ?? {
 	id: genId(),
 	name: '',
-	layers: [createTextLayer()],
+	layers: [],
 });
 
 const emit = defineEmits<{
@@ -187,28 +188,6 @@ async function cancel() {
 	dialog.value?.close();
 }
 
-const {
-	model: type,
-	def: typeDef,
-} = useMkSelect({
-	items: [
-		{ label: i18n.ts._watermarkEditor.text, value: 'text' },
-		{ label: i18n.ts._watermarkEditor.image, value: 'image' },
-		{ label: i18n.ts._watermarkEditor.advanced, value: 'advanced' },
-	],
-	initialValue: preset.layers.length > 1 ? 'advanced' : preset.layers[0].type,
-});
-
-watch(type, () => {
-	if (type.value === 'text') {
-		preset.layers = [createTextLayer()];
-	} else if (type.value === 'image') {
-		preset.layers = [createImageLayer()];
-	} else if (type.value === 'advanced') {
-		// nop
-	}
-});
-
 watch(preset, async (newValue, oldValue) => {
 	if (renderer != null) {
 		renderer.setLayers(preset.layers);
@@ -338,6 +317,11 @@ function addLayer(ev: MouseEvent) {
 		action: () => {
 			preset.layers.push(createImageLayer());
 		},
+	}, {
+		text: i18n.ts._watermarkEditor.qr,
+		action: () => {
+			preset.layers.push(createQrLayer());
+		},
 	}, {
 		text: i18n.ts._watermarkEditor.stripe,
 		action: () => {
-- 
cgit v1.2.3-freya

