summaryrefslogtreecommitdiff
path: root/packages/frontend/src/widgets/clock.vue
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2022-12-27 14:36:33 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2022-12-27 14:36:33 +0900
commit9384f5399da39e53855beb8e7f8ded1aa56bf72e (patch)
treece5959571a981b9c4047da3c7b3fd080aa44222c /packages/frontend/src/widgets/clock.vue
parentwip: retention for dashboard (diff)
downloadmisskey-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.vue203
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>