diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2022-12-27 14:36:33 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2022-12-27 14:36:33 +0900 |
| commit | 9384f5399da39e53855beb8e7f8ded1aa56bf72e (patch) | |
| tree | ce5959571a981b9c4047da3c7b3fd080aa44222c /packages/frontend/src/widgets/clock.vue | |
| parent | wip: retention for dashboard (diff) | |
| download | misskey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.tar.gz misskey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.tar.bz2 misskey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.zip | |
rename: client -> frontend
Diffstat (limited to 'packages/frontend/src/widgets/clock.vue')
| -rw-r--r-- | packages/frontend/src/widgets/clock.vue | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/packages/frontend/src/widgets/clock.vue b/packages/frontend/src/widgets/clock.vue new file mode 100644 index 0000000000..dc99b6631e --- /dev/null +++ b/packages/frontend/src/widgets/clock.vue @@ -0,0 +1,203 @@ +<template> +<MkContainer :naked="widgetProps.transparent" :show-header="false" class="mkw-clock"> + <div class="vubelbmv" :class="widgetProps.size"> + <div v-if="widgetProps.label === 'tz' || widgetProps.label === 'timeAndTz'" class="_monospace label a abbrev">{{ tzAbbrev }}</div> + <MkAnalogClock + class="clock" + :thickness="widgetProps.thickness" + :offset="tzOffset" + :graduations="widgetProps.graduations" + :fade-graduations="widgetProps.fadeGraduations" + :twentyfour="widgetProps.twentyFour" + :s-animation="widgetProps.sAnimation" + /> + <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> +</MkContainer> +</template> + +<script lang="ts" setup> +import { } from 'vue'; +import { useWidgetPropsManager, Widget, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget'; +import { GetFormResultType } from '@/scripts/form'; +import MkContainer from '@/components/MkContainer.vue'; +import MkAnalogClock from '@/components/MkAnalogClock.vue'; +import MkDigitalClock from '@/components/MkDigitalClock.vue'; +import { timezones } from '@/scripts/timezones'; +import { i18n } from '@/i18n'; + +const name = 'clock'; + +const widgetPropsDef = { + transparent: { + type: 'boolean' as const, + default: false, + }, + size: { + type: 'radio' as const, + default: 'medium', + options: [{ + value: 'small', label: i18n.ts.small, + }, { + value: 'medium', label: i18n.ts.medium, + }, { + value: 'large', label: i18n.ts.large, + }], + }, + thickness: { + type: 'radio' as const, + default: 0.2, + options: [{ + value: 0.1, label: 'thin', + }, { + value: 0.2, label: 'medium', + }, { + value: 0.3, label: 'thick', + }], + }, + graduations: { + type: 'radio' as const, + default: 'numbers', + options: [{ + value: 'none', label: 'None', + }, { + value: 'dots', label: 'Dots', + }, { + value: 'numbers', label: 'Numbers', + }], + }, + fadeGraduations: { + type: 'boolean' as const, + default: true, + }, + sAnimation: { + type: 'radio' as const, + default: 'elastic', + options: [{ + value: 'none', label: 'None', + }, { + value: 'elastic', label: 'Elastic', + }, { + value: 'easeOut', label: 'Ease out', + }], + }, + twentyFour: { + type: 'boolean' as const, + default: false, + }, + label: { + type: 'radio' as const, + default: 'none', + options: [{ + value: 'none', label: 'None', + }, { + value: 'time', label: 'Time', + }, { + value: 'tz', label: 'TZ', + }, { + value: 'timeAndTz', label: 'Time + TZ', + }], + }, + timezone: { + type: 'enum' as const, + default: null, + enum: [...timezones.map((tz) => ({ + label: tz.name, + value: tz.name.toLowerCase(), + })), { + label: '(auto)', + value: null, + }], + }, +}; + +type WidgetProps = GetFormResultType<typeof widgetPropsDef>; + +// 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない +//const props = defineProps<WidgetComponentProps<WidgetProps>>(); +//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +const props = defineProps<{ widget?: Widget<WidgetProps>; }>(); +const emit = defineEmits<{ (ev: 'updateProps', props: WidgetProps); }>(); + +const { widgetProps, configure } = useWidgetPropsManager(name, + widgetPropsDef, + props, + emit, +); + +const tzAbbrev = $computed(() => (widgetProps.timezone === null + ? timezones.find((tz) => tz.name.toLowerCase() === Intl.DateTimeFormat().resolvedOptions().timeZone.toLowerCase())?.abbrev + : timezones.find((tz) => tz.name.toLowerCase() === widgetProps.timezone)?.abbrev) ?? '?'); + +const tzOffset = $computed(() => widgetProps.timezone === null + ? 0 - new Date().getTimezoneOffset() + : timezones.find((tz) => tz.name.toLowerCase() === widgetProps.timezone)?.offset ?? 0); + +const tzOffsetLabel = $computed(() => (tzOffset >= 0 ? '+' : '-') + Math.floor(tzOffset / 60).toString().padStart(2, '0') + ':' + (tzOffset % 60).toString().padStart(2, '0')); + +defineExpose<WidgetComponentExpose>({ + name, + configure, + id: props.widget ? props.widget.id : null, +}); +</script> + +<style lang="scss" scoped> +.vubelbmv { + position: relative; + + > .label { + position: absolute; + opacity: 0.7; + + &.a { + top: 14px; + left: 14px; + } + + &.b { + top: 14px; + right: 14px; + } + + &.c { + bottom: 14px; + left: 14px; + } + + &.d { + bottom: 14px; + right: 14px; + } + } + + > .clock { + margin: auto; + } + + &.small { + padding: 12px; + + > .clock { + height: 100px; + } + } + + &.medium { + padding: 14px; + + > .clock { + height: 150px; + } + } + + &.large { + padding: 16px; + + > .clock { + height: 200px; + } + } +} +</style> |