1
0
mirror of https://git.boykissers.com/pawkey/pawkey-sk.git synced 2025-12-20 04:04:16 +00:00

feat: add music to front page of instance (#6)

This commit is contained in:
Leafus
2025-05-19 16:34:21 +00:00
committed by Bluey Heeler
parent 400354237c
commit 9599b802a4
9 changed files with 110 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { MigrationInterface, QueryRunner } from "typeorm";
export class AddMusicFieldsToMeta1743894419864 implements MigrationInterface {
name = 'AddMusicFieldsToMeta1743894419864'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "meta" ADD "musicSource" character varying(1024)`);
await queryRunner.query(`ALTER TABLE "meta" ADD "musicEnabled" boolean NOT NULL DEFAULT false`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "musicEnabled"`);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "musicSource"`);
}
}

View File

@@ -114,6 +114,8 @@ export class MetaEntityService {
sidebarLogoUrl: instance.sidebarLogoUrl,
backgroundImageUrl: instance.backgroundImageUrl,
logoImageUrl: instance.logoImageUrl,
musicSource: instance.musicSource,
musicEnabled: instance.musicEnabled,
maxNoteTextLength: this.config.maxNoteLength,
maxRemoteNoteTextLength: this.config.maxRemoteNoteLength,
maxCwLength: this.config.maxCwLength,

View File

@@ -142,6 +142,17 @@ export class MiMeta {
@Column('boolean', {
default: false,
})
public musicSource: string | null;
@Column('boolean', {
default: false,
})
public musicEnabled: boolean;
@Column('varchar', {
length: 1024,
nullable: true,
})
public iconUrl: string | null;
@Column('varchar', {

View File

@@ -321,6 +321,14 @@ export const packedMetaLiteSchema = {
type: 'string',
optional: false, nullable: true,
},
musicSource: {
type: 'string',
optional: false, nullable: true,
},
musicEnabled: {
type: 'boolean',
optional: false, nullable: false,
},
privacyPolicyUrl: {
type: 'string',
optional: false, nullable: true,

View File

@@ -453,6 +453,14 @@ export const meta = {
type: 'string',
optional: false, nullable: true,
},
musicSource: {
type: 'string',
optional: false, nullable: true,
},
musicEnabled: {
type: 'boolean',
optional: false, nullable: false,
},
translationTimeout: {
type: 'number',
optional: false, nullable: false,
@@ -696,6 +704,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
app512IconUrl: instance.app512IconUrl,
sidebarLogoUrl: instance.sidebarLogoUrl,
backgroundImageUrl: instance.backgroundImageUrl,
musicSource: instance.musicSource,
musicEnabled: instance.musicEnabled,
logoImageUrl: instance.logoImageUrl,
defaultLightTheme: instance.defaultLightTheme,
defaultDarkTheme: instance.defaultDarkTheme,

View File

@@ -63,6 +63,8 @@ export const paramDef = {
app512IconUrl: { type: 'string', nullable: true },
sidebarLogoUrl: { type: 'string', nullable: true },
backgroundImageUrl: { type: 'string', nullable: true },
musicSource: { type: 'string', nullable: true },
musicEnabled: { type: 'boolean', nullable: false },
logoImageUrl: { type: 'string', nullable: true },
name: { type: 'string', nullable: true },
shortName: { type: 'string', nullable: true },
@@ -316,6 +318,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
set.backgroundImageUrl = ps.backgroundImageUrl;
}
if (ps.musicEnabled !== undefined) {
set.musicEnabled = ps.musicEnabled;
}
if (ps.musicSource !== undefined) {
set.musicSource = ps.musicSource;
}
if (ps.logoImageUrl !== undefined) {
set.logoImageUrl = ps.logoImageUrl;
}

View File

@@ -5,6 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div v-if="instance" :class="$style.root">
<PwVisitorMusic/>
<div :class="[$style.main, $style.panel]">
<img :src="instance.sidebarLogoUrl || instance.iconUrl || '/apple-touch-icon.png'" alt="" :class="instance.sidebarLogoUrl ? $style.wideIcon : $style.mainIcon"/>
<button class="_button _acrylic" :class="$style.mainMenu" @click="showMenu"><i class="ti ti-dots"></i></button>
@@ -61,6 +62,7 @@ import * as Misskey from 'misskey-js';
import sanitizeHtml from '@/utility/sanitize-html.js';
import XSigninDialog from '@/components/MkSigninDialog.vue';
import XSignupDialog from '@/components/MkSignupDialog.vue';
import PwVisitorMusic from '@/components/PwVisitorMusic.vue';
import MkButton from '@/components/MkButton.vue';
import MkTimeline from '@/components/MkTimeline.vue';
import MkInfo from '@/components/MkInfo.vue';

View File

@@ -0,0 +1,30 @@
<template v-if="instance">
<audio v-if="instance.musicEnabled" ref="audioRef" :src="instance.musicSource" loop></audio>
</template>
<script lang="ts" setup>
import { computed, ref, onMounted, onUnmounted } from 'vue';
import { instance } from '@/instance.js';
const audioRef = ref<HTMLAudioElement | null>(null);
const hasPlayed = ref(false);
const playMusic = () => {
if (audioRef.value && !hasPlayed.value && instance.musicEnabled) {
audioRef.value.volume = 0.2;
audioRef.value.play().catch(() => {
// Ignore autoplay errors
});
hasPlayed.value = true;
document.removeEventListener('click', playMusic);
}
};
onMounted(() => {
document.addEventListener('click', playMusic);
});
onUnmounted(() => {
document.removeEventListener('click', playMusic);
});
</script>

View File

@@ -54,6 +54,16 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts.backgroundImageUrl }}</template>
</MkInput>
<MkSwitch v-model="musicEnabled">
<template #label>Enable Login Music</template>
<template #caption>Play music when users visit the login page</template>
</MkSwitch>
<MkInput v-model="musicSource" type="url">
<template #prefix><i class="ti ti-link"></i></template>
<template #label>Login Music URL</template>
</MkInput>
<FromSlot>
<template #label>{{ i18n.ts.defaultLike }}</template>
<MkCustomEmoji v-if="defaultLike.startsWith(':')" style="max-height: 3em; font-size: 1.1em;" :useOriginalSize="false" :name="defaultLike" :normal="true" :noStyle="true"/>
@@ -129,6 +139,7 @@ import { misskeyApi } from '@/utility/misskey-api.js';
import { instance, fetchInstance } from '@/instance.js';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import MkSwitch from '@/components/MkSwitch.vue';
import MkButton from '@/components/MkButton.vue';
import MkColorInput from '@/components/MkColorInput.vue';
@@ -138,6 +149,8 @@ const app192IconUrl = ref<string | null>(null);
const app512IconUrl = ref<string | null>(null);
const bannerUrl = ref<string | null>(null);
const backgroundImageUrl = ref<string | null>(null);
const musicSource = ref<string | null>(null);
const musicEnabled = ref<boolean>(false);
const themeColor = ref<string | null>(null);
const defaultLightTheme = ref<string | null>(null);
const defaultDarkTheme = ref<string | null>(null);
@@ -157,6 +170,8 @@ async function init() {
app512IconUrl.value = meta.app512IconUrl;
bannerUrl.value = meta.bannerUrl;
backgroundImageUrl.value = meta.backgroundImageUrl;
musicSource.value = meta.musicSource;
musicEnabled.value = meta.musicEnabled;
themeColor.value = meta.themeColor;
defaultLightTheme.value = meta.defaultLightTheme;
defaultDarkTheme.value = meta.defaultDarkTheme;
@@ -177,6 +192,8 @@ function save() {
app512IconUrl: app512IconUrl.value,
bannerUrl: bannerUrl.value,
backgroundImageUrl: backgroundImageUrl.value,
musicSource: musicSource.value,
musicEnabled: musicEnabled.value,
themeColor: themeColor.value === '' ? null : themeColor.value,
defaultLightTheme: defaultLightTheme.value === '' ? null : defaultLightTheme.value,
defaultDarkTheme: defaultDarkTheme.value === '' ? null : defaultDarkTheme.value,