mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-04 15:34:13 +00:00 
			
		
		
		
	enhance(client): improve clock widget
This commit is contained in:
		
							parent
							
								
									3a9da78901
								
							
						
					
					
						commit
						b31f09692a
					
				
					 3 changed files with 110 additions and 68 deletions
				
			
		
							
								
								
									
										77
									
								
								packages/client/src/components/digital-clock.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								packages/client/src/components/digital-clock.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,77 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<span class="zjobosdg">
 | 
				
			||||||
 | 
						<span v-text="hh"></span>
 | 
				
			||||||
 | 
						<span class="colon" :class="{ showColon }">:</span>
 | 
				
			||||||
 | 
						<span v-text="mm"></span>
 | 
				
			||||||
 | 
						<span v-if="showS" class="colon" :class="{ showColon }">:</span>
 | 
				
			||||||
 | 
						<span v-if="showS" v-text="ss"></span>
 | 
				
			||||||
 | 
						<span v-if="showMs" class="colon" :class="{ showColon }">:</span>
 | 
				
			||||||
 | 
						<span v-if="showMs" v-text="ms"></span>
 | 
				
			||||||
 | 
					</span>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import { onUnmounted, ref, watch } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = withDefaults(defineProps<{
 | 
				
			||||||
 | 
						showS?: boolean;
 | 
				
			||||||
 | 
						showMs?: boolean;
 | 
				
			||||||
 | 
						offset?: number;
 | 
				
			||||||
 | 
					}>(), {
 | 
				
			||||||
 | 
						showS: true,
 | 
				
			||||||
 | 
						showMs: false,
 | 
				
			||||||
 | 
						offset: 0 - new Date().getTimezoneOffset(),
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let intervalId;
 | 
				
			||||||
 | 
					const hh = ref('');
 | 
				
			||||||
 | 
					const mm = ref('');
 | 
				
			||||||
 | 
					const ss = ref('');
 | 
				
			||||||
 | 
					const ms = ref('');
 | 
				
			||||||
 | 
					const showColon = ref(false);
 | 
				
			||||||
 | 
					let prevSec: number | null = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(showColon, (v) => {
 | 
				
			||||||
 | 
						if (v) {
 | 
				
			||||||
 | 
							window.setTimeout(() => {
 | 
				
			||||||
 | 
								showColon.value = false;
 | 
				
			||||||
 | 
							}, 30);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const tick = () => {
 | 
				
			||||||
 | 
						const now = new Date();
 | 
				
			||||||
 | 
						now.setMinutes(now.getMinutes() + (new Date().getTimezoneOffset() + props.offset));
 | 
				
			||||||
 | 
						hh.value = now.getHours().toString().padStart(2, '0');
 | 
				
			||||||
 | 
						mm.value = now.getMinutes().toString().padStart(2, '0');
 | 
				
			||||||
 | 
						ss.value = now.getSeconds().toString().padStart(2, '0');
 | 
				
			||||||
 | 
						ms.value = Math.floor(now.getMilliseconds() / 10).toString().padStart(2, '0');
 | 
				
			||||||
 | 
						if (now.getSeconds() !== prevSec) showColon.value = true;
 | 
				
			||||||
 | 
						prevSec = now.getSeconds();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tick();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(() => props.showMs, () => {
 | 
				
			||||||
 | 
						if (intervalId) window.clearInterval(intervalId);
 | 
				
			||||||
 | 
						intervalId = window.setInterval(tick, props.showMs ? 10 : 1000);
 | 
				
			||||||
 | 
					}, { immediate: true });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					onUnmounted(() => {
 | 
				
			||||||
 | 
						window.clearInterval(intervalId);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.zjobosdg {
 | 
				
			||||||
 | 
						> .colon {
 | 
				
			||||||
 | 
							opacity: 0;
 | 
				
			||||||
 | 
							transition: opacity 1s ease;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&.showColon {
 | 
				
			||||||
 | 
								opacity: 1;
 | 
				
			||||||
 | 
								transition: opacity 0s;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<MkContainer :naked="widgetProps.transparent" :show-header="false" class="mkw-clock">
 | 
					<MkContainer :naked="widgetProps.transparent" :show-header="false" class="mkw-clock">
 | 
				
			||||||
	<div class="vubelbmv" :class="widgetProps.size">
 | 
						<div class="vubelbmv" :class="widgetProps.size">
 | 
				
			||||||
		<div v-if="widgetProps.showLabel" class="label abbrev">{{ tzAbbrev }}</div>
 | 
							<div v-if="widgetProps.label === 'tz' || widgetProps.label === 'timeAndTz'" class="_monospace label a abbrev">{{ tzAbbrev }}</div>
 | 
				
			||||||
		<MkAnalogClock
 | 
							<MkAnalogClock
 | 
				
			||||||
			class="clock"
 | 
								class="clock"
 | 
				
			||||||
			:thickness="widgetProps.thickness"
 | 
								:thickness="widgetProps.thickness"
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,8 @@
 | 
				
			||||||
			:fade-graduations="widgetProps.fadeGraduations"
 | 
								:fade-graduations="widgetProps.fadeGraduations"
 | 
				
			||||||
			:twentyfour="widgetProps.twentyFour"
 | 
								:twentyfour="widgetProps.twentyFour"
 | 
				
			||||||
		/>
 | 
							/>
 | 
				
			||||||
		<div v-if="widgetProps.showLabel" class="label offset">{{ tzOffsetLabel }}</div>
 | 
							<MkDigitalClock v-if="widgetProps.label === 'time' || widgetProps.label === 'timeAndTz'" class="_monospace label c time" :show-s="false" :offset="tzOffset"/>
 | 
				
			||||||
 | 
							<div v-if="widgetProps.label === 'tz' || widgetProps.label === 'timeAndTz'" class="_monospace label d offset">{{ tzOffsetLabel }}</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</MkContainer>
 | 
					</MkContainer>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					@ -21,6 +22,7 @@ import { useWidgetPropsManager, Widget, WidgetComponentEmits, WidgetComponentExp
 | 
				
			||||||
import { GetFormResultType } from '@/scripts/form';
 | 
					import { GetFormResultType } from '@/scripts/form';
 | 
				
			||||||
import MkContainer from '@/components/ui/container.vue';
 | 
					import MkContainer from '@/components/ui/container.vue';
 | 
				
			||||||
import MkAnalogClock from '@/components/analog-clock.vue';
 | 
					import MkAnalogClock from '@/components/analog-clock.vue';
 | 
				
			||||||
 | 
					import MkDigitalClock from '@/components/digital-clock.vue';
 | 
				
			||||||
import { timezones } from '@/scripts/timezones';
 | 
					import { timezones } from '@/scripts/timezones';
 | 
				
			||||||
import { i18n } from '@/i18n';
 | 
					import { i18n } from '@/i18n';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,9 +74,18 @@ const widgetPropsDef = {
 | 
				
			||||||
		type: 'boolean' as const,
 | 
							type: 'boolean' as const,
 | 
				
			||||||
		default: false,
 | 
							default: false,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	showLabel: {
 | 
						label: {
 | 
				
			||||||
		type: 'boolean' as const,
 | 
							type: 'radio' as const,
 | 
				
			||||||
		default: true,
 | 
							default: 'none',
 | 
				
			||||||
 | 
							options: [{
 | 
				
			||||||
 | 
								value: 'none', label: 'None',
 | 
				
			||||||
 | 
							}, {
 | 
				
			||||||
 | 
								value: 'time', label: 'Time',
 | 
				
			||||||
 | 
							}, {
 | 
				
			||||||
 | 
								value: 'tz', label: 'TZ',
 | 
				
			||||||
 | 
							}, {
 | 
				
			||||||
 | 
								value: 'timeAndTz', label: 'Time + TZ',
 | 
				
			||||||
 | 
							}],
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	timezone: {
 | 
						timezone: {
 | 
				
			||||||
		type: 'enum' as const,
 | 
							type: 'enum' as const,
 | 
				
			||||||
| 
						 | 
					@ -125,16 +136,25 @@ defineExpose<WidgetComponentExpose>({
 | 
				
			||||||
	position: relative;
 | 
						position: relative;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .label {
 | 
						> .label {
 | 
				
			||||||
 | 
							position: absolute;
 | 
				
			||||||
		opacity: 0.7;
 | 
							opacity: 0.7;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		&.abbrev {
 | 
							&.a {
 | 
				
			||||||
			position: absolute;
 | 
					 | 
				
			||||||
			top: 14px;
 | 
								top: 14px;
 | 
				
			||||||
			left: 14px;
 | 
								left: 14px;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		&.offset {
 | 
							&.b {
 | 
				
			||||||
			position: absolute;
 | 
								top: 14px;
 | 
				
			||||||
 | 
								right: 14px;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&.c {
 | 
				
			||||||
 | 
								bottom: 14px;
 | 
				
			||||||
 | 
								left: 14px;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&.d {
 | 
				
			||||||
			bottom: 14px;
 | 
								bottom: 14px;
 | 
				
			||||||
			right: 14px;
 | 
								right: 14px;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -145,7 +165,7 @@ defineExpose<WidgetComponentExpose>({
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	&.small {
 | 
						&.small {
 | 
				
			||||||
		padding: 8px;
 | 
							padding: 12px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .clock {
 | 
							> .clock {
 | 
				
			||||||
			height: 100px;
 | 
								height: 100px;
 | 
				
			||||||
| 
						 | 
					@ -153,7 +173,7 @@ defineExpose<WidgetComponentExpose>({
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	&.medium {
 | 
						&.medium {
 | 
				
			||||||
		padding: 8px;
 | 
							padding: 14px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .clock {
 | 
							> .clock {
 | 
				
			||||||
			height: 150px;
 | 
								height: 150px;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,13 +2,7 @@
 | 
				
			||||||
<div class="mkw-digitalClock _monospace" :class="{ _panel: !widgetProps.transparent }" :style="{ fontSize: `${widgetProps.fontSize}em` }">
 | 
					<div class="mkw-digitalClock _monospace" :class="{ _panel: !widgetProps.transparent }" :style="{ fontSize: `${widgetProps.fontSize}em` }">
 | 
				
			||||||
	<div v-if="widgetProps.showLabel" class="label">{{ tzAbbrev }}</div>
 | 
						<div v-if="widgetProps.showLabel" class="label">{{ tzAbbrev }}</div>
 | 
				
			||||||
	<div class="time">
 | 
						<div class="time">
 | 
				
			||||||
		<span v-text="hh"></span>
 | 
							<MkDigitalClock :show-ms="widgetProps.showMs" :offset="tzOffset"/>
 | 
				
			||||||
		<span class="colon" :class="{ showColon }">:</span>
 | 
					 | 
				
			||||||
		<span v-text="mm"></span>
 | 
					 | 
				
			||||||
		<span class="colon" :class="{ showColon }">:</span>
 | 
					 | 
				
			||||||
		<span v-text="ss"></span>
 | 
					 | 
				
			||||||
		<span v-if="widgetProps.showMs" class="colon" :class="{ showColon }">:</span>
 | 
					 | 
				
			||||||
		<span v-if="widgetProps.showMs" v-text="ms"></span>
 | 
					 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<div v-if="widgetProps.showLabel" class="label">{{ tzOffsetLabel }}</div>
 | 
						<div v-if="widgetProps.showLabel" class="label">{{ tzOffsetLabel }}</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
| 
						 | 
					@ -19,6 +13,7 @@ import { onUnmounted, ref, watch } from 'vue';
 | 
				
			||||||
import { useWidgetPropsManager, Widget, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget';
 | 
					import { useWidgetPropsManager, Widget, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget';
 | 
				
			||||||
import { GetFormResultType } from '@/scripts/form';
 | 
					import { GetFormResultType } from '@/scripts/form';
 | 
				
			||||||
import { timezones } from '@/scripts/timezones';
 | 
					import { timezones } from '@/scripts/timezones';
 | 
				
			||||||
 | 
					import MkDigitalClock from '@/components/digital-clock.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const name = 'digitalClock';
 | 
					const name = 'digitalClock';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,44 +72,6 @@ const tzOffset = $computed(() => widgetProps.timezone === null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const tzOffsetLabel = $computed(() => (tzOffset >= 0 ? '+' : '-') + Math.floor(tzOffset / 60).toString().padStart(2, '0') + ':' + (tzOffset % 60).toString().padStart(2, '0'));
 | 
					const tzOffsetLabel = $computed(() => (tzOffset >= 0 ? '+' : '-') + Math.floor(tzOffset / 60).toString().padStart(2, '0') + ':' + (tzOffset % 60).toString().padStart(2, '0'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let intervalId;
 | 
					 | 
				
			||||||
const hh = ref('');
 | 
					 | 
				
			||||||
const mm = ref('');
 | 
					 | 
				
			||||||
const ss = ref('');
 | 
					 | 
				
			||||||
const ms = ref('');
 | 
					 | 
				
			||||||
const showColon = ref(false);
 | 
					 | 
				
			||||||
let prevSec: number | null = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
watch(showColon, (v) => {
 | 
					 | 
				
			||||||
	if (v) {
 | 
					 | 
				
			||||||
		window.setTimeout(() => {
 | 
					 | 
				
			||||||
			showColon.value = false;
 | 
					 | 
				
			||||||
		}, 30);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const tick = () => {
 | 
					 | 
				
			||||||
	const now = new Date();
 | 
					 | 
				
			||||||
	now.setMinutes(now.getMinutes() + (new Date().getTimezoneOffset() + tzOffset));
 | 
					 | 
				
			||||||
	hh.value = now.getHours().toString().padStart(2, '0');
 | 
					 | 
				
			||||||
	mm.value = now.getMinutes().toString().padStart(2, '0');
 | 
					 | 
				
			||||||
	ss.value = now.getSeconds().toString().padStart(2, '0');
 | 
					 | 
				
			||||||
	ms.value = Math.floor(now.getMilliseconds() / 10).toString().padStart(2, '0');
 | 
					 | 
				
			||||||
	if (now.getSeconds() !== prevSec) showColon.value = true;
 | 
					 | 
				
			||||||
	prevSec = now.getSeconds();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
tick();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
watch(() => widgetProps.showMs, () => {
 | 
					 | 
				
			||||||
	if (intervalId) window.clearInterval(intervalId);
 | 
					 | 
				
			||||||
	intervalId = window.setInterval(tick, widgetProps.showMs ? 10 : 1000);
 | 
					 | 
				
			||||||
}, { immediate: true });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
onUnmounted(() => {
 | 
					 | 
				
			||||||
	window.clearInterval(intervalId);
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
defineExpose<WidgetComponentExpose>({
 | 
					defineExpose<WidgetComponentExpose>({
 | 
				
			||||||
	name,
 | 
						name,
 | 
				
			||||||
	configure,
 | 
						configure,
 | 
				
			||||||
| 
						 | 
					@ -131,17 +88,5 @@ defineExpose<WidgetComponentExpose>({
 | 
				
			||||||
		font-size: 65%;
 | 
							font-size: 65%;
 | 
				
			||||||
		opacity: 0.7;
 | 
							opacity: 0.7;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	> .time {
 | 
					 | 
				
			||||||
		> .colon {
 | 
					 | 
				
			||||||
			opacity: 0;
 | 
					 | 
				
			||||||
			transition: opacity 1s ease;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			&.showColon {
 | 
					 | 
				
			||||||
				opacity: 1;
 | 
					 | 
				
			||||||
				transition: opacity 0s;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue