Skip to content

Commit

Permalink
Merge branch 'main' into native-ios
Browse files Browse the repository at this point in the history
  • Loading branch information
idoshamun authored Jan 16, 2025
2 parents 027d782 + 1d7ba28 commit f863d27
Show file tree
Hide file tree
Showing 21 changed files with 359 additions and 69 deletions.
2 changes: 1 addition & 1 deletion packages/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@tanstack/react-query-devtools": "^5.59.16",
"classnames": "^2.5.1",
"date-fns": "^2.25.0",
"date-fns-tz": "1.0.0",
"date-fns-tz": "1.2.2",
"dompurify": "^2.5.4",
"focus-visible": "^5.2.1",
"graphql": "^16.9.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@tanstack/react-query-devtools": "^4.35.3",
"classnames": "^2.3.1",
"date-fns": "^2.22.1",
"date-fns-tz": "1.0.0",
"date-fns-tz": "1.2.2",
"dompurify": "^2.3.0",
"graphql": "^15.5.0",
"graphql-request": "^3.4.0",
Expand Down Expand Up @@ -57,7 +57,7 @@
"babel-jest": "^26.6.3",
"babel-plugin-dynamic-import-node": "^2.3.3",
"date-fns": "^2.25.0",
"date-fns-tz": "1.0.0",
"date-fns-tz": "1.2.2",
"dompurify": "^2.5.4",
"eslint": "^7.32.0",
"eslint-config-airbnb-typescript": "^12.3.1",
Expand Down
38 changes: 36 additions & 2 deletions packages/shared/src/components/Icon.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ComponentProps, ReactElement } from 'react';
import React from 'react';
import type { ComponentProps, ReactElement, ReactNode } from 'react';
import React, { Children } from 'react';
import classNames from 'classnames';

export enum IconSize {
Expand Down Expand Up @@ -62,4 +62,38 @@ const Icon = ({
);
};

export /**
* Icon wrapper so we can use more then single element inside the icon
* prop on different components. Wrapper automatically applies icon
* props as size to all children.
*/
const IconWrapper = ({
size,
wrapperClassName,
children,
...rest
}: Omit<IconProps, 'className'> & {
wrapperClassName?: string;
children: ReactNode;
}): ReactElement => {
return (
<div className={wrapperClassName}>
{Children.map(children, (child) => {
if (React.isValidElement(child)) {
// so that className is no exposed from outside since components
// like Button override it for icons
const { className } = rest as { className: string };

return React.cloneElement<Props>(child as ReactElement, {
size,
className: classNames(child.props.className, className),
});
}

return child;
})}
</div>
);
};

export default Icon;
6 changes: 2 additions & 4 deletions packages/shared/src/components/icons/Warning/filled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 2 additions & 4 deletions packages/shared/src/components/icons/Warning/outlined.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions packages/shared/src/components/modals/Prompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export function PromptElement(props: Partial<ModalProps>): ReactElement {
cancelButton = {},
okButton = {},
className = {},
shouldCloseOnOverlayClick,
},
} = prompt;
return (
Expand All @@ -46,6 +47,7 @@ export function PromptElement(props: Partial<ModalProps>): ReactElement {
overlayClassName="!z-max"
isDrawerOnMobile
drawerProps={{ displayCloseButton: false, appendOnRoot: true }}
shouldCloseOnOverlayClick={shouldCloseOnOverlayClick}
{...props}
>
<Modal.Body>
Expand Down
21 changes: 17 additions & 4 deletions packages/shared/src/components/streak/ReadingStreakButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import classnames from 'classnames';
import { ReadingStreakPopup } from './popup';
import type { ButtonIconPosition } from '../buttons/Button';
import { Button, ButtonSize, ButtonVariant } from '../buttons/Button';
import { ReadingStreakIcon } from '../icons';
import { ReadingStreakIcon, WarningIcon } from '../icons';
import { SimpleTooltip } from '../tooltips';
import type { UserStreak } from '../../graphql/users';
import { useViewSize, ViewSize } from '../../hooks';
Expand All @@ -15,6 +15,10 @@ import { RootPortal } from '../tooltips/Portal';
import { Drawer } from '../drawers';
import ConditionalWrapper from '../ConditionalWrapper';
import type { TooltipPosition } from '../tooltips/BaseTooltipContainer';
import { useAuthContext } from '../../contexts/AuthContext';
import { isSameDayInTimezone } from '../../lib/timezones';
import { IconWrapper } from '../Icon';
import { useStreakTimezoneOk } from '../../hooks/streaks/useStreakTimezoneOk';

interface ReadingStreakButtonProps {
streak: UserStreak;
Expand Down Expand Up @@ -68,12 +72,14 @@ export function ReadingStreakButton({
className,
}: ReadingStreakButtonProps): ReactElement {
const { logEvent } = useLogContext();
const { user } = useAuthContext();
const isLaptop = useViewSize(ViewSize.Laptop);
const isMobile = useViewSize(ViewSize.MobileL);
const [shouldShowStreaks, setShouldShowStreaks] = useState(false);
const hasReadToday =
streak?.lastViewAtTz &&
new Date(streak.lastViewAtTz).getDate() === new Date().getDate();
streak?.lastViewAt &&
isSameDayInTimezone(new Date(streak.lastViewAt), new Date(), user.timezone);
const isTimezoneOk = useStreakTimezoneOk();

const handleToggle = useCallback(() => {
setShouldShowStreaks((state) => !state);
Expand Down Expand Up @@ -115,7 +121,14 @@ export function ReadingStreakButton({
id="reading-streak-header-button"
type="button"
iconPosition={iconPosition}
icon={<ReadingStreakIcon secondary={hasReadToday} />}
icon={
<IconWrapper wrapperClassName="relative flex items-center gap-2">
<ReadingStreakIcon secondary={hasReadToday} />
{!isTimezoneOk && (
<WarningIcon className="!mr-0 text-raw-cheese-40" secondary />
)}
</IconWrapper>
}
variant={
isLaptop || isMobile ? ButtonVariant.Tertiary : ButtonVariant.Float
}
Expand Down
14 changes: 7 additions & 7 deletions packages/shared/src/components/streak/popup/DayStreak.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import classNames from 'classnames';
import { ReadingStreakIcon, TriangleArrowIcon, EditIcon } from '../../icons';
import classed from '../../../lib/classed';
import { IconSize, iconSizeToClassName } from '../../Icon';
import { isNullOrUndefined } from '../../../lib/func';
import { SimpleTooltip } from '../../tooltips';
import { useAuthContext } from '../../../contexts/AuthContext';
import { dateFormatInTimezone } from '../../../lib/timezones';

export enum Streak {
Completed = 'completed',
Expand All @@ -16,27 +17,28 @@ export enum Streak {

interface DayStreakProps {
streak: Streak;
day?: number;
date: Date;
size?: IconSize;
className?: string;
shouldShowArrow?: boolean;
onClick?: () => void;
}

const dayInitial = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
const Circle = classed(
'div',
'rounded-full border border-border-subtlest-tertiary',
);

export function DayStreak({
streak,
day,
date,
size = IconSize.Medium,
className,
shouldShowArrow,
onClick,
}: DayStreakProps): ReactElement {
const { user } = useAuthContext();

const renderIcon = () => {
if (streak === Streak.Completed || streak === Streak.Pending) {
return (
Expand Down Expand Up @@ -69,8 +71,6 @@ export function DayStreak({
);
};

const finalDay = day < 7 ? day : day % 7;

return (
<SimpleTooltip
show={streak === Streak.Freeze}
Expand All @@ -89,7 +89,7 @@ export function DayStreak({
/>
)}
{renderIcon()}
{!isNullOrUndefined(day) ? dayInitial[finalDay] : null}
{dateFormatInTimezone(date, 'iiiii', user.timezone)}
</div>
</SimpleTooltip>
);
Expand Down
Loading

0 comments on commit f863d27

Please sign in to comment.