Skip to content

Commit

Permalink
feat(tms): サーバーカスタムCSS
Browse files Browse the repository at this point in the history
  • Loading branch information
taiyme committed Nov 28, 2024
1 parent d4c6ec9 commit 1ddfa9b
Show file tree
Hide file tree
Showing 17 changed files with 185 additions and 21 deletions.
12 changes: 12 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10614,6 +10614,10 @@ export interface Locale extends ILocale {
* taiymeについて
*/
readonly "aboutTaiyme": string;
/**
* taiyme限定
*/
readonly "taiymeOnly": string;
/**
* taiyme限定機能
*/
Expand Down Expand Up @@ -10809,6 +10813,14 @@ export interface Locale extends ILocale {
};
};
readonly "_admin": {
/**
* サーバーカスタムCSS
*/
readonly "serverCustomCss": string;
/**
* この設定は必ず知識のある方が行ってください。不適切な設定を行うと、管理者を含むすべてのユーザーのクライアントが正常に使用できなくなる恐れがあります。
*/
readonly "serverCustomCssDescription": string;
/**
* ソースコードが公開されているリポジトリがある場合、そのURLを記入します。taiymeを現状のまま(ソースコードにいかなる変更も加えずに)使用している場合は https://github.com/taiyme/misskey と記入します。
*/
Expand Down
3 changes: 3 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2831,6 +2831,7 @@ _tms:
taiy: "taiy"
taiyme: "taiyme"
aboutTaiyme: "taiymeについて"
taiymeOnly: "taiyme限定"
taiymeFeatures: "taiyme限定機能"
taiymeFeaturesDescription: "これらの機能はtaiymeで独自実装したものです。"
poweredByTaiyme: "{name}は、Misskeyの派生であるtaiymeを使用したサーバーのひとつです。"
Expand Down Expand Up @@ -2884,6 +2885,8 @@ _tms:
label: "長押しによるコンテキストメニューイベントの発行を防ぐ"
caption: "長押しを含む操作が中断される問題を解消します。"
_admin:
serverCustomCss: "サーバーカスタムCSS"
serverCustomCssDescription: "この設定は必ず知識のある方が行ってください。不適切な設定を行うと、管理者を含むすべてのユーザーのクライアントが正常に使用できなくなる恐れがあります。"
repositoryUrlDescription: "ソースコードが公開されているリポジトリがある場合、そのURLを記入します。taiymeを現状のまま(ソースコードにいかなる変更も加えずに)使用している場合は https://github.com/taiyme/misskey と記入します。"
_search:
searchScopeAll: "全て"
Expand Down
16 changes: 16 additions & 0 deletions packages/backend/migration/1732244400000-tmsServerCustomCss.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

export class TmsServerCustomCss1732244400000 {
name = 'TmsServerCustomCss1732244400000';

async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "tmsServerCustomCss" character varying(8192)`);
}

async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "tmsServerCustomCss"`);
}
}
1 change: 1 addition & 0 deletions packages/backend/src/core/entities/MetaEntityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export class MetaEntityService {
maxNoteTextLength: MAX_NOTE_TEXT_LENGTH,
defaultLightTheme,
defaultDarkTheme,
tmsServerCustomCss: instance.tmsServerCustomCss,
ads: ads.map(ad => ({
id: ad.id,
url: ad.url,
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/models/Meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,12 @@ export class MiMeta {
})
public defaultDarkTheme: string | null;

@Column('varchar', {
length: 8192,
nullable: true,
})
public tmsServerCustomCss: string | null;

@Column('boolean', {
default: false,
})
Expand Down
4 changes: 4 additions & 0 deletions packages/backend/src/models/json-schema/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ export const packedMetaLiteSchema = {
type: 'string',
optional: false, nullable: true,
},
tmsServerCustomCss: {
type: 'string',
optional: false, nullable: true,
},
disableRegistration: {
type: 'boolean',
optional: false, nullable: false,
Expand Down
5 changes: 5 additions & 0 deletions packages/backend/src/server/api/endpoints/admin/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@ export const meta = {
type: 'string',
optional: false, nullable: true,
},
tmsServerCustomCss: {
type: 'string',
optional: false, nullable: true,
},
description: {
type: 'string',
optional: false, nullable: true,
Expand Down Expand Up @@ -591,6 +595,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
logoImageUrl: instance.logoImageUrl,
defaultLightTheme: instance.defaultLightTheme,
defaultDarkTheme: instance.defaultDarkTheme,
tmsServerCustomCss: instance.tmsServerCustomCss,
enableEmail: instance.enableEmail,
enableServiceWorker: instance.enableServiceWorker,
translatorAvailable: instance.deeplAuthKey != null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export const paramDef = {
description: { type: 'string', nullable: true },
defaultLightTheme: { type: 'string', nullable: true },
defaultDarkTheme: { type: 'string', nullable: true },
tmsServerCustomCss: { type: 'string', nullable: true },
cacheRemoteFiles: { type: 'boolean' },
cacheRemoteSensitiveFiles: { type: 'boolean' },
emailRequiredForSignup: { type: 'boolean' },
Expand Down Expand Up @@ -303,6 +304,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
set.defaultDarkTheme = ps.defaultDarkTheme;
}

if (ps.tmsServerCustomCss !== undefined) {
set.tmsServerCustomCss = ps.tmsServerCustomCss;
}

if (ps.cacheRemoteFiles !== undefined) {
set.cacheRemoteFiles = ps.cacheRemoteFiles;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/backend/src/server/web/boot.embed.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@
//#endregion

async function addStyle(styleText) {
let css = document.createElement('style');
css.appendChild(document.createTextNode(styleText));
document.head.appendChild(css);
const styleTag = document.createElement('style');
styleTag.textContent = styleText;
document.head.appendChild(styleTag);
}

async function renderError(code) {
Expand Down
26 changes: 17 additions & 9 deletions packages/backend/src/server/web/boot.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

/* global window, document, localStorage, navigator, console, LANGS, CLIENT_ENTRY */
/* global window, document, localStorage, navigator, console, URLSearchParams, LANGS, CLIENT_ENTRY */

'use strict';

Expand Down Expand Up @@ -134,17 +134,25 @@
document.documentElement.style.backgroundImage = `url(${wallpaper})`;
}

const customCss = localStorage.getItem('customCss');
if (customCss && customCss.length > 0) {
const style = document.createElement('style');
style.innerHTML = customCss;
document.head.appendChild(style);
const availableCustomCss = (() => {
const params = new URLSearchParams(window.location.search);
return !params.has('disableCustomCss') && !params.has('disablecustomcss');
})();

if (availableCustomCss) {
const customCss = localStorage.getItem('customCss');
if (customCss && customCss.length > 0) {
const styleTag = document.createElement('style');
styleTag.id = 'user_custom_css';
styleTag.textContent = customCss;
document.head.appendChild(styleTag);
}
}

async function addStyle(styleText) {
let css = document.createElement('style');
css.appendChild(document.createTextNode(styleText));
document.head.appendChild(css);
const styleTag = document.createElement('style');
styleTag.textContent = styleText;
document.head.appendChild(styleTag);
}

async function renderError(code, details) {
Expand Down
18 changes: 13 additions & 5 deletions packages/frontend/src/_dev_boot_.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,19 @@ async function main() {
document.documentElement.style.backgroundImage = `url(${wallpaper})`;
}

const customCss = localStorage.getItem('customCss');
if (customCss && customCss.length > 0) {
const style = document.createElement('style');
style.innerHTML = customCss;
document.head.appendChild(style);
const availableCustomCss = (() => {
const params = new URLSearchParams(window.location.search);
return !params.has('disableCustomCss') && !params.has('disablecustomcss');
})();

if (availableCustomCss) {
const customCss = localStorage.getItem('customCss');
if (customCss && customCss.length > 0) {
const styleTag = document.createElement('style');
styleTag.id = 'user_custom_css';
styleTag.textContent = customCss;
document.head.appendChild(styleTag);
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions packages/frontend/src/boot/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { setupRouter } from '@/router/main.js';
import { createMainRouter } from '@/router/definition.js';
import { tmsFlaskStore } from '@/tms/flask-store.js';
import { tmsStore } from '@/tms/store.js';
import { applyCustomCss } from '@/scripts/tms/apply-custom-css.js';
import { preventLongPressContextMenu } from '@/scripts/tms/prevent-longpress-contextmenu.js';

export async function common(createVue: () => App<Element>) {
Expand Down Expand Up @@ -135,6 +136,14 @@ export async function common(createVue: () => App<Element>) {
miLocalStorage.setItem('v', instance.version);
});

//#region tmsServerCustomCss
fetchInstanceMetaPromise.then(() => {
applyCustomCss({
serverCustomCss: instance.tmsServerCustomCss,
});
});
//#endregion

//#region loginId
const params = new URLSearchParams(location.search);
const loginId = params.get('loginId');
Expand Down
8 changes: 4 additions & 4 deletions packages/frontend/src/components/MkRange.vue
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ function onMousedown(ev: MouseEvent | TouchEvent) {
closed: () => dispose(),
});

const style = document.createElement('style');
style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }'));
document.head.appendChild(style);
const styleTag = document.createElement('style');
styleTag.textContent = '* { cursor: grabbing !important; } body * { pointer-events: none !important; }';
document.head.appendChild(styleTag);

const thumbWidth = getThumbWidth();

Expand All @@ -172,7 +172,7 @@ function onMousedown(ev: MouseEvent | TouchEvent) {
let beforeValue = finalValue.value;

const onMouseup = () => {
document.head.removeChild(style);
document.head.removeChild(styleTag);
tooltipForDragShowing.value = false;
window.removeEventListener('mousemove', onDrag);
window.removeEventListener('touchmove', onDrag);
Expand Down
12 changes: 12 additions & 0 deletions packages/frontend/src/pages/admin/branding.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkTextarea v-model="manifestJsonOverride">
<template #label>{{ i18n.ts._serverSettings.manifestJsonOverride }}</template>
</MkTextarea>

<MkCodeEditor v-model="tmsServerCustomCss" lang="css">
<template #label>
<span>{{ i18n.ts._tms._admin.serverCustomCss }}</span>
<span class="_taiymeOnly">{{ i18n.ts._tms.taiymeOnly }}</span>
</template>
<template #caption>{{ i18n.ts._tms._admin.serverCustomCssDescription }}</template>
</MkCodeEditor>
</div>
</FormSuspense>
</MkSpacer>
Expand All @@ -114,6 +122,7 @@ import { instance, fetchInstance } from '@/instance.js';
import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import MkButton from '@/components/MkButton.vue';
import MkCodeEditor from '@/components/MkCodeEditor.vue';
import MkColorInput from '@/components/MkColorInput.vue';

const iconUrl = ref<string | null>(null);
Expand All @@ -124,6 +133,7 @@ const backgroundImageUrl = ref<string | null>(null);
const themeColor = ref<string | null>(null);
const defaultLightTheme = ref<string | null>(null);
const defaultDarkTheme = ref<string | null>(null);
const tmsServerCustomCss = ref<string | null>(null);
const serverErrorImageUrl = ref<string | null>(null);
const infoImageUrl = ref<string | null>(null);
const notFoundImageUrl = ref<string | null>(null);
Expand All @@ -141,6 +151,7 @@ async function init() {
themeColor.value = meta.themeColor;
defaultLightTheme.value = meta.defaultLightTheme;
defaultDarkTheme.value = meta.defaultDarkTheme;
tmsServerCustomCss.value = meta.tmsServerCustomCss;
serverErrorImageUrl.value = meta.serverErrorImageUrl;
infoImageUrl.value = meta.infoImageUrl;
notFoundImageUrl.value = meta.notFoundImageUrl;
Expand All @@ -159,6 +170,7 @@ function save() {
themeColor: themeColor.value === '' ? null : themeColor.value,
defaultLightTheme: defaultLightTheme.value === '' ? null : defaultLightTheme.value,
defaultDarkTheme: defaultDarkTheme.value === '' ? null : defaultDarkTheme.value,
tmsServerCustomCss: tmsServerCustomCss.value === '' ? null : tmsServerCustomCss.value,
infoImageUrl: infoImageUrl.value === '' ? null : infoImageUrl.value,
notFoundImageUrl: notFoundImageUrl.value === '' ? null : notFoundImageUrl.value,
serverErrorImageUrl: serverErrorImageUrl.value === '' ? null : serverErrorImageUrl.value,
Expand Down
60 changes: 60 additions & 0 deletions packages/frontend/src/scripts/tms/apply-custom-css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { url as configUrl } from '@@/js/config.js';

const availableCustomCss = (() => {
const params = new URLSearchParams(window.location.search);
return !params.has('disableCustomCss') && !params.has('disablecustomcss');
})();

export function applyCustomCss({ serverCustomCss, userCustomCss }: {
readonly serverCustomCss?: string | null;
readonly userCustomCss?: string | null;
}) {
if (!availableCustomCss) return;
if (serverCustomCss === undefined && userCustomCss === undefined) return;

let serverStyleTag = document.getElementById('server_custom_css');
if (serverCustomCss !== undefined) {
if (serverCustomCss === null || serverCustomCss === '') {
serverStyleTag?.remove();
serverStyleTag = null;
} else {
if (serverStyleTag == null) {
serverStyleTag = document.createElement('style');
serverStyleTag.id = 'server_custom_css';
}
serverStyleTag.textContent = serverCustomCss;
}
}

let userStyleTag = document.getElementById('user_custom_css');
if (userCustomCss !== undefined) {
if (userCustomCss === null || userCustomCss === '') {
userStyleTag?.remove();
userStyleTag = null;
} else {
if (userStyleTag == null) {
userStyleTag = document.createElement('style');
userStyleTag.id = 'user_custom_css';
}
userStyleTag.textContent = userCustomCss;
}
}

if (serverStyleTag != null) {
document.head.appendChild(serverStyleTag);
}
if (userStyleTag != null) {
document.head.appendChild(userStyleTag);
}

if (serverStyleTag != null || userStyleTag != null) {
const url = `${configUrl}/?disableCustomCss`;
console.warn(`Custom CSS has been applied. To temporarily disable it, please visit ${url}.`);
console.warn(`カスタムCSSが適用されました。一時的に無効にするには ${url} にアクセスします。`);
}
}
12 changes: 12 additions & 0 deletions packages/frontend/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,18 @@ rt {
line-height: 1;
}

._taiymeOnly {
margin-left: 0.7em;
font-size: 65%;
padding: 3px 4px;
color: #fff;
background-color: #1c3c70;
border-radius: 4px;
vertical-align: top;
display: inline-block;
line-height: 1;
}

._table {
> ._row {
display: flex;
Expand Down
Loading

0 comments on commit 1ddfa9b

Please sign in to comment.