diff --git a/packages/harmony/src/assets/icons/Pin.svg b/packages/harmony/src/assets/icons/Pin.svg new file mode 100644 index 00000000000..6b00af97cd7 --- /dev/null +++ b/packages/harmony/src/assets/icons/Pin.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/harmony/src/components/comments/SendIcon/SendIcon.tsx b/packages/harmony/src/components/comments/SendIcon/SendIcon.tsx new file mode 100644 index 00000000000..b33f0fa94d4 --- /dev/null +++ b/packages/harmony/src/components/comments/SendIcon/SendIcon.tsx @@ -0,0 +1 @@ +export const SendIcon = () => {} diff --git a/packages/harmony/src/components/comments/Timestamp/Timestamp.stories.tsx b/packages/harmony/src/components/comments/Timestamp/Timestamp.stories.tsx new file mode 100644 index 00000000000..d7bc11adca6 --- /dev/null +++ b/packages/harmony/src/components/comments/Timestamp/Timestamp.stories.tsx @@ -0,0 +1,42 @@ +import type { Meta, StoryObj } from '@storybook/react' + +import { Flex } from 'components/layout' + +import { Timestamp } from './Timestamp' +import { + DAY_IN_MONTH, + HR_IN_DAY, + MIN_IN_HR, + MONTH_IN_YEAR, + MS_IN_S, + S_IN_MIN +} from './types' + +const meta: Meta = { + title: 'Components/Comments/Timestamp [beta]', + component: Timestamp +} + +export default meta + +type Story = StoryObj + +const secondsAgo = MS_IN_S +const minutesAgo = secondsAgo * S_IN_MIN +const hoursAgo = minutesAgo * MIN_IN_HR +const daysAgo = hoursAgo * HR_IN_DAY +const monthsAgo = daysAgo * DAY_IN_MONTH +const yearsAgo = monthsAgo * MONTH_IN_YEAR + +export const Default: Story = { + render: () => ( + + + + + + + + + ) +} diff --git a/packages/harmony/src/components/comments/Timestamp/Timestamp.tsx b/packages/harmony/src/components/comments/Timestamp/Timestamp.tsx new file mode 100644 index 00000000000..44bf4902e7a --- /dev/null +++ b/packages/harmony/src/components/comments/Timestamp/Timestamp.tsx @@ -0,0 +1,14 @@ +import { Text } from 'components/text' + +import { TimestampProps } from './types' +import { getLargestTimeUnitText } from './util' + +export const Timestamp = ({ time }: TimestampProps) => { + const text = getLargestTimeUnitText(time) + + return ( + + {text} + + ) +} diff --git a/packages/harmony/src/components/comments/Timestamp/index.ts b/packages/harmony/src/components/comments/Timestamp/index.ts new file mode 100644 index 00000000000..188db063a81 --- /dev/null +++ b/packages/harmony/src/components/comments/Timestamp/index.ts @@ -0,0 +1,3 @@ +export { Timestamp } from './Timestamp' +export { getLargestTimeUnitText } from './util' +export * from './types' diff --git a/packages/harmony/src/components/comments/Timestamp/types.ts b/packages/harmony/src/components/comments/Timestamp/types.ts new file mode 100644 index 00000000000..9659ceadaf7 --- /dev/null +++ b/packages/harmony/src/components/comments/Timestamp/types.ts @@ -0,0 +1,13 @@ +export type TimestampProps = { + time: Date +} + +// TODO: Probably should move these to a general util file +export const MS_IN_S = 1000 +export const S_IN_MIN = 60 +export const MIN_IN_HR = 60 +export const HR_IN_DAY = 24 +export const DAY_IN_MONTH = 30 +export const MONTH_IN_YEAR = 12 + +export type TimeUnit = 'm' | 'h' | 'd' | 'mo' | 'y' diff --git a/packages/harmony/src/components/comments/Timestamp/util.ts b/packages/harmony/src/components/comments/Timestamp/util.ts new file mode 100644 index 00000000000..031c816210b --- /dev/null +++ b/packages/harmony/src/components/comments/Timestamp/util.ts @@ -0,0 +1,33 @@ +import type { TimeUnit } from './types' +import { + DAY_IN_MONTH, + HR_IN_DAY, + MIN_IN_HR, + MONTH_IN_YEAR, + MS_IN_S, + S_IN_MIN +} from './types' + +const timeUnitMsMap: Record = { + m: MS_IN_S * S_IN_MIN, + h: MS_IN_S * S_IN_MIN * MIN_IN_HR, + d: MS_IN_S * S_IN_MIN * MIN_IN_HR * HR_IN_DAY, + mo: MS_IN_S * S_IN_MIN * MIN_IN_HR * HR_IN_DAY * DAY_IN_MONTH, + y: MS_IN_S * S_IN_MIN * MIN_IN_HR * HR_IN_DAY * DAY_IN_MONTH * MONTH_IN_YEAR +} as const + +export const getLargestTimeUnitText = (time: Date) => { + const then = new Date(time).getTime() + const now = Date.now() + const diff = now - then + let unit: TimeUnit | null = null + + // Iterate through all time units to determine the largest one + Object.entries(timeUnitMsMap).forEach(([u, ms]) => { + if (diff >= ms) { + unit = u as TimeUnit + } + }) + + return unit ? `${Math.floor(diff / timeUnitMsMap[unit])}${unit}` : 'just now' +} diff --git a/packages/harmony/src/components/index.ts b/packages/harmony/src/components/index.ts index 7b24cf80b21..1c008c37908 100644 --- a/packages/harmony/src/components/index.ts +++ b/packages/harmony/src/components/index.ts @@ -25,3 +25,4 @@ export { default as LoadingSpinner } from './loading-spinner/LoadingSpinner' export * from './pill' export * from './common/HiddenInput' export * from './select' +export * from './comments/Timestamp' diff --git a/packages/harmony/src/icons/utilityIcons.ts b/packages/harmony/src/icons/utilityIcons.ts index 97cece1e932..b96c9fa7c2b 100644 --- a/packages/harmony/src/icons/utilityIcons.ts +++ b/packages/harmony/src/icons/utilityIcons.ts @@ -75,6 +75,7 @@ import IconNotificationOffSVG from '../assets/icons/NotificationOff.svg' import IconNotificationOnSVG from '../assets/icons/NotificationOn.svg' import IconPauseSVG from '../assets/icons/Pause.svg' import IconPencilSVG from '../assets/icons/Pencil.svg' +import IconPinSVG from '../assets/icons/Pin.svg' import IconPlaySVG from '../assets/icons/Play.svg' import IconPlaybackPauseSVG from '../assets/icons/PlaybackPause.svg' import IconPlaybackPlaySVG from '../assets/icons/PlaybackPlay.svg' @@ -237,6 +238,7 @@ export const IconPause = IconPauseSVG as IconComponent export const IconTurntable = IconTurntableSVG as IconComponent export const IconCloudUpload = IconCloudUploadSVG as IconComponent export const IconPencil = IconPencilSVG as IconComponent +export const IconPin = IconPinSVG as IconComponent export const IconUser = IconUserSVG as IconComponent export const IconUserArrowRotate = IconUserArrowRotateSVG as IconComponent export const IconCollectible = IconCollectibleSVG as IconComponent diff --git a/packages/mobile/src/harmony-native/components/Comments/Timestamp/Timestamp.stories.tsx b/packages/mobile/src/harmony-native/components/Comments/Timestamp/Timestamp.stories.tsx new file mode 100644 index 00000000000..d242224366f --- /dev/null +++ b/packages/mobile/src/harmony-native/components/Comments/Timestamp/Timestamp.stories.tsx @@ -0,0 +1,42 @@ +import { + DAY_IN_MONTH, + HR_IN_DAY, + MIN_IN_HR, + MONTH_IN_YEAR, + MS_IN_S, + S_IN_MIN +} from '@audius/harmony/src/components/comments/Timestamp/types' +import type { Meta, StoryObj } from '@storybook/react' + +import { Flex } from '../..' + +import { Timestamp } from './Timestamp' + +const meta: Meta = { + title: 'Components/Comments/Timestamp [beta]', + component: Timestamp +} + +export default meta + +type Story = StoryObj + +const secondsAgo = MS_IN_S +const minutesAgo = secondsAgo * S_IN_MIN +const hoursAgo = minutesAgo * MIN_IN_HR +const daysAgo = hoursAgo * HR_IN_DAY +const monthsAgo = daysAgo * DAY_IN_MONTH +const yearsAgo = monthsAgo * MONTH_IN_YEAR + +export const Default: Story = { + render: () => ( + + + + + + + + + ) +} diff --git a/packages/mobile/src/harmony-native/components/Comments/Timestamp/Timestamp.tsx b/packages/mobile/src/harmony-native/components/Comments/Timestamp/Timestamp.tsx new file mode 100644 index 00000000000..579676498ab --- /dev/null +++ b/packages/mobile/src/harmony-native/components/Comments/Timestamp/Timestamp.tsx @@ -0,0 +1,14 @@ +import type { TimestampProps } from '@audius/harmony/src/components/comments/Timestamp/types' +import { getLargestTimeUnitText } from '@audius/harmony/src/components/comments/Timestamp/util' + +import { Text } from '../..' + +export const Timestamp = ({ time }: TimestampProps) => { + const text = getLargestTimeUnitText(time) + + return ( + + {text} + + ) +} diff --git a/packages/mobile/src/harmony-native/components/Comments/Timestamp/index.ts b/packages/mobile/src/harmony-native/components/Comments/Timestamp/index.ts new file mode 100644 index 00000000000..811f95df774 --- /dev/null +++ b/packages/mobile/src/harmony-native/components/Comments/Timestamp/index.ts @@ -0,0 +1 @@ +export { Timestamp } from './Timestamp' diff --git a/packages/mobile/src/harmony-native/components/index.ts b/packages/mobile/src/harmony-native/components/index.ts index 6aa47b579ac..8ff39cf8f40 100644 --- a/packages/mobile/src/harmony-native/components/index.ts +++ b/packages/mobile/src/harmony-native/components/index.ts @@ -26,3 +26,4 @@ export * from './CompletionCheck/CompletionCheck' export * from './RadialGradient/RadialGradient' export * from './FastImage/FastImage' export * from './Radio' +export * from './Comments/Timestamp' diff --git a/packages/mobile/src/harmony-native/icons.ts b/packages/mobile/src/harmony-native/icons.ts index ebea5544ad8..004b7f62f42 100644 --- a/packages/mobile/src/harmony-native/icons.ts +++ b/packages/mobile/src/harmony-native/icons.ts @@ -147,6 +147,7 @@ export { default as IconSoundwave } from '@audius/harmony/src/assets/icons/Sound export { default as IconCreditCard } from '@audius/harmony/src/assets/icons/CreditCard.svg' export { default as IconWaveform } from '@audius/harmony/src/assets/icons/Waveform.svg' export { default as IconMoneyBracket } from '@audius/harmony/src/assets/icons/MoneyBracket.svg' +export { default as IconPin } from '@audius/harmony/src/assets/icons/Pin.svg' // Two Tone / Special Styling