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