diff --git a/.pnp.cjs b/.pnp.cjs index 6d50f3cce..100d991e3 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -8365,6 +8365,7 @@ const RAW_RUNTIME_STATE = ["insert-text-at-cursor", "npm:0.3.0"],\ ["json5", "npm:2.2.3"],\ ["katex", "npm:0.16.8"],\ + ["libopenmpt-wasm", "https://github.com/TheEssem/libopenmpt-packaging.git#commit=d05d151a72b638c6312227af0417aca69521172c"],\ ["matter-js", "npm:0.18.0"],\ ["mfm-js", "npm:0.23.3"],\ ["paralint", "npm:1.2.1"],\ @@ -16813,6 +16814,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["libopenmpt-wasm", [\ + ["https://github.com/TheEssem/libopenmpt-packaging.git#commit=d05d151a72b638c6312227af0417aca69521172c", {\ + "packageLocation": "./.yarn/cache/libopenmpt-wasm-https-c2e0cb89a7-ace14fcb0e.zip/node_modules/libopenmpt-wasm/",\ + "packageDependencies": [\ + ["libopenmpt-wasm", "https://github.com/TheEssem/libopenmpt-packaging.git#commit=d05d151a72b638c6312227af0417aca69521172c"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["liftoff", [\ ["npm:3.1.0", {\ "packageLocation": "./.yarn/cache/liftoff-npm-3.1.0-6dd0a868bd-af0ea7c51c.zip/node_modules/liftoff/",\ diff --git a/.yarn/cache/libopenmpt-wasm-https-c2e0cb89a7-ace14fcb0e.zip b/.yarn/cache/libopenmpt-wasm-https-c2e0cb89a7-ace14fcb0e.zip new file mode 100644 index 000000000..d72f8eade --- /dev/null +++ b/.yarn/cache/libopenmpt-wasm-https-c2e0cb89a7-ace14fcb0e.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0ff96aad5c05d839f740e4d7941a3e1fa15942be56cad2b354b3ebb02ff29c0 +size 487564 diff --git a/COPYING b/COPYING index 783b54c3a..f67a2cbcd 100644 --- a/COPYING +++ b/COPYING @@ -25,6 +25,10 @@ RsaSignature2017 implementation by Transmute Industries Inc License: MIT https://github.com/transmute-industries/RsaSignature2017/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: `yarn -R info --manifest` diff --git a/README.md b/README.md index 31510ecda..5eb7d1e17 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ It is made in honor of the grind that went into upstream projects and is not mea - Highlighted changes: - Achievements using patches from Sharkey/Misskey - Chomp! Activity Support (Patch adopted [from mia](https://iceshrimp.dev/mia/withdrawal)) + - Fast🚜 Scream🚜 Mod🔌 Tracker/SID playback support (Thanks to [Jeder](https://iceshrimp.dev/iceshrimp/iceshrimp/pulls/490)) - Suppress the "You haven't configured mail" message (Patch adopted [from mia](https://iceshrimp.dev/mia/withdrawal)) - Fixes that allow proper federation of likes with instances using the UA "misskey" (Sharkey) - First-class Mastodon client API support diff --git a/locales/en-US.yml b/locales/en-US.yml index 5c850065f..b01f56f13 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -135,6 +135,7 @@ rememberNoteVisibility: "Remember post visibility settings" attachCancel: "Remove attachment" markAsSensitive: "Mark as sensitive" unmarkAsSensitive: "Unmark as sensitive" +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 59f12b8b6..88e6f2c60 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -113,6 +113,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 f3c1ea788..144cca87c 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -469,7 +469,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 *; media-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 c519f5cd8..0824ba453 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.18.0", "mfm-js": "0.23.3", "paralint": "^1.2.1", diff --git a/packages/client/src/components/MkMediaList.vue b/packages/client/src/components/MkMediaList.vue index 0c9a7a321..83bc7c219 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"; import { defaultStore } from "@/store"; const props = defineProps<{ @@ -171,11 +188,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..aa31c27a8 --- /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 38ebe29e3..95e2fafe4 100644 --- a/packages/client/src/components/form/range.vue +++ b/packages/client/src/components/form/range.vue @@ -1,7 +1,7 @@