diff --git a/locales/en-US.yml b/locales/en-US.yml
index f4ff6fac91..0abb78a469 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -1139,6 +1139,7 @@ confirm: "Confirm"
importZip: "Import ZIP"
exportZip: "Export ZIP"
emojiPackCreator: "Emoji pack creator"
+getQrCode: "Get QR code"
_sensitiveMediaDetection:
description: "Reduces the effort of server moderation through automatically recognizing
diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml
index 098c97a409..3e27bcd8a7 100644
--- a/locales/fr-FR.yml
+++ b/locales/fr-FR.yml
@@ -932,6 +932,8 @@ colored: "Coloré"
label: "Étiquette"
localOnly: "Local seulement"
account: "Comptes"
+getQrCode: "Obtenir le code QR"
+
_emailUnavailable:
used: "Non disponible"
format: "Le format de cette adresse de courriel est invalide"
diff --git a/packages/client/package.json b/packages/client/package.json
index 9efe66f4b6..f99771937e 100644
--- a/packages/client/package.json
+++ b/packages/client/package.json
@@ -25,6 +25,7 @@
"@types/katex": "0.16.2",
"@types/matter-js": "0.19.0",
"@types/punycode": "2.1.0",
+ "@types/qrcode": "1.5.1",
"@types/seedrandom": "3.0.5",
"@types/throttle-debounce": "5.0.0",
"@types/tinycolor2": "1.4.3",
@@ -61,14 +62,18 @@
"insert-text-at-cursor": "0.3.0",
"json5": "2.2.3",
"katex": "0.16.8",
+ "long": "^5.2.3",
"matter-js": "0.19.0",
"mfm-js": "0.23.3",
+ "multer": "1.4.4-lts.1",
"paralint": "^1.2.1",
"photoswipe": "5.3.8",
"prettier": "3.0.2",
"prettier-plugin-vue": "1.1.6",
"prismjs": "1.29.0",
"punycode": "2.3.0",
+ "qrcode": "1.5.3",
+ "qrcode-vue3": "^1.6.8",
"rndstr": "1.0.0",
"rollup": "3.28.0",
"s-age": "1.1.2",
diff --git a/packages/client/src/components/FfQrCode.vue b/packages/client/src/components/FfQrCode.vue
new file mode 100644
index 0000000000..9dca107406
--- /dev/null
+++ b/packages/client/src/components/FfQrCode.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
{{
+ i18n.ts.gotIt
+ }}
+
+
+
+
+
+
+
diff --git a/packages/client/src/os.ts b/packages/client/src/os.ts
index d95edd7bf5..2c65477b7c 100644
--- a/packages/client/src/os.ts
+++ b/packages/client/src/os.ts
@@ -9,6 +9,7 @@ import MkPostFormDialog from "@/components/MkPostFormDialog.vue";
import MkWaitingDialog from "@/components/MkWaitingDialog.vue";
import MkToast from "@/components/MkToast.vue";
import MkDialog from "@/components/MkDialog.vue";
+import FfQrCode from "@/components/FfQrCode.vue";
import { MenuItem } from "@/types/menu";
import { $i } from "@/account";
import { i18n } from "./i18n";
@@ -926,6 +927,19 @@ export function post(props: Record = {}) {
});
}
+export async function displayQrCode(qrCode: string) {
+ (await new Promise<(() => void) | undefined>((resolve) => {
+ let dispose: (() => void) | undefined;
+ popup(FfQrCode, { qrCode }, {
+ closed: () => {
+ resolve(dispose);
+ }
+ }).then((res) => {
+ dispose = res.dispose
+ })
+ }))?.();
+}
+
export const deckGlobalEvents = new EventEmitter();
/*
diff --git a/packages/client/src/scripts/get-user-menu.ts b/packages/client/src/scripts/get-user-menu.ts
index 26112379cc..6f9fa26e49 100644
--- a/packages/client/src/scripts/get-user-menu.ts
+++ b/packages/client/src/scripts/get-user-menu.ts
@@ -280,6 +280,13 @@ export function getUserMenu(user, router: Router = mainRouter) {
os.post({ specified: user });
},
},
+ {
+ icon: "ph-qr-code ph-bold ph-lg",
+ text: i18n.ts.getQrCode,
+ action: () => {
+ os.displayQrCode(window.location.href)
+ }
+ },
meId !== user.id
? {
type: "link",