feat: instance default theme
This commit is contained in:
parent
bc9157a03b
commit
ba4ef23d6b
|
@ -16,11 +16,12 @@ You should also include the user name that made the change.
|
||||||
このバージョンからNode v16.14.0以降が必要です
|
このバージョンからNode v16.14.0以降が必要です
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
- ノートの最大文字数を設定できる機能が廃止され、デフォルトで一律3000文字になりました
|
- ノートの最大文字数を設定できる機能が廃止され、デフォルトで一律3000文字になりました @syuilo
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
- プロフィールの追加情報を最大16まで保存できるように
|
- インスタンスデフォルトテーマを設定できるように @syuilo
|
||||||
- 連合チャートにPub&Subを追加
|
- プロフィールの追加情報を最大16まで保存できるように @syuilo
|
||||||
|
- 連合チャートにPub&Subを追加 @syuilo
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
- Client: リアクションピッカーの高さが低くなったまま戻らないことがあるのを修正 @syuilo
|
- Client: リアクションピッカーの高さが低くなったまま戻らないことがあるのを修正 @syuilo
|
||||||
|
|
|
@ -831,6 +831,9 @@ themeColor: "テーマカラー"
|
||||||
size: "サイズ"
|
size: "サイズ"
|
||||||
numberOfColumn: "列の数"
|
numberOfColumn: "列の数"
|
||||||
searchByGoogle: "ググる"
|
searchByGoogle: "ググる"
|
||||||
|
instanceDefaultLightTheme: "インスタンスデフォルトのライトテーマ"
|
||||||
|
instanceDefaultDarkTheme: "インスタンスデフォルトのダークテーマ"
|
||||||
|
instanceDefaultThemeDescription: "オブジェクト形式のテーマコードを記入します。"
|
||||||
|
|
||||||
_emailUnavailable:
|
_emailUnavailable:
|
||||||
used: "既に使用されています"
|
used: "既に使用されています"
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
export class instanceDefaultTheme1646143552768 {
|
||||||
|
name = 'instanceDefaultTheme1646143552768'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "defaultLightTheme" character varying(8192)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "defaultDarkTheme" character varying(8192)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "defaultDarkTheme"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "defaultLightTheme"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -344,6 +344,20 @@ export class Meta {
|
||||||
})
|
})
|
||||||
public feedbackUrl: string | null;
|
public feedbackUrl: string | null;
|
||||||
|
|
||||||
|
@Column('varchar', {
|
||||||
|
length: 8192,
|
||||||
|
default: null,
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
public defaultLightTheme: string | null;
|
||||||
|
|
||||||
|
@Column('varchar', {
|
||||||
|
length: 8192,
|
||||||
|
default: null,
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
public defaultDarkTheme: string | null;
|
||||||
|
|
||||||
@Column('boolean', {
|
@Column('boolean', {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
|
|
|
@ -36,6 +36,8 @@ export const paramDef = {
|
||||||
logoImageUrl: { type: 'string', nullable: true },
|
logoImageUrl: { type: 'string', nullable: true },
|
||||||
name: { type: 'string', nullable: true },
|
name: { type: 'string', nullable: true },
|
||||||
description: { type: 'string', nullable: true },
|
description: { type: 'string', nullable: true },
|
||||||
|
defaultLightTheme: { type: 'string', nullable: true },
|
||||||
|
defaultDarkTheme: { type: 'string', nullable: true },
|
||||||
localDriveCapacityMb: { type: 'integer' },
|
localDriveCapacityMb: { type: 'integer' },
|
||||||
remoteDriveCapacityMb: { type: 'integer' },
|
remoteDriveCapacityMb: { type: 'integer' },
|
||||||
cacheRemoteFiles: { type: 'boolean' },
|
cacheRemoteFiles: { type: 'boolean' },
|
||||||
|
@ -162,6 +164,14 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
set.description = ps.description;
|
set.description = ps.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ps.defaultLightTheme !== undefined) {
|
||||||
|
set.defaultLightTheme = ps.defaultLightTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ps.defaultDarkTheme !== undefined) {
|
||||||
|
set.defaultDarkTheme = ps.defaultDarkTheme;
|
||||||
|
}
|
||||||
|
|
||||||
if (ps.localDriveCapacityMb !== undefined) {
|
if (ps.localDriveCapacityMb !== undefined) {
|
||||||
set.localDriveCapacityMb = ps.localDriveCapacityMb;
|
set.localDriveCapacityMb = ps.localDriveCapacityMb;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,14 @@ export const meta = {
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
defaultDarkTheme: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false, nullable: true,
|
||||||
|
},
|
||||||
|
defaultLightTheme: {
|
||||||
|
type: 'string',
|
||||||
|
optional: false, nullable: true,
|
||||||
|
},
|
||||||
disableRegistration: {
|
disableRegistration: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
|
@ -504,6 +512,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
logoImageUrl: instance.logoImageUrl,
|
logoImageUrl: instance.logoImageUrl,
|
||||||
maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため
|
maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため
|
||||||
emojis: await Emojis.packMany(emojis),
|
emojis: await Emojis.packMany(emojis),
|
||||||
|
defaultLightTheme: instance.defaultLightTheme,
|
||||||
|
defaultDarkTheme: instance.defaultDarkTheme,
|
||||||
ads: ads.map(ad => ({
|
ads: ads.map(ad => ({
|
||||||
id: ad.id,
|
id: ad.id,
|
||||||
url: ad.url,
|
url: ad.url,
|
||||||
|
|
|
@ -15,6 +15,7 @@ if (localStorage.getItem('accounts') != null) {
|
||||||
|
|
||||||
import { computed, createApp, watch, markRaw, version as vueVersion } from 'vue';
|
import { computed, createApp, watch, markRaw, version as vueVersion } from 'vue';
|
||||||
import compareVersions from 'compare-versions';
|
import compareVersions from 'compare-versions';
|
||||||
|
import * as JSON5 from 'json5';
|
||||||
|
|
||||||
import widgets from '@/widgets';
|
import widgets from '@/widgets';
|
||||||
import directives from '@/directives';
|
import directives from '@/directives';
|
||||||
|
@ -159,7 +160,9 @@ if ($i && $i.token) {
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
fetchInstance().then(() => {
|
const fetchInstanceMetaPromise = fetchInstance();
|
||||||
|
|
||||||
|
fetchInstanceMetaPromise.then(() => {
|
||||||
localStorage.setItem('v', instance.version);
|
localStorage.setItem('v', instance.version);
|
||||||
|
|
||||||
// Init service worker
|
// Init service worker
|
||||||
|
@ -267,6 +270,14 @@ window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => {
|
||||||
});
|
});
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
fetchInstanceMetaPromise.then(() => {
|
||||||
|
if (defaultStore.state.themeInitial) {
|
||||||
|
if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON5.parse(instance.defaultLightTheme));
|
||||||
|
if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON5.parse(instance.defaultDarkTheme));
|
||||||
|
defaultStore.set('themeInitial', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// shortcut
|
// shortcut
|
||||||
document.addEventListener('keydown', makeHotkey({
|
document.addEventListener('keydown', makeHotkey({
|
||||||
'd': () => {
|
'd': () => {
|
||||||
|
|
|
@ -31,6 +31,16 @@
|
||||||
<template #caption>#RRGGBB</template>
|
<template #caption>#RRGGBB</template>
|
||||||
</FormInput>
|
</FormInput>
|
||||||
|
|
||||||
|
<FormTextarea v-model="defaultLightTheme" class="_formBlock">
|
||||||
|
<template #label>{{ $ts.instanceDefaultLightTheme }}</template>
|
||||||
|
<template #caption>{{ $ts.instanceDefaultThemeDescription }}</template>
|
||||||
|
</FormTextarea>
|
||||||
|
|
||||||
|
<FormTextarea v-model="defaultDarkTheme" class="_formBlock">
|
||||||
|
<template #label>{{ $ts.instanceDefaultDarkTheme }}</template>
|
||||||
|
<template #caption>{{ $ts.instanceDefaultThemeDescription }}</template>
|
||||||
|
</FormTextarea>
|
||||||
|
|
||||||
<FormInput v-model="tosUrl" class="_formBlock">
|
<FormInput v-model="tosUrl" class="_formBlock">
|
||||||
<template #prefix><i class="fas fa-link"></i></template>
|
<template #prefix><i class="fas fa-link"></i></template>
|
||||||
<template #label>{{ $ts.tosUrl }}</template>
|
<template #label>{{ $ts.tosUrl }}</template>
|
||||||
|
@ -176,6 +186,8 @@ export default defineComponent({
|
||||||
bannerUrl: null,
|
bannerUrl: null,
|
||||||
backgroundImageUrl: null,
|
backgroundImageUrl: null,
|
||||||
themeColor: null,
|
themeColor: null,
|
||||||
|
defaultLightTheme: null,
|
||||||
|
defaultDarkTheme: null,
|
||||||
enableLocalTimeline: false,
|
enableLocalTimeline: false,
|
||||||
enableGlobalTimeline: false,
|
enableGlobalTimeline: false,
|
||||||
pinnedUsers: '',
|
pinnedUsers: '',
|
||||||
|
@ -202,6 +214,8 @@ export default defineComponent({
|
||||||
this.bannerUrl = meta.bannerUrl;
|
this.bannerUrl = meta.bannerUrl;
|
||||||
this.backgroundImageUrl = meta.backgroundImageUrl;
|
this.backgroundImageUrl = meta.backgroundImageUrl;
|
||||||
this.themeColor = meta.themeColor;
|
this.themeColor = meta.themeColor;
|
||||||
|
this.defaultLightTheme = meta.defaultLightTheme;
|
||||||
|
this.defaultDarkTheme = meta.defaultDarkTheme;
|
||||||
this.maintainerName = meta.maintainerName;
|
this.maintainerName = meta.maintainerName;
|
||||||
this.maintainerEmail = meta.maintainerEmail;
|
this.maintainerEmail = meta.maintainerEmail;
|
||||||
this.enableLocalTimeline = !meta.disableLocalTimeline;
|
this.enableLocalTimeline = !meta.disableLocalTimeline;
|
||||||
|
@ -228,6 +242,8 @@ export default defineComponent({
|
||||||
bannerUrl: this.bannerUrl,
|
bannerUrl: this.bannerUrl,
|
||||||
backgroundImageUrl: this.backgroundImageUrl,
|
backgroundImageUrl: this.backgroundImageUrl,
|
||||||
themeColor: this.themeColor === '' ? null : this.themeColor,
|
themeColor: this.themeColor === '' ? null : this.themeColor,
|
||||||
|
defaultLightTheme: this.defaultLightTheme === '' ? null : this.defaultLightTheme,
|
||||||
|
defaultDarkTheme: this.defaultDarkTheme === '' ? null : this.defaultDarkTheme,
|
||||||
maintainerName: this.maintainerName,
|
maintainerName: this.maintainerName,
|
||||||
maintainerEmail: this.maintainerEmail,
|
maintainerEmail: this.maintainerEmail,
|
||||||
disableLocalTimeline: !this.enableLocalTimeline,
|
disableLocalTimeline: !this.enableLocalTimeline,
|
||||||
|
|
|
@ -87,6 +87,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, onActivated, onMounted, ref, watch } from 'vue';
|
import { computed, defineComponent, onActivated, onMounted, ref, watch } from 'vue';
|
||||||
|
import * as JSON5 from 'json5';
|
||||||
import FormSwitch from '@/components/form/switch.vue';
|
import FormSwitch from '@/components/form/switch.vue';
|
||||||
import FormSelect from '@/components/form/select.vue';
|
import FormSelect from '@/components/form/select.vue';
|
||||||
import FormGroup from '@/components/form/group.vue';
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
@ -99,6 +100,8 @@ import { isDeviceDarkmode } from '@/scripts/is-device-darkmode';
|
||||||
import { ColdDeviceStorage } from '@/store';
|
import { ColdDeviceStorage } from '@/store';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { defaultStore } from '@/store';
|
import { defaultStore } from '@/store';
|
||||||
|
import { instance } from '@/instance';
|
||||||
|
import { concat } from '@/scripts/array';
|
||||||
import { fetchThemes, getThemes } from '@/theme-store';
|
import { fetchThemes, getThemes } from '@/theme-store';
|
||||||
import * as symbols from '@/symbols';
|
import * as symbols from '@/symbols';
|
||||||
|
|
||||||
|
@ -122,7 +125,10 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
|
|
||||||
const installedThemes = ref(getThemes());
|
const installedThemes = ref(getThemes());
|
||||||
const themes = computed(() => builtinThemes.concat(installedThemes.value));
|
const instanceThemes = [];
|
||||||
|
if (instance.defaultLightTheme != null) instanceThemes.push(JSON5.parse(instance.defaultLightTheme));
|
||||||
|
if (instance.defaultDarkTheme != null) instanceThemes.push(JSON5.parse(instance.defaultDarkTheme));
|
||||||
|
const themes = computed(() => instanceThemes.concat(builtinThemes.concat(installedThemes.value)));
|
||||||
const darkThemes = computed(() => themes.value.filter(t => t.base === 'dark' || t.kind === 'dark'));
|
const darkThemes = computed(() => themes.value.filter(t => t.base === 'dark' || t.kind === 'dark'));
|
||||||
const lightThemes = computed(() => themes.value.filter(t => t.base === 'light' || t.kind === 'light'));
|
const lightThemes = computed(() => themes.value.filter(t => t.base === 'light' || t.kind === 'light'));
|
||||||
const darkTheme = ColdDeviceStorage.ref('darkTheme');
|
const darkTheme = ColdDeviceStorage.ref('darkTheme');
|
||||||
|
|
|
@ -230,6 +230,10 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||||
where: 'device',
|
where: 'device',
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
|
themeInitial: {
|
||||||
|
where: 'device',
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
aiChanMode: {
|
aiChanMode: {
|
||||||
where: 'device',
|
where: 'device',
|
||||||
default: false
|
default: false
|
||||||
|
|
Loading…
Reference in a new issue