mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-13 08:55:48 +01:00
feat: remove location based timezone resolving (#1680)
This commit is contained in:
@@ -75,7 +75,6 @@
|
|||||||
"axios": "^1.0.0",
|
"axios": "^1.0.0",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"better-sqlite3": "^8.6.0",
|
"better-sqlite3": "^8.6.0",
|
||||||
"browser-geo-tz": "^0.0.4",
|
|
||||||
"consola": "^3.0.0",
|
"consola": "^3.0.0",
|
||||||
"cookies": "^0.8.0",
|
"cookies": "^0.8.0",
|
||||||
"cookies-next": "^2.1.1",
|
"cookies-next": "^2.1.1",
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
"description": "Displays the current date and time.",
|
"description": "Displays the current date and time.",
|
||||||
"settings": {
|
"settings": {
|
||||||
"title": "Settings for Date and Time widget",
|
"title": "Settings for Date and Time widget",
|
||||||
|
"timezone":{
|
||||||
|
"label":"Timezone",
|
||||||
|
"info":"Select the name of your timezone, find yours here: "
|
||||||
|
},
|
||||||
|
"customTitle":{
|
||||||
|
"label":"City name or custom title"
|
||||||
|
},
|
||||||
"display24HourFormat": {
|
"display24HourFormat": {
|
||||||
"label": "Display full time (24-hour)"
|
"label": "Display full time (24-hour)"
|
||||||
},
|
},
|
||||||
@@ -13,18 +20,12 @@
|
|||||||
"hide": "Hide Date"
|
"hide": "Hide Date"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"enableTimezone": {
|
|
||||||
"label": "Display a custom Timezone"
|
|
||||||
},
|
|
||||||
"timezoneLocation": {
|
|
||||||
"label": "Timezone Location"
|
|
||||||
},
|
|
||||||
"titleState": {
|
"titleState": {
|
||||||
"label": "City title",
|
"label": "Clock title",
|
||||||
"info": "In case you activate the Timezone option, the name of the city and the timezone code can be shown.<br/>You can also show the city alone or even show none.",
|
"info": "The custom title and the timezone code can be shown on your widget.<br/>You can also show the city alone, show none,<br/>or even show the timezone alone when both are selected but no title is provided.",
|
||||||
"data": {
|
"data": {
|
||||||
"both": "City and Timezone",
|
"both": "Title and Timezone",
|
||||||
"city": "City only",
|
"city": "Title only",
|
||||||
"none": "None"
|
"none": "None"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
{info && <InfoCard message={t(`descriptor.settings.${key}.info`)} link={link} />}
|
{info && <InfoCard message={t(`descriptor.settings.${key}.info`)} link={link} />}
|
||||||
</Group>
|
</Group>
|
||||||
<Select
|
<Select
|
||||||
|
searchable
|
||||||
defaultValue={option.defaultValue}
|
defaultValue={option.defaultValue}
|
||||||
data={data}
|
data={data}
|
||||||
value={value as string}
|
value={value as string}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import { overseerrRouter } from './routers/overseerr';
|
|||||||
import { passwordRouter } from './routers/password';
|
import { passwordRouter } from './routers/password';
|
||||||
import { rssRouter } from './routers/rss';
|
import { rssRouter } from './routers/rss';
|
||||||
import { smartHomeEntityStateRouter } from './routers/smart-home/entity-state';
|
import { smartHomeEntityStateRouter } from './routers/smart-home/entity-state';
|
||||||
import { timezoneRouter } from './routers/timezone';
|
|
||||||
import { usenetRouter } from './routers/usenet/router';
|
import { usenetRouter } from './routers/usenet/router';
|
||||||
import { userRouter } from './routers/user';
|
import { userRouter } from './routers/user';
|
||||||
import { weatherRouter } from './routers/weather';
|
import { weatherRouter } from './routers/weather';
|
||||||
@@ -40,7 +39,6 @@ export const rootRouter = createTRPCRouter({
|
|||||||
mediaRequest: mediaRequestsRouter,
|
mediaRequest: mediaRequestsRouter,
|
||||||
mediaServer: mediaServerRouter,
|
mediaServer: mediaServerRouter,
|
||||||
overseerr: overseerrRouter,
|
overseerr: overseerrRouter,
|
||||||
timezone: timezoneRouter,
|
|
||||||
usenet: usenetRouter,
|
usenet: usenetRouter,
|
||||||
weather: weatherRouter,
|
weather: weatherRouter,
|
||||||
invites: inviteRouter,
|
invites: inviteRouter,
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import { createTRPCRouter, publicProcedure } from '../trpc';
|
|
||||||
|
|
||||||
const GeoTz = require('browser-geo-tz/dist/geotz.js');
|
|
||||||
|
|
||||||
export const timezoneRouter = createTRPCRouter({
|
|
||||||
at: publicProcedure
|
|
||||||
.input(
|
|
||||||
z.object({
|
|
||||||
longitude: z.number(),
|
|
||||||
latitude: z.number(),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.query(async ({ input }) => {
|
|
||||||
const timezone = await GeoTz.find(input.latitude, input.longitude);
|
|
||||||
return Array.isArray(timezone) ? timezone[0] : timezone;
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
@@ -8,10 +8,8 @@ import utc from 'dayjs/plugin/utc';
|
|||||||
import { useSession } from 'next-auth/react';
|
import { useSession } from 'next-auth/react';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { getLanguageByCode } from '~/tools/language';
|
import { getLanguageByCode } from '~/tools/language';
|
||||||
import { api } from '~/utils/api';
|
|
||||||
|
|
||||||
import { defineWidget } from '../helper';
|
import { defineWidget } from '../helper';
|
||||||
import { WidgetLoading } from '../loading';
|
|
||||||
import { IWidget } from '../widgets';
|
import { IWidget } from '../widgets';
|
||||||
|
|
||||||
dayjs.extend(advancedFormat);
|
dayjs.extend(advancedFormat);
|
||||||
@@ -22,6 +20,17 @@ const definition = defineWidget({
|
|||||||
id: 'date',
|
id: 'date',
|
||||||
icon: IconClock,
|
icon: IconClock,
|
||||||
options: {
|
options: {
|
||||||
|
timezone: {
|
||||||
|
type: 'select',
|
||||||
|
data: () => Intl.supportedValuesOf('timeZone').map((value) => ({ value, label: value })),
|
||||||
|
defaultValue: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||||
|
info: true,
|
||||||
|
infoLink: "https://www.timeanddate.com/time/map/",
|
||||||
|
},
|
||||||
|
customTitle: {
|
||||||
|
type: 'text',
|
||||||
|
defaultValue: '',
|
||||||
|
},
|
||||||
display24HourFormat: {
|
display24HourFormat: {
|
||||||
type: 'switch',
|
type: 'switch',
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
@@ -41,18 +50,6 @@ const definition = defineWidget({
|
|||||||
{ value: 'MM/DD', label: dayjs().format('MM/DD') },
|
{ value: 'MM/DD', label: dayjs().format('MM/DD') },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
enableTimezone: {
|
|
||||||
type: 'switch',
|
|
||||||
defaultValue: false,
|
|
||||||
},
|
|
||||||
timezoneLocation: {
|
|
||||||
type: 'location',
|
|
||||||
defaultValue: {
|
|
||||||
name: 'Paris',
|
|
||||||
latitude: 48.85341,
|
|
||||||
longitude: 2.3488,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
titleState: {
|
titleState: {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
defaultValue: 'both',
|
defaultValue: 'both',
|
||||||
@@ -81,16 +78,7 @@ function DateTile({ widget }: DateTileProps) {
|
|||||||
const { cx, classes } = useStyles();
|
const { cx, classes } = useStyles();
|
||||||
const { data: sessionData } = useSession();
|
const { data: sessionData } = useSession();
|
||||||
const [now, setDate] = useState(new Date());
|
const [now, setDate] = useState(new Date());
|
||||||
const { data, isFetching } = api.timezone.at.useQuery(
|
|
||||||
{
|
|
||||||
latitude: widget.properties.timezoneLocation.latitude,
|
|
||||||
longitude: widget.properties.timezoneLocation.longitude,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
enabled: location !== undefined && widget.properties.enableTimezone,
|
|
||||||
retry: false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Refresh the time every second
|
// Refresh the time every second
|
||||||
const interval = setInterval(() => setDate(new Date()), 1000);
|
const interval = setInterval(() => setDate(new Date()), 1000);
|
||||||
@@ -100,22 +88,21 @@ function DateTile({ widget }: DateTileProps) {
|
|||||||
const language = getLanguageByCode(sessionData?.user.language ?? 'en');
|
const language = getLanguageByCode(sessionData?.user.language ?? 'en');
|
||||||
dayjs.locale(language.locale);
|
dayjs.locale(language.locale);
|
||||||
|
|
||||||
if (isFetching) return <WidgetLoading />;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack ref={ref} className={cx(classes.wrapper, 'dashboard-tile-clock-wrapper')}>
|
<Stack ref={ref} className={cx(classes.wrapper, 'dashboard-tile-clock-wrapper')}>
|
||||||
{widget.properties.enableTimezone && widget.properties.titleState !== 'none' && (
|
{widget.properties.titleState !== 'none' &&
|
||||||
<Text
|
(widget.properties.customTitle.length > 0 || widget.properties.titleState === 'both') && (
|
||||||
size={width < 150 ? 'sm' : 'lg'}
|
<Text
|
||||||
className={cx(classes.extras, 'dashboard-tile-clock-city')}
|
size={width < 150 ? 'sm' : 'lg'}
|
||||||
>
|
className={cx(classes.extras, 'dashboard-tile-clock-city')}
|
||||||
{isFetching}
|
>
|
||||||
{widget.properties.timezoneLocation.name}
|
{widget.properties.customTitle.length > 0 && widget.properties.customTitle}
|
||||||
{widget.properties.titleState === 'both' && dayjs(now).tz(data).format(' (z)')}
|
{widget.properties.titleState === 'both' &&
|
||||||
</Text>
|
dayjs(now).tz(widget.properties.timezone).format(' (z)')}
|
||||||
)}
|
</Text>
|
||||||
|
)}
|
||||||
<Text className={cx(classes.clock, 'dashboard-tile-clock-hour')}>
|
<Text className={cx(classes.clock, 'dashboard-tile-clock-hour')}>
|
||||||
{dayjs(now).tz(data).format(formatString)}
|
{dayjs(now).tz(widget.properties.timezone).format(formatString)}
|
||||||
</Text>
|
</Text>
|
||||||
{!widget.properties.dateFormat.includes('hide') && (
|
{!widget.properties.dateFormat.includes('hide') && (
|
||||||
<Text
|
<Text
|
||||||
@@ -123,7 +110,7 @@ function DateTile({ widget }: DateTileProps) {
|
|||||||
pt="0.2rem"
|
pt="0.2rem"
|
||||||
className={cx(classes.extras, 'dashboard-tile-clock-date')}
|
className={cx(classes.extras, 'dashboard-tile-clock-date')}
|
||||||
>
|
>
|
||||||
{dayjs(now).tz(data).format(widget.properties.dateFormat)}
|
{dayjs(now).tz(widget.properties.timezone).format(widget.properties.dateFormat)}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
Reference in New Issue
Block a user