summaryrefslogtreecommitdiff
path: root/packages/frontend-embed/src
diff options
context:
space:
mode:
authorJulia <julia@insertdomain.name>2025-03-02 19:54:32 +0000
committerJulia <julia@insertdomain.name>2025-03-02 19:54:32 +0000
commit9e13c375c5ef4103ad5ee87fea583b154e9e16f3 (patch)
treefe9e7b1a474e22fb0c37bd68cfd260f7ba39be74 /packages/frontend-embed/src
parentmerge: pin corepack version (!885) (diff)
parentbump version (diff)
downloadsharkey-9e13c375c5ef4103ad5ee87fea583b154e9e16f3.tar.gz
sharkey-9e13c375c5ef4103ad5ee87fea583b154e9e16f3.tar.bz2
sharkey-9e13c375c5ef4103ad5ee87fea583b154e9e16f3.zip
merge: 2025.2.2 (!927)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/927 Approved-by: Marie <github@yuugi.dev> Approved-by: Julia <julia@insertdomain.name>
Diffstat (limited to 'packages/frontend-embed/src')
-rw-r--r--packages/frontend-embed/src/boot.ts20
-rw-r--r--packages/frontend-embed/src/components/EmAcct.vue2
-rw-r--r--packages/frontend-embed/src/components/EmMention.vue2
-rw-r--r--packages/frontend-embed/src/components/EmNote.vue9
-rw-r--r--packages/frontend-embed/src/components/EmNoteDetailed.vue9
-rw-r--r--packages/frontend-embed/src/components/EmNoteSimple.vue11
-rw-r--r--packages/frontend-embed/src/components/EmNoteSub.vue11
-rw-r--r--packages/frontend-embed/src/components/EmNotes.vue3
-rw-r--r--packages/frontend-embed/src/components/EmUrl.vue2
-rw-r--r--packages/frontend-embed/src/index.html38
-rw-r--r--packages/frontend-embed/src/theme.ts23
11 files changed, 63 insertions, 67 deletions
diff --git a/packages/frontend-embed/src/boot.ts b/packages/frontend-embed/src/boot.ts
index 71a3156311..7c8336ce3f 100644
--- a/packages/frontend-embed/src/boot.ts
+++ b/packages/frontend-embed/src/boot.ts
@@ -15,11 +15,11 @@ import { applyTheme, assertIsTheme } from '@/theme.js';
import { fetchCustomEmojis } from '@/custom-emojis.js';
import { DI } from '@/di.js';
import { serverMetadata } from '@/server-metadata.js';
-import { url } from '@@/js/config.js';
+import { url, version, locale, lang, updateLocale, langsVersion } from '@@/js/config.js';
import { parseEmbedParams } from '@@/js/embed-page.js';
import { postMessageToParentWindow, setIframeId } from '@/post-message.js';
import { serverContext } from '@/server-context.js';
-import { i18n } from '@/i18n.js';
+import { i18n, updateI18n } from '@/i18n.js';
import type { Theme } from '@/theme.js';
@@ -69,6 +69,22 @@ if (embedParams.colorMode === 'dark') {
}
//#endregion
+//#region Detect language & fetch translations
+const localeVersion = localStorage.getItem('localeVersion');
+const localeOutdated = (localeVersion == null || localeVersion !== langsVersion || locale == null);
+if (localeOutdated) {
+ const res = await window.fetch(`/assets/locales/${lang}.${langsVersion}.json`);
+ if (res.status === 200) {
+ const newLocale = await res.text();
+ const parsedNewLocale = JSON.parse(newLocale);
+ localStorage.setItem('locale', newLocale);
+ localStorage.setItem('localeVersion', langsVersion);
+ updateLocale(parsedNewLocale);
+ updateI18n(parsedNewLocale);
+ }
+}
+//#endregion
+
// サイズの制限
document.documentElement.style.maxWidth = '500px';
diff --git a/packages/frontend-embed/src/components/EmAcct.vue b/packages/frontend-embed/src/components/EmAcct.vue
index 6856b8272e..ff794d9b6e 100644
--- a/packages/frontend-embed/src/components/EmAcct.vue
+++ b/packages/frontend-embed/src/components/EmAcct.vue
@@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import * as Misskey from 'misskey-js';
-import { toUnicode } from 'punycode/';
+import { toUnicode } from 'punycode.js';
import { host as hostRaw } from '@@/js/config.js';
defineProps<{
diff --git a/packages/frontend-embed/src/components/EmMention.vue b/packages/frontend-embed/src/components/EmMention.vue
index a71364237d..b5aaa95894 100644
--- a/packages/frontend-embed/src/components/EmMention.vue
+++ b/packages/frontend-embed/src/components/EmMention.vue
@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
-import { toUnicode } from 'punycode';
+import { toUnicode } from 'punycode.js';
import { } from 'vue';
import tinycolor from 'tinycolor2';
import { host as localHost } from '@@/js/config.js';
diff --git a/packages/frontend-embed/src/components/EmNote.vue b/packages/frontend-embed/src/components/EmNote.vue
index 025c4c0734..bf96c557ea 100644
--- a/packages/frontend-embed/src/components/EmNote.vue
+++ b/packages/frontend-embed/src/components/EmNote.vue
@@ -46,11 +46,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<EmNoteHeader :note="appearNote" :mini="true"/>
<EmInstanceTicker v-if="appearNote.user.instance != null" :instance="appearNote.user.instance"/>
<div style="container-type: inline-size;">
- <p v-if="appearNote.cw != null" :class="$style.cw">
- <EmMfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'respect'" :isBlock="true"/>
+ <p v-if="mergedCW != null" :class="$style.cw">
+ <EmMfm v-if="mergedCW != ''" style="margin-right: 8px;" :text="mergedCW" :author="appearNote.user" :nyaize="'respect'" :isBlock="true"/>
<button style="display: block; width: 100%; margin: 4px 0;" class="_buttonGray _buttonRounded" @click="showContent = !showContent">{{ showContent ? i18n.ts._cw.hide : i18n.ts._cw.show }}</button>
</p>
- <div v-show="appearNote.cw == null || showContent" :class="[{ [$style.contentCollapsed]: collapsed }]">
+ <div v-show="mergedCW == null || showContent" :class="[{ [$style.contentCollapsed]: collapsed }]">
<div :class="$style.text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<EmA v-if="appearNote.replyId" :class="$style.replyIcon" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></EmA>
@@ -109,6 +109,7 @@ import * as mfm from '@transfem-org/sfm-js';
import * as Misskey from 'misskey-js';
import { shouldCollapsed } from '@@/js/collapsed.js';
import { url } from '@@/js/config.js';
+import { computeMergedCw } from '@@/js/compute-merged-cw.js';
import I18n from '@/components/I18n.vue';
import EmNoteSub from '@/components/EmNoteSub.vue';
import EmNoteHeader from '@/components/EmNoteHeader.vue';
@@ -154,6 +155,8 @@ const parsed = computed(() => appearNote.value.text ? mfm.parse(appearNote.value
const isLong = shouldCollapsed(appearNote.value, []);
const collapsed = ref(appearNote.value.cw == null && isLong);
const isDeleted = ref(false);
+
+const mergedCW = computed(() => computeMergedCw(appearNote.value));
</script>
<style lang="scss" module>
diff --git a/packages/frontend-embed/src/components/EmNoteDetailed.vue b/packages/frontend-embed/src/components/EmNoteDetailed.vue
index c4ea9b4f2e..0961b36e35 100644
--- a/packages/frontend-embed/src/components/EmNoteDetailed.vue
+++ b/packages/frontend-embed/src/components/EmNoteDetailed.vue
@@ -58,11 +58,11 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</header>
<div :class="[$style.noteContent, { [$style.contentCollapsed]: collapsed }]">
- <p v-if="appearNote.cw != null" :class="$style.cw">
- <EmMfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'respect'" :isBlock="true"/>
+ <p v-if="mergedCW != null" :class="$style.cw">
+ <EmMfm v-if="mergedCW != ''" style="margin-right: 8px;" :text="mergedCW" :author="appearNote.user" :nyaize="'respect'" :isBlock="true"/>
<button style="display: block; width: 100%; margin: 4px 0;" class="_buttonGray _buttonRounded" @click="showContent = !showContent">{{ showContent ? i18n.ts._cw.hide : i18n.ts._cw.show }}</button>
</p>
- <div v-show="appearNote.cw == null || showContent">
+ <div v-show="mergedCW == null || showContent">
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<EmA v-if="appearNote.replyId" :class="$style.noteReplyTarget" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></EmA>
<EmMfm
@@ -130,6 +130,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { computed, inject, ref } from 'vue';
import * as mfm from '@transfem-org/sfm-js';
import * as Misskey from 'misskey-js';
+import { computeMergedCw } from '@@/js/compute-merged-cw.js';
import I18n from '@/components/I18n.vue';
import EmMediaList from '@/components/EmMediaList.vue';
import EmNoteSub from '@/components/EmNoteSub.vue';
@@ -175,6 +176,8 @@ const isDeleted = ref(false);
const parsed = appearNote.value.text ? mfm.parse(appearNote.value.text) : null;
const isLong = shouldCollapsed(appearNote.value, []);
const collapsed = ref(appearNote.value.cw == null && isLong);
+
+const mergedCW = computed(() => computeMergedCw(appearNote.value));
</script>
<style lang="scss" module>
diff --git a/packages/frontend-embed/src/components/EmNoteSimple.vue b/packages/frontend-embed/src/components/EmNoteSimple.vue
index 83e73f9870..688758edb6 100644
--- a/packages/frontend-embed/src/components/EmNoteSimple.vue
+++ b/packages/frontend-embed/src/components/EmNoteSimple.vue
@@ -9,11 +9,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.main">
<EmNoteHeader :class="$style.header" :note="note" :mini="true"/>
<div>
- <p v-if="note.cw != null" :class="$style.cw">
- <EmMfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :nyaize="'respect'" :emojiUrls="note.emojis" :isBlock="true"/>
+ <p v-if="mergedCW != null" :class="$style.cw">
+ <EmMfm v-if="mergedCW != ''" style="margin-right: 8px;" :text="mergedCW" :author="note.user" :nyaize="'respect'" :emojiUrls="note.emojis" :isBlock="true"/>
<button style="display: block; width: 100%;" class="_buttonGray _buttonRounded" @click="showContent = !showContent">{{ showContent ? i18n.ts._cw.hide : i18n.ts._cw.show }}</button>
</p>
- <div v-show="note.cw == null || showContent">
+ <div v-show="mergedCW == null || showContent">
<EmSubNoteContent :class="$style.text" :note="note"/>
</div>
</div>
@@ -22,8 +22,9 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
-import { ref } from 'vue';
+import { computed, ref } from 'vue';
import * as Misskey from 'misskey-js';
+import { computeMergedCw } from '@@/js/compute-merged-cw.js';
import { i18n } from '@/i18n.js';
import EmAvatar from '@/components/EmAvatar.vue';
import EmNoteHeader from '@/components/EmNoteHeader.vue';
@@ -35,6 +36,8 @@ const props = defineProps<{
}>();
const showContent = ref(false);
+
+const mergedCW = computed(() => computeMergedCw(props.note));
</script>
<style lang="scss" module>
diff --git a/packages/frontend-embed/src/components/EmNoteSub.vue b/packages/frontend-embed/src/components/EmNoteSub.vue
index cc379e8281..629f0bffcd 100644
--- a/packages/frontend-embed/src/components/EmNoteSub.vue
+++ b/packages/frontend-embed/src/components/EmNoteSub.vue
@@ -11,11 +11,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.body">
<EmNoteHeader :class="$style.header" :note="note" :mini="true"/>
<div>
- <p v-if="note.cw != null" :class="$style.cw">
- <EmMfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :nyaize="'respect'" :isBlock="true"/>
+ <p v-if="mergedCW != null" :class="$style.cw">
+ <EmMfm v-if="mergedCW != ''" style="margin-right: 8px;" :text="mergedCW" :author="note.user" :nyaize="'respect'" :isBlock="true"/>
<button style="display: block; width: 100%;" class="_buttonGray _buttonRounded" @click="showContent = !showContent">{{ showContent ? i18n.ts._cw.hide : i18n.ts._cw.show }}</button>
</p>
- <div v-show="note.cw == null || showContent">
+ <div v-show="mergedCW == null || showContent">
<EmSubNoteContent :class="$style.text" :note="note"/>
</div>
</div>
@@ -31,8 +31,9 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
-import { ref } from 'vue';
+import { computed, ref } from 'vue';
import * as Misskey from 'misskey-js';
+import { computeMergedCw } from '@@/js/compute-merged-cw.js';
import EmA from '@/components/EmA.vue';
import EmAvatar from '@/components/EmAvatar.vue';
import EmNoteHeader from '@/components/EmNoteHeader.vue';
@@ -55,6 +56,8 @@ const props = withDefaults(defineProps<{
const showContent = ref(false);
const replies = ref<Misskey.entities.Note[]>([]);
+const mergedCW = computed(() => computeMergedCw(props.note));
+
if (props.detail) {
misskeyApi('notes/children', {
noteId: props.note.id,
diff --git a/packages/frontend-embed/src/components/EmNotes.vue b/packages/frontend-embed/src/components/EmNotes.vue
index 4211261e19..4e0ae005df 100644
--- a/packages/frontend-embed/src/components/EmNotes.vue
+++ b/packages/frontend-embed/src/components/EmNotes.vue
@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #default="{ items: notes }">
<div :class="[$style.root]">
- <EmNote v-for="note in notes" :key="note._featuredId_ || note._prId_ || note.id" :class="$style.note" :note="note"/>
+ <EmNote v-for="note in notes" :key="note._featuredId_ || note._prId_ || note.id" :class="$style.note" :note="note as Misskey.entities.Note"/>
</div>
</template>
</EmPagination>
@@ -24,6 +24,7 @@ import { useTemplateRef } from 'vue';
import EmNote from '@/components/EmNote.vue';
import EmPagination, { Paging } from '@/components/EmPagination.vue';
import { i18n } from '@/i18n.js';
+import * as Misskey from 'misskey-js';
withDefaults(defineProps<{
pagination: Paging;
diff --git a/packages/frontend-embed/src/components/EmUrl.vue b/packages/frontend-embed/src/components/EmUrl.vue
index 94424cab28..2dbbe90858 100644
--- a/packages/frontend-embed/src/components/EmUrl.vue
+++ b/packages/frontend-embed/src/components/EmUrl.vue
@@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { ref } from 'vue';
-import { toUnicode as decodePunycode } from 'punycode/';
+import { toUnicode as decodePunycode } from 'punycode.js';
import EmA from './EmA.vue';
import { url as local } from '@@/js/config.js';
diff --git a/packages/frontend-embed/src/index.html b/packages/frontend-embed/src/index.html
deleted file mode 100644
index d94ada5ea8..0000000000
--- a/packages/frontend-embed/src/index.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!--
- SPDX-FileCopyrightText: syuilo and misskey-project
- SPDX-License-Identifier: AGPL-3.0-only
--->
-
-<!--
- 開発モードのviteはこのファイルを起点にサーバーを起動します。
- このファイルに書かれた [t]js のリンクと (s)cssのリンクと、その依存関係にあるファイルはビルドされます
--->
-
-<!DOCTYPE html>
-<html>
-<head>
- <meta charset="UTF-8" />
- <title>[DEV] Loading...</title>
- <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
- <meta
- http-equiv="Content-Security-Policy"
- content="default-src 'self' https://newassets.hcaptcha.com/ https://challenges.cloudflare.com/ http://localhost:7493/;
- worker-src 'self';
- script-src 'self' 'unsafe-eval' https://*.hcaptcha.com https://challenges.cloudflare.com https://esm.sh https://cdn.jsdelivr.net;
- style-src 'self' 'unsafe-inline';
- img-src 'self' data: blob: www.google.com xn--931a.moe localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000;
- media-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000;
- connect-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000 https://newassets.hcaptcha.com;
- frame-src *;"
- />
- <meta property="og:site_name" content="[DEV BUILD] Sharkey" />
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel='stylesheet' href='/assets/phosphor-icons/bold/style.css'>
- <link rel='stylesheet' href='/static-assets/fonts/sharkey-icons/style.css'>
-</head>
-
-<body>
-<div id="sharkey_app"></div>
-<script type="module" src="./boot.ts"></script>
-</body>
-</html>
diff --git a/packages/frontend-embed/src/theme.ts b/packages/frontend-embed/src/theme.ts
index 4664ad4880..680ab80167 100644
--- a/packages/frontend-embed/src/theme.ts
+++ b/packages/frontend-embed/src/theme.ts
@@ -75,16 +75,21 @@ function compile(theme: Theme): Record<string, string> {
return getColor(theme.props[val]);
} else if (val[0] === ':') { // func
const parts = val.split('<');
- const func = parts.shift().substring(1);
- const arg = parseFloat(parts.shift());
- const color = getColor(parts.join('<'));
+ const funcTxt = parts.shift();
+ const argTxt = parts.shift();
- switch (func) {
- case 'darken': return color.darken(arg);
- case 'lighten': return color.lighten(arg);
- case 'alpha': return color.setAlpha(arg);
- case 'hue': return color.spin(arg);
- case 'saturate': return color.saturate(arg);
+ if (funcTxt && argTxt) {
+ const func = funcTxt.substring(1);
+ const arg = parseFloat(argTxt);
+ const color = getColor(parts.join('<'));
+
+ switch (func) {
+ case 'darken': return color.darken(arg);
+ case 'lighten': return color.lighten(arg);
+ case 'alpha': return color.setAlpha(arg);
+ case 'hue': return color.spin(arg);
+ case 'saturate': return color.saturate(arg);
+ }
}
}