mirror of
https://github.com/mue/mue.git
synced 2026-07-17 05:54:14 +02:00
feat(greeting): add preview
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import variables from 'config/variables';
|
||||
import { useRef, useState, useEffect } from 'react';
|
||||
import { useRef, useState, useEffect, useCallback } from 'react';
|
||||
|
||||
import { appendNth, convertTimezone } from 'utils/date';
|
||||
import EventBus from 'utils/eventbus';
|
||||
@@ -10,29 +10,19 @@ import './greeting.scss';
|
||||
|
||||
const isEventsEnabled = localStorage.getItem('events') !== 'false';
|
||||
|
||||
function Greeting() {
|
||||
function Greeting({ isPreview = false, staticTime }) {
|
||||
const [greeting, setGreeting] = useState('');
|
||||
const timer = useRef(null);
|
||||
const greetingRef = useRef(null);
|
||||
|
||||
/**
|
||||
* Change the greeting message for the events of Christmas, New Year and Halloween.
|
||||
* If the events setting is disabled, then the greeting message will not be changed.
|
||||
* @param {Date} time The current time.
|
||||
* @param {String} message The current greeting message.
|
||||
* @returns The message variable is being returned.
|
||||
*/
|
||||
|
||||
const doEvents = (time, message) => {
|
||||
if (!isEventsEnabled) {
|
||||
return message;
|
||||
}
|
||||
|
||||
// Get current month & day
|
||||
const month = time.getMonth();
|
||||
const date = time.getDate();
|
||||
|
||||
// Parse the customEvents from localStorage
|
||||
const customEvents = JSON.parse(localStorage.getItem('customEvents') || defaults.customEvents);
|
||||
|
||||
const event = customEvents.find((e) => e.month - 1 === month && e.date === date);
|
||||
@@ -43,115 +33,139 @@ function Greeting() {
|
||||
return message;
|
||||
};
|
||||
|
||||
/**
|
||||
* It takes a date object and returns the age of the person in years.
|
||||
* @param {Date} date The date of birth.
|
||||
* @returns The age of the person.
|
||||
* */
|
||||
const calculateAge = (date) => {
|
||||
const diff = Date.now() - date.getTime();
|
||||
const birthday = new Date(diff);
|
||||
return Math.abs(birthday.getUTCFullYear() - 1970);
|
||||
};
|
||||
|
||||
const getGreeting = (time = 60000 - (Date.now() % 60000)) => {
|
||||
timer.current = setTimeout(() => {
|
||||
let now = new Date();
|
||||
const timezone = localStorage.getItem('timezone');
|
||||
if (timezone && timezone !== 'auto') {
|
||||
now = convertTimezone(now, timezone);
|
||||
}
|
||||
const getGreeting = useCallback(
|
||||
(time = 60000 - (Date.now() % 60000)) => {
|
||||
if (isPreview) {
|
||||
// Use static time for preview
|
||||
const hour = staticTime.getHours();
|
||||
let message;
|
||||
|
||||
const hour = now.getHours();
|
||||
|
||||
let message;
|
||||
switch (true) {
|
||||
case hour < 12:
|
||||
message = variables.getMessage('widgets.greeting.morning');
|
||||
break;
|
||||
case hour < 18:
|
||||
message = variables.getMessage('widgets.greeting.afternoon');
|
||||
break;
|
||||
default:
|
||||
message = variables.getMessage('widgets.greeting.evening');
|
||||
break;
|
||||
}
|
||||
|
||||
// Events and custom
|
||||
const custom = localStorage.getItem('defaultGreetingMessage');
|
||||
if (custom === 'false') {
|
||||
message = '';
|
||||
} else {
|
||||
message = doEvents(now, message);
|
||||
}
|
||||
|
||||
// Name
|
||||
let name = '';
|
||||
const data = localStorage.getItem('greetingName');
|
||||
|
||||
if (typeof data === 'string') {
|
||||
if (data.replace(/\s/g, '').length > 0) {
|
||||
name = `, ${data.trim()}`;
|
||||
switch (true) {
|
||||
case hour < 12:
|
||||
message = variables.getMessage('widgets.greeting.morning');
|
||||
break;
|
||||
case hour < 18:
|
||||
message = variables.getMessage('widgets.greeting.afternoon');
|
||||
break;
|
||||
default:
|
||||
message = variables.getMessage('widgets.greeting.evening');
|
||||
break;
|
||||
}
|
||||
|
||||
const name = localStorage.getItem('greetingName');
|
||||
const nameString = name ? `, ${name.trim()}` : '';
|
||||
setGreeting(`${message}${nameString}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const birthday = localStorage.getItem('birthdayenabled');
|
||||
timer.current = setTimeout(() => {
|
||||
let now = new Date();
|
||||
const timezone = localStorage.getItem('timezone');
|
||||
if (timezone && timezone !== 'auto') {
|
||||
now = convertTimezone(now, timezone);
|
||||
}
|
||||
|
||||
if (custom === 'false' && birthday !== 'true') {
|
||||
name = name.replace(',', '');
|
||||
}
|
||||
const hour = now.getHours();
|
||||
|
||||
// Birthday
|
||||
if (birthday === 'true') {
|
||||
const birth = new Date(localStorage.getItem('birthday'));
|
||||
let message;
|
||||
switch (true) {
|
||||
case hour < 12:
|
||||
message = variables.getMessage('widgets.greeting.morning');
|
||||
break;
|
||||
case hour < 18:
|
||||
message = variables.getMessage('widgets.greeting.afternoon');
|
||||
break;
|
||||
default:
|
||||
message = variables.getMessage('widgets.greeting.evening');
|
||||
break;
|
||||
}
|
||||
|
||||
if (birth.getDate() === now.getDate() && birth.getMonth() === now.getMonth()) {
|
||||
if (localStorage.getItem('birthdayage') === 'true' && calculateAge(birth) !== 0) {
|
||||
const text = variables.getMessage('widgets.greeting.birthday').split(' ');
|
||||
message = `${text[0]} ${appendNth(calculateAge(birth))} ${text[1]}`;
|
||||
} else {
|
||||
message = variables.getMessage('widgets.greeting.birthday');
|
||||
const custom = localStorage.getItem('defaultGreetingMessage');
|
||||
if (custom === 'false') {
|
||||
message = '';
|
||||
} else {
|
||||
message = doEvents(now, message);
|
||||
}
|
||||
|
||||
let name = '';
|
||||
const data = localStorage.getItem('greetingName');
|
||||
|
||||
if (typeof data === 'string') {
|
||||
if (data.replace(/\s/g, '').length > 0) {
|
||||
name = `, ${data.trim()}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the state to the greeting string
|
||||
setGreeting(`${message}${name}`);
|
||||
const birthday = localStorage.getItem('birthdayenabled');
|
||||
|
||||
// Log the event when a greeting is shown
|
||||
Stats.postEvent('feature', 'greeting', 'shown');
|
||||
|
||||
getGreeting();
|
||||
}, time);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
EventBus.on('refresh', (data) => {
|
||||
if (data === 'greeting' || data === 'timezone') {
|
||||
if (localStorage.getItem('greeting') === 'false') {
|
||||
return (greetingRef.current.style.display = 'none');
|
||||
if (custom === 'false' && birthday !== 'true') {
|
||||
name = name.replace(',', '');
|
||||
}
|
||||
|
||||
timer.current = null;
|
||||
getGreeting(0);
|
||||
if (birthday === 'true') {
|
||||
const birth = new Date(localStorage.getItem('birthday'));
|
||||
|
||||
greetingRef.current.style.display = 'block';
|
||||
greetingRef.current.style.fontSize = `${
|
||||
1.6 * Number((localStorage.getItem('zoomGreeting') || defaults.zoomGreeting) / 100)
|
||||
}em`;
|
||||
}
|
||||
});
|
||||
if (birth.getDate() === now.getDate() && birth.getMonth() === now.getMonth()) {
|
||||
if (localStorage.getItem('birthdayage') === 'true' && calculateAge(birth) !== 0) {
|
||||
const text = variables.getMessage('widgets.greeting.birthday').split(' ');
|
||||
message = `${text[0]} ${appendNth(calculateAge(birth))} ${text[1]}`;
|
||||
} else {
|
||||
message = variables.getMessage('widgets.greeting.birthday');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
greetingRef.current.style.fontSize = `${
|
||||
1.6 * Number((localStorage.getItem('zoomGreeting') || defaults.zoomGreeting) / 100)
|
||||
}em`;
|
||||
setGreeting(`${message}${name}`);
|
||||
|
||||
getGreeting(0);
|
||||
if (!isPreview) {
|
||||
Stats.postEvent('feature', 'greeting', 'shown');
|
||||
getGreeting();
|
||||
}
|
||||
}, time);
|
||||
},
|
||||
[isPreview, staticTime],
|
||||
);
|
||||
|
||||
return () => {
|
||||
EventBus.off('refresh');
|
||||
};
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
if (!isPreview) {
|
||||
EventBus.on('refresh', (data) => {
|
||||
if (data === 'greeting' || data === 'timezone') {
|
||||
if (localStorage.getItem('greeting') === 'false') {
|
||||
return (greetingRef.current.style.display = 'none');
|
||||
}
|
||||
|
||||
timer.current = null;
|
||||
getGreeting(0);
|
||||
|
||||
greetingRef.current.style.display = 'block';
|
||||
greetingRef.current.style.fontSize = `${
|
||||
1.6 * Number((localStorage.getItem('zoomGreeting') || defaults.zoomGreeting) / 100)
|
||||
}em`;
|
||||
}
|
||||
});
|
||||
|
||||
greetingRef.current.style.fontSize = `${
|
||||
1.6 * Number((localStorage.getItem('zoomGreeting') || defaults.zoomGreeting) / 100)
|
||||
}em`;
|
||||
|
||||
getGreeting(0);
|
||||
|
||||
return () => {
|
||||
EventBus.off('refresh');
|
||||
if (timer.current) {
|
||||
clearTimeout(timer.current);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
getGreeting(0);
|
||||
}
|
||||
}, [getGreeting, isPreview]);
|
||||
|
||||
return (
|
||||
<span className="greeting" ref={greetingRef}>
|
||||
|
||||
@@ -13,11 +13,13 @@ import { Checkbox, Switch, Text, TextareaAutosize } from 'components/Form/Settin
|
||||
import { Button } from 'components/Elements';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useTab } from 'components/Elements/MainModal/backend/TabContext';
|
||||
import { Hero, Preview, Controls } from 'components/Layout/Settings/Hero';
|
||||
|
||||
import defaults from './default';
|
||||
import defaultEvents from '../events.json';
|
||||
|
||||
import { MdEventNote, MdAdd, MdCancel, MdRefresh } from 'react-icons/md';
|
||||
import GreetingPreview from './GreetingPreview';
|
||||
|
||||
const GreetingOptions = () => {
|
||||
const { subSection } = useTab();
|
||||
@@ -296,8 +298,34 @@ const GreetingOptions = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{/*{header}*/}
|
||||
{subSection === 'events' ? (
|
||||
{subSection === '' && (
|
||||
<>
|
||||
<Hero>
|
||||
<Preview>
|
||||
<GreetingPreview />
|
||||
</Preview>
|
||||
<Controls
|
||||
title={variables.getMessage(`${GREETING_SECTION}.title`)}
|
||||
setting="greeting"
|
||||
category="greeting"
|
||||
element=".greeting"
|
||||
zoomSetting="zoomGreeting"
|
||||
visibilityToggle={true}
|
||||
/>
|
||||
</Hero>
|
||||
<Section
|
||||
id="events"
|
||||
title={variables.getMessage(`${GREETING_SECTION}.events`)}
|
||||
subtitle={variables.getMessage(`${GREETING_SECTION}.events_description`)}
|
||||
onClick={() => setEvents(true)}
|
||||
icon={<MdEventNote />}
|
||||
/>
|
||||
<PreferencesWrapper setting="greeting">
|
||||
<AdditionalOptions />
|
||||
</PreferencesWrapper>
|
||||
</>
|
||||
)}
|
||||
{subSection === 'events' && (
|
||||
<>
|
||||
<Row>
|
||||
<Content
|
||||
@@ -318,24 +346,6 @@ const GreetingOptions = () => {
|
||||
{BirthdayOptions()}
|
||||
{CustomEventsSection()}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Section
|
||||
id="events"
|
||||
title={variables.getMessage(`${GREETING_SECTION}.events`)}
|
||||
subtitle={variables.getMessage(`${GREETING_SECTION}.events_description`)}
|
||||
onClick={() => setEvents(true)}
|
||||
icon={<MdEventNote />}
|
||||
/>
|
||||
<PreferencesWrapper
|
||||
setting="greeting"
|
||||
zoomSetting="zoomGreeting"
|
||||
category="greeting"
|
||||
visibilityToggle={true}
|
||||
>
|
||||
<AdditionalOptions />
|
||||
</PreferencesWrapper>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
32
src/features/greeting/options/GreetingPreview.jsx
Normal file
32
src/features/greeting/options/GreetingPreview.jsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import Greeting from 'features/greeting/Greeting';
|
||||
|
||||
const GreetingPreview = ({ zoomLevel = 100 }) => {
|
||||
// Set a fixed time for preview (e.g. 10:30 AM)
|
||||
const previewTime = new Date();
|
||||
previewTime.setHours(10, 30, 0);
|
||||
|
||||
return (
|
||||
<AnimatePresence mode="crossfade">
|
||||
<motion.div
|
||||
className="absolute text-3xl"
|
||||
key="greeting-preview"
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: zoomLevel / 100,
|
||||
}}
|
||||
exit={{ opacity: 0, scale: 0.95 }}
|
||||
transition={{
|
||||
opacity: { duration: 0.2 },
|
||||
scale: { duration: 0.3, ease: 'anticipate' },
|
||||
}}
|
||||
>
|
||||
<Greeting isPreview={true} staticTime={previewTime} />
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
|
||||
export { GreetingPreview, GreetingPreview as default };
|
||||
Reference in New Issue
Block a user