From 22ef74d92ce9b1113ad82221d7ab56461c32ada4 Mon Sep 17 00:00:00 2001 From: Essem Date: Fri, 22 Sep 2023 03:48:54 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20Implement=20module=20player?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- COPYING | 4 + locales/en-US.yml | 1 + locales/pt-PT.yml | 1 + packages/backend/src/const.ts | 9 + packages/backend/src/server/web/index.ts | 2 +- packages/client/package.json | 1 + .../client/src/components/MkMediaList.vue | 46 +- .../client/src/components/MkModPlayer.vue | 516 +++ packages/client/src/components/form/range.vue | 32 +- packages/client/src/const.ts | 68 + packages/client/src/scripts/chiptune2.ts | 372 ++ pnpm-lock.yaml | 3238 +++++++++-------- 12 files changed, 2829 insertions(+), 1461 deletions(-) create mode 100644 packages/client/src/components/MkModPlayer.vue create mode 100644 packages/client/src/scripts/chiptune2.ts diff --git a/COPYING b/COPYING index 27aeb01ac..5b35f69f2 100644 --- a/COPYING +++ b/COPYING @@ -28,6 +28,10 @@ Machine learning model for sensitive images by Infinite Red, Inc. License: MIT https://github.com/infinitered/nsfwjs/blob/master/LICENSE +Chiptune2.js by Simon Gündling +License: MIT +https://github.com/deskjet/chiptune2.js#license + Licenses for all softwares and software libraries installed via the Node Package Manager ("npm") can be found by running the following shell command in the root directory of this repository: pnpm licenses list diff --git a/locales/en-US.yml b/locales/en-US.yml index 46242d5fc..37de0e0ac 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -132,6 +132,7 @@ rememberNoteVisibility: "Remember post visibility settings" attachCancel: "Remove attachment" markAsSensitive: "Mark as NSFW" unmarkAsSensitive: "Unmark as NSFW" +clickToShowPatterns: "Click to show module patterns" enterFileName: "Enter filename" mute: "Mute" unmute: "Unmute" diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml index 574afa851..9df04022b 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -120,6 +120,7 @@ rememberNoteVisibility: "Lembrar das configurações de visibilidade de notas" attachCancel: "Remover anexo" markAsSensitive: "Marcar como sensível" unmarkAsSensitive: "Desmarcar como sensível" +clickToShowPatterns: "Clique para mostrar os padrões do módulo" enterFileName: "Digite o nome do ficheiro" mute: "Silenciar" unmute: "Dessilenciar" diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts index 2a955ee52..6dddf1fff 100644 --- a/packages/backend/src/const.ts +++ b/packages/backend/src/const.ts @@ -68,6 +68,15 @@ export const FILE_TYPE_BROWSERSAFE = [ "audio/x-flac", "audio/flac", "audio/vnd.wave", + + "audio/mod", + "audio/x-mod", + "audio/s3m", + "audio/x-s3m", + "audio/xm", + "audio/x-xm", + "audio/it", + "audio/x-it", ]; /* https://github.com/sindresorhus/file-type/blob/main/supported.js diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 7f28f443f..52078515a 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -492,7 +492,7 @@ router.get("/notes/:note", async (ctx, next) => { ctx.set("Cache-Control", "public, max-age=15"); ctx.set( "Content-Security-Policy", - "default-src 'self' 'unsafe-inline'; img-src *; frame-ancestors *", + "default-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src *; font-src 'self' data:; img-src *; media-src *; worker-src 'self'; frame-ancestors *", ); return; diff --git a/packages/client/package.json b/packages/client/package.json index 6bd13bac9..82284cfb0 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -61,6 +61,7 @@ "insert-text-at-cursor": "0.3.0", "json5": "2.2.3", "katex": "0.16.8", + "libopenmpt-wasm": "github:TheEssem/libopenmpt-packaging#build", "matter-js": "0.19.0", "mfm-js": "0.23.3", "photoswipe": "5.3.9", diff --git a/packages/client/src/components/MkMediaList.vue b/packages/client/src/components/MkMediaList.vue index 5a51be938..1fbc77d2c 100644 --- a/packages/client/src/components/MkMediaList.vue +++ b/packages/client/src/components/MkMediaList.vue @@ -12,16 +12,28 @@ :class="{ dmWidth: inDm }" >
- + > + + +
@@ -35,8 +47,13 @@ import PhotoSwipe from "photoswipe"; import "photoswipe/style.css"; import XBanner from "@/components/MkMediaBanner.vue"; import XMedia from "@/components/MkMedia.vue"; +import XModPlayer from "@/components/MkModPlayer.vue"; import * as os from "@/os"; -import { FILE_TYPE_BROWSERSAFE } from "@/const"; +import { + FILE_TYPE_BROWSERSAFE, + FILE_TYPE_TRACKER_MODULES, + FILE_EXT_TRACKER_MODULES, +} from "@/const"; const props = defineProps<{ mediaList: misskey.entities.DriveFile[]; @@ -170,11 +187,24 @@ onMounted(() => { const previewable = (file: misskey.entities.DriveFile): boolean => { if (file.type === "image/svg+xml") return true; // svgのwebpublic/thumbnailはpngなのでtrue // FILE_TYPE_BROWSERSAFEに適合しないものはブラウザで表示するのに不適切 + if (isModule(file)) return true; return ( (file.type.startsWith("video") || file.type.startsWith("image")) && FILE_TYPE_BROWSERSAFE.includes(file.type) ); }; + +const isModule = (file: misskey.entities.DriveFile): boolean => { + return ( + FILE_TYPE_TRACKER_MODULES.some((type) => { + return file.type === type; + }) || + FILE_EXT_TRACKER_MODULES.some((ext) => { + return file.name.toLowerCase().endsWith("." + ext); + }) + ); +}; + const previewableCount = props.mediaList.filter((media) => previewable(media), ).length; diff --git a/packages/client/src/components/MkModPlayer.vue b/packages/client/src/components/MkModPlayer.vue new file mode 100644 index 000000000..f7ad14095 --- /dev/null +++ b/packages/client/src/components/MkModPlayer.vue @@ -0,0 +1,516 @@ + + + + + diff --git a/packages/client/src/components/form/range.vue b/packages/client/src/components/form/range.vue index fef7d0898..c7aa7ed77 100644 --- a/packages/client/src/components/form/range.vue +++ b/packages/client/src/components/form/range.vue @@ -1,7 +1,7 @@