feat(client): blur effect for modal
This commit is contained in:
		
							parent
							
								
									426c2fa5d1
								
							
						
					
					
						commit
						aae9bc4cf4
					
				
					 11 changed files with 64 additions and 76 deletions
				
			
		|  | @ -528,6 +528,7 @@ plugins: "プラグイン" | |||
| pluginInstallWarn: "信頼できないプラグインはインストールしないでください。" | ||||
| deck: "デッキ" | ||||
| undeck: "デッキ解除" | ||||
| useBlurEffectForModal: "モーダルにぼかし効果を使用" | ||||
| 
 | ||||
| _theme: | ||||
|   explore: "テーマを探す" | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="mk-dialog" :class="{ iconOnly }"> | ||||
| 	<transition :name="$store.state.device.animation ? 'bg-fade' : ''" appear> | ||||
| 		<div class="bg" ref="bg" @click="onBgClick" v-if="show"></div> | ||||
| 		<div class="bg _modalBg" ref="bg" @click="onBgClick" v-if="show"></div> | ||||
| 	</transition> | ||||
| 	<transition :name="$store.state.device.animation ? 'dialog' : ''" appear @after-leave="() => { destroyDom(); }"> | ||||
| 		<div class="main" ref="main" v-if="show"> | ||||
|  | @ -245,16 +245,6 @@ export default Vue.extend({ | |||
| 		width: initial; | ||||
| 	} | ||||
| 
 | ||||
| 	> .bg { | ||||
| 		display: block; | ||||
| 		position: fixed; | ||||
| 		top: 0; | ||||
| 		left: 0; | ||||
| 		width: 100%; | ||||
| 		height: 100%; | ||||
| 		background: rgba(0,0,0,0.7); | ||||
| 	} | ||||
| 
 | ||||
| 	> .main { | ||||
| 		display: block; | ||||
| 		position: fixed; | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="mk-modal" v-hotkey.global="keymap"> | ||||
| 	<transition :name="$store.state.device.animation ? 'bg-fade' : ''" appear> | ||||
| 		<div class="bg" ref="bg" v-if="show" @click="canClose ? close() : () => {}"></div> | ||||
| 		<div class="bg _modalBg" ref="bg" v-if="show" @click="canClose ? close() : () => {}"></div> | ||||
| 	</transition> | ||||
| 	<transition :name="$store.state.device.animation ? 'modal' : ''" appear @after-leave="() => { $emit('closed'); destroyDom(); }"> | ||||
| 		<div class="content" ref="content" v-if="show" @click.self="canClose ? close() : () => {}"><slot></slot></div> | ||||
|  | @ -60,13 +60,7 @@ export default Vue.extend({ | |||
| 
 | ||||
| .mk-modal { | ||||
| 	> .bg { | ||||
| 		position: fixed; | ||||
| 		top: 0; | ||||
| 		left: 0; | ||||
| 		z-index: 10000; | ||||
| 		width: 100%; | ||||
| 		height: 100%; | ||||
| 		background: var(--modalBg) | ||||
| 	} | ||||
| 
 | ||||
| 	> .content { | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="mk-popup" v-hotkey.global="keymap"> | ||||
| 	<transition :name="$store.state.device.animation ? 'bg-fade' : ''" appear> | ||||
| 		<div class="bg" ref="bg" @click="close()" v-if="show"></div> | ||||
| 		<div class="bg _modalBg" ref="bg" @click="close()" v-if="show"></div> | ||||
| 	</transition> | ||||
| 	<transition :name="$store.state.device.animation ? 'popup' : ''" appear @after-leave="() => { $emit('closed'); destroyDom(); }"> | ||||
| 		<div class="content" :class="{ fixed }" ref="content" v-if="show" :style="{ width: width ? width + 'px' : 'auto' }"><slot></slot></div> | ||||
|  | @ -128,13 +128,7 @@ export default Vue.extend({ | |||
| 
 | ||||
| .mk-popup { | ||||
| 	> .bg { | ||||
| 		position: fixed; | ||||
| 		top: 0; | ||||
| 		left: 0; | ||||
| 		z-index: 10000; | ||||
| 		width: 100%; | ||||
| 		height: 100%; | ||||
| 		background: var(--modalBg) | ||||
| 	} | ||||
| 
 | ||||
| 	> .content { | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="ulveipglmagnxfgvitaxyszerjwiqmwl"> | ||||
| <div class="ulveipgl"> | ||||
| 	<transition :name="$store.state.device.animation ? 'form-fade' : ''" appear @after-leave="$emit('closed');"> | ||||
| 		<div class="bg" ref="bg" v-if="show" @click="close()"></div> | ||||
| 		<div class="bg _modalBg" ref="bg" v-if="show" @click="close()"></div> | ||||
| 	</transition> | ||||
| 	<div class="main" ref="main" @click.self="close()" @keydown="onKeydown"> | ||||
| 		<transition :name="$store.state.device.animation ? 'form' : ''" appear | ||||
|  | @ -119,16 +119,9 @@ export default Vue.extend({ | |||
| 	opacity: 0; | ||||
| } | ||||
| 
 | ||||
| .ulveipglmagnxfgvitaxyszerjwiqmwl { | ||||
| .ulveipgl { | ||||
| 	> .bg { | ||||
| 		display: block; | ||||
| 		position: fixed; | ||||
| 		z-index: 10000; | ||||
| 		top: 0; | ||||
| 		left: 0; | ||||
| 		width: 100%; | ||||
| 		height: 100%; | ||||
| 		background: rgba(#000, 0.7); | ||||
| 	} | ||||
| 
 | ||||
| 	> .main { | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="mvcprjjd"> | ||||
| 	<transition name="nav-back"> | ||||
| 		<div class="nav-back" | ||||
| 		<div class="nav-back _modalBg" | ||||
| 			v-if="showing" | ||||
| 			@click="showing = false" | ||||
| 			@touchstart="showing = false" | ||||
|  | @ -320,13 +320,7 @@ export default Vue.extend({ | |||
| 	$nav-hide-threshold: 650px; // TODO: どこかに集約したい | ||||
| 
 | ||||
| 	> .nav-back { | ||||
| 		position: fixed; | ||||
| 		top: 0; | ||||
| 		left: 0; | ||||
| 		z-index: 1001; | ||||
| 		width: 100%; | ||||
| 		height: 100%; | ||||
| 		background: var(--modalBg); | ||||
| 	} | ||||
| 
 | ||||
| 	> .nav { | ||||
|  |  | |||
|  | @ -106,36 +106,17 @@ document.body.innerHTML = '<div id="app"></div>'; | |||
| 
 | ||||
| const store = createStore(); | ||||
| 
 | ||||
| window.addEventListener('storage', e => { | ||||
| 	if (e.key === 'vuex') { | ||||
| 		store.replaceState(JSON.parse(localStorage['vuex'])); | ||||
| 	} else if (e.key === 'i') { | ||||
| 		location.reload(); | ||||
| 	} | ||||
| }, false); | ||||
| 
 | ||||
| const os = new MiOS(store); | ||||
| 
 | ||||
| os.init(async () => { | ||||
| 	window.addEventListener('storage', e => { | ||||
| 		if (e.key === 'vuex') { | ||||
| 			store.replaceState(JSON.parse(localStorage['vuex'])); | ||||
| 		} else if (e.key === 'i') { | ||||
| 			location.reload(); | ||||
| 		} | ||||
| 	}, false); | ||||
| 
 | ||||
| 	store.watch(state => state.device.darkMode, darkMode => { | ||||
| 		import('./scripts/theme').then(({ builtinThemes }) => { | ||||
| 			const themes = builtinThemes.concat(store.state.device.themes); | ||||
| 			applyTheme(themes.find(x => x.id === (darkMode ? store.state.device.darkTheme : store.state.device.lightTheme))); | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	//#region Sync dark mode
 | ||||
| 	if (store.state.device.syncDeviceDarkMode) { | ||||
| 		store.commit('device/set', { key: 'darkMode', value: isDeviceDarkmode() }); | ||||
| 	} | ||||
| 
 | ||||
| 	window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => { | ||||
| 		if (store.state.device.syncDeviceDarkMode) { | ||||
| 			store.commit('device/set', { key: 'darkMode', value: mql.matches }); | ||||
| 		} | ||||
| 	}); | ||||
| 	//#endregion
 | ||||
| 
 | ||||
| 	//#region Fetch locale data
 | ||||
| 	const i18n = new VueI18n(); | ||||
| 
 | ||||
|  | @ -148,13 +129,6 @@ os.init(async () => { | |||
| 	}); | ||||
| 	//#endregion
 | ||||
| 
 | ||||
| 	if ('Notification' in window && store.getters.isSignedIn) { | ||||
| 		// 許可を得ていなかったらリクエスト
 | ||||
| 		if (Notification.permission === 'default') { | ||||
| 			Notification.requestPermission(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	const app = new Vue({ | ||||
| 		store: store, | ||||
| 		i18n, | ||||
|  | @ -228,6 +202,29 @@ os.init(async () => { | |||
| 	// マウント
 | ||||
| 	app.$mount('#app'); | ||||
| 
 | ||||
| 	store.watch(state => state.device.darkMode, darkMode => { | ||||
| 		import('./scripts/theme').then(({ builtinThemes }) => { | ||||
| 			const themes = builtinThemes.concat(store.state.device.themes); | ||||
| 			applyTheme(themes.find(x => x.id === (darkMode ? store.state.device.darkTheme : store.state.device.lightTheme))); | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	//#region Sync dark mode
 | ||||
| 	if (store.state.device.syncDeviceDarkMode) { | ||||
| 		store.commit('device/set', { key: 'darkMode', value: isDeviceDarkmode() }); | ||||
| 	} | ||||
| 
 | ||||
| 	window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => { | ||||
| 		if (store.state.device.syncDeviceDarkMode) { | ||||
| 			store.commit('device/set', { key: 'darkMode', value: mql.matches }); | ||||
| 		} | ||||
| 	}); | ||||
| 	//#endregion
 | ||||
| 
 | ||||
| 	store.watch(state => state.device.useBlurEffectForModal, v => { | ||||
| 		document.documentElement.style.setProperty('--modalBgFilter', v ? 'blur(4px)' : 'none'); | ||||
| 	}, { immediate: true }); | ||||
| 
 | ||||
| 	os.stream.on('emojiAdded', data => { | ||||
| 		// TODO
 | ||||
| 		//store.commit('instance/set', );
 | ||||
|  | @ -263,6 +260,13 @@ os.init(async () => { | |||
| 	} | ||||
| 
 | ||||
| 	if (store.getters.isSignedIn) { | ||||
| 		if ('Notification' in window) { | ||||
| 			// 許可を得ていなかったらリクエスト
 | ||||
| 			if (Notification.permission === 'default') { | ||||
| 				Notification.requestPermission(); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		const main = os.stream.useSharedConnection('main'); | ||||
| 
 | ||||
| 		// 自分の情報が更新されたとき
 | ||||
|  |  | |||
|  | @ -78,6 +78,7 @@ | |||
| 			<mk-switch v-model="imageNewTab">{{ $t('openImageInNewTab') }}</mk-switch> | ||||
| 			<mk-switch v-model="disableAnimatedMfm">{{ $t('disableAnimatedMfm') }}</mk-switch> | ||||
| 			<mk-switch v-model="reduceAnimation">{{ $t('reduceUiAnimation') }}</mk-switch> | ||||
| 			<mk-switch v-model="useBlurEffectForModal">{{ $t('useBlurEffectForModal') }}</mk-switch> | ||||
| 			<mk-switch v-model="useOsNativeEmojis"> | ||||
| 				{{ $t('useOsNativeEmojis') }} | ||||
| 				<template #desc><mfm text="🍮🍦🍭🍩🍰🍫🍬🥞🍪"/></template> | ||||
|  | @ -178,6 +179,11 @@ export default Vue.extend({ | |||
| 			set(value) { this.$store.commit('device/set', { key: 'animation', value: !value }); } | ||||
| 		}, | ||||
| 
 | ||||
| 		useBlurEffectForModal: { | ||||
| 			get() { return this.$store.state.device.useBlurEffectForModal; }, | ||||
| 			set(value) { this.$store.commit('device/set', { key: 'useBlurEffectForModal', value: value }); } | ||||
| 		}, | ||||
| 
 | ||||
| 		disableAnimatedMfm: { | ||||
| 			get() { return !this.$store.state.device.animatedMfm; }, | ||||
| 			set(value) { this.$store.commit('device/set', { key: 'animatedMfm', value: !value }); } | ||||
|  |  | |||
|  | @ -68,6 +68,7 @@ export const defaultDeviceSettings = { | |||
| 	disablePagesScript: true, | ||||
| 	enableInfiniteScroll: true, | ||||
| 	fixedWidgetsPosition: false, | ||||
| 	useBlurEffectForModal: true, | ||||
| 	roomGraphicsQuality: 'medium', | ||||
| 	roomUseOrthographicCamera: true, | ||||
| 	deckColumnAlign: 'left', | ||||
|  |  | |||
|  | @ -197,6 +197,16 @@ hr { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| ._modalBg { | ||||
| 	position: fixed; | ||||
| 	top: 0; | ||||
| 	left: 0; | ||||
| 	width: 100%; | ||||
| 	height: 100%; | ||||
| 	background: var(--modalBg); | ||||
| 	backdrop-filter: var(--modalBgFilter); | ||||
| } | ||||
| 
 | ||||
| ._button { | ||||
| 	appearance: none; | ||||
| 	padding: 0; | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| 		panelHeaderBg: '@panel', | ||||
| 		panelHeaderDivider: '@divider', | ||||
| 		panelBorder: '@divider', | ||||
| 		modalBg: 'rgba(255, 255, 255, 0.1)', | ||||
| 		messageBg: '#1d1d1d', | ||||
| 		deckColumnBorder: '@divider', | ||||
| 	}, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue