mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-01 20:39:18 +00:00
refactor: fit user message in screen
This commit is contained in:
committed by
Carlos Valente
parent
66083813f9
commit
bc6b7c5596
@@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* Copied from
|
||||||
|
* https://github.com/namhong2001/react-textfit/blob/master/index.tsx
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { HTMLAttributes, PropsWithChildren, useCallback, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
|
import { bsearch } from './fitText.utils';
|
||||||
|
|
||||||
|
interface FitTextProps extends HTMLAttributes<HTMLDivElement> {
|
||||||
|
mode?: 'single' | 'multi';
|
||||||
|
min?: number; // inclusive
|
||||||
|
max?: number; // inclusive
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FitText(props: PropsWithChildren<FitTextProps>) {
|
||||||
|
const { children, mode = 'multi', min = 16, max = 256, ...elementProps } = props;
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const isOverflown = useCallback(() => {
|
||||||
|
const el = ref.current;
|
||||||
|
if (!el) return false;
|
||||||
|
return el.scrollHeight > el.clientHeight || el.scrollWidth > el.clientWidth;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const setFontSize = useCallback(() => {
|
||||||
|
const el = ref.current;
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
const originVisibility = el.style.visibility;
|
||||||
|
|
||||||
|
el.style.visibility = 'hidden';
|
||||||
|
const fontSize = bsearch(min, max + 1, (mid) => {
|
||||||
|
el.style.fontSize = `${mid}px`;
|
||||||
|
return !isOverflown();
|
||||||
|
});
|
||||||
|
el.style.fontSize = `${fontSize}px`;
|
||||||
|
el.style.visibility = originVisibility;
|
||||||
|
}, [isOverflown, min, max]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const el = ref.current;
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
setFontSize();
|
||||||
|
const observer = new ResizeObserver(setFontSize);
|
||||||
|
observer.observe(el);
|
||||||
|
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, [children, mode, setFontSize]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
style={{
|
||||||
|
whiteSpace: mode === 'single' ? 'nowrap' : 'normal',
|
||||||
|
}}
|
||||||
|
{...elementProps}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* @param low inclusive, must be true on predicate function
|
||||||
|
* @param high exclusive,
|
||||||
|
* @param predicate predicate function
|
||||||
|
*/
|
||||||
|
export const bsearch = (low: number, high: number, predicate: (mid: number) => boolean): number => {
|
||||||
|
while (low < high) {
|
||||||
|
const mid = Math.floor((low + high) / 2);
|
||||||
|
if (mid === low) break;
|
||||||
|
|
||||||
|
if (predicate(mid)) {
|
||||||
|
low = mid;
|
||||||
|
} else {
|
||||||
|
high = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return low;
|
||||||
|
};
|
||||||
@@ -167,36 +167,28 @@
|
|||||||
|
|
||||||
.message-overlay {
|
.message-overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background-color: $viewer-overlay-bg-color;
|
padding: 2vw;
|
||||||
z-index: -1;
|
background: var(--background-color-override, $viewer-background-color);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: $viewer-transition-time;
|
transition: opacity $viewer-transition-time;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
&--active {
|
&--active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: $viewer-transition-time;
|
|
||||||
transition-property: opacity;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
width: inherit;
|
display: grid;
|
||||||
padding: 2vw;
|
place-content: center;
|
||||||
position: absolute;
|
height: 100%;
|
||||||
top: 50%;
|
width: 100%;
|
||||||
left: 50%;
|
|
||||||
color: $viewer-color;
|
color: var(--color-override, $viewer-color);
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
-ms-transform: translate(-50%, -50%);
|
|
||||||
font-size: 15vw;
|
|
||||||
line-height: 30vh;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
} from 'ontime-types';
|
} from 'ontime-types';
|
||||||
|
|
||||||
import { overrideStylesURL } from '../../../common/api/constants';
|
import { overrideStylesURL } from '../../../common/api/constants';
|
||||||
|
import { FitText } from '../../../common/components/fit-text/FitText';
|
||||||
import MultiPartProgressBar from '../../../common/components/multi-part-progress-bar/MultiPartProgressBar';
|
import MultiPartProgressBar from '../../../common/components/multi-part-progress-bar/MultiPartProgressBar';
|
||||||
import TitleCard from '../../../common/components/title-card/TitleCard';
|
import TitleCard from '../../../common/components/title-card/TitleCard';
|
||||||
import ViewParamsEditor from '../../../common/components/view-params-editor/ViewParamsEditor';
|
import ViewParamsEditor from '../../../common/components/view-params-editor/ViewParamsEditor';
|
||||||
@@ -163,7 +164,9 @@ export default function Timer(props: TimerProps) {
|
|||||||
<div className={showBlackout ? 'blackout blackout--active' : 'blackout'} />
|
<div className={showBlackout ? 'blackout blackout--active' : 'blackout'} />
|
||||||
{!userOptions.hideMessage && (
|
{!userOptions.hideMessage && (
|
||||||
<div className={showOverlay ? 'message-overlay message-overlay--active' : 'message-overlay'}>
|
<div className={showOverlay ? 'message-overlay message-overlay--active' : 'message-overlay'}>
|
||||||
<div className={`message ${showBlinking ? 'blink' : ''}`}>{pres.text}</div>
|
<FitText mode='multi' min={32} max={256} className={`message ${showBlinking ? 'blink' : ''}`}>
|
||||||
|
{pres.text}
|
||||||
|
</FitText>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ $viewer-background-color: $ui-black; // --background-color-override
|
|||||||
$viewer-color: rgba(white, 80%); // --color-override
|
$viewer-color: rgba(white, 80%); // --color-override
|
||||||
$viewer-secondary-color: rgba(white, 45%); // --secondary-color-override
|
$viewer-secondary-color: rgba(white, 45%); // --secondary-color-override
|
||||||
$viewer-card-bg-color: rgba(white, 7%); // --card-background-color-override
|
$viewer-card-bg-color: rgba(white, 7%); // --card-background-color-override
|
||||||
$viewer-overlay-bg-color: rgba(black, 90%);
|
|
||||||
$element-border-radius: 8px;
|
$element-border-radius: 8px;
|
||||||
|
|
||||||
// Properties related to timer
|
// Properties related to timer
|
||||||
|
|||||||
Reference in New Issue
Block a user