+
+
+
+
+ {content}
+
-
-
setExpandReplies(!expandReplies)}
+ onReply={() => setReplyDraftSubject(comment)}
/>
-
+
+ {expandReplies &&
}
);
-};
+});
diff --git a/src/widgets/post/lib/index.ts b/src/widgets/post/lib/index.ts
deleted file mode 100644
index 784547f..0000000
--- a/src/widgets/post/lib/index.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-export const getTimeSince = (timestamp?: Date): string => {
- if (!timestamp) return 'unknown';
-
- const now = new Date();
- const secondsAgo = Math.floor((now.getTime() - timestamp.getTime()) / 1000);
-
- const intervals = [
- {unit: 'd', seconds: 60 * 60 * 24, minUnits: 2},
- {unit: 'yesterday', seconds: 60 * 60 * 24, minUnits: 1},
- {unit: 'h', seconds: 60 * 60, minUnits: 1},
- {unit: 'm', seconds: 60, minUnits: 1},
- {unit: 's', seconds: 1, minUnits: 5},
- {unit: 'now', seconds: 1, minUnits: 0},
- ];
-
- for (const {unit, seconds, minUnits} of intervals) {
- const unitsAgo = Math.floor(secondsAgo / seconds);
- if (unitsAgo >= minUnits) {
- if (unit === 'yesterday' || unit === 'now') return unit;
-
- if (unit === 'd' && unitsAgo > 30) {
- return new Intl.DateTimeFormat('en-US', {
- month: 'short',
- day: 'numeric',
- year: timestamp.getFullYear() < now.getFullYear() ? 'numeric' : undefined,
- }).format(timestamp);
- }
-
- return `${unitsAgo}${unit} ago`;
- }
- }
-
- return 'in future';
-};
-
-export const isEmoji = (text: string) =>
- /^(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff]).?$/.test(
- text,
- );
diff --git a/src/widgets/post/model.ts b/src/widgets/post/model.ts
index 1eeeb93..012d756 100644
--- a/src/widgets/post/model.ts
+++ b/src/widgets/post/model.ts
@@ -1,4 +1,52 @@
-import {attach, createEvent, createStore, restore, sample} from 'effector';
+import * as typed from 'typed-contracts';
+import {createStore, sample} from 'effector';
+import _ from 'lodash';
+
+import {
+ apiV1CommentsCommentIdRepliesGetFx,
+ apiV1CommentsCommentIdRepliesGetOk,
+ apiV1CommentsCommentIdRepliesPostFx,
+} from '~/shared/api';
+
+export const $replies = createStore<
+ Record
['items']>
+>({});
+
+sample({
+ clock: apiV1CommentsCommentIdRepliesGetFx.done,
+ source: $replies,
+ fn: (currentReplies, {params, result}) => {
+ const commentId = params.path.commentId;
+ return {
+ ...currentReplies,
+ [commentId]: _.uniqBy(
+ [...(currentReplies[commentId] ?? []), ...result.answer.items],
+ (reply) => reply.id,
+ ),
+ };
+ },
+ target: $replies,
+});
+
+sample({
+ clock: apiV1CommentsCommentIdRepliesPostFx.done,
+ source: $replies,
+ fn: (currentReplies, {params, result}) => {
+ const commentId = params.path.commentId;
+ return {
+ ...currentReplies,
+ [commentId]: _.uniqBy(
+ [...(currentReplies[commentId] ?? []), result.answer],
+ (reply) => reply.id,
+ ),
+ };
+ },
+ target: $replies,
+});
+
+/*
+
+import {attach, createEvent, createStore, sample} from 'effector';
import {produce} from 'immer';
import {sortBy} from 'lodash';
@@ -6,7 +54,6 @@ import {
apiV1CommentsCommentIdReactionsPostFx,
apiV1CommentsGetFx,
apiV1CommentsParentCommentIdRepliesGetFx,
- apiV1LookupReactionsGetFx,
} from '~/shared/api';
import {AlertOptions, showNotificationFx} from '~/shared/notifications';
@@ -29,11 +76,6 @@ const commitReactionsFx = attach({
export const $reactions = createStore>({});
-export const $availableReactions = restore(
- apiV1LookupReactionsGetFx.doneData.map((payload) => payload.answer),
- [],
-);
-
export const reactionToggled = createEvent<{commentId: string; toggledReaction: string}>();
sample({
@@ -173,3 +215,4 @@ sample({
),
target: $reactions,
});
+*/
diff --git a/src/widgets/post/ui/failed-message.tsx b/src/widgets/post/ui/failed-message.tsx
index 135c0a6..769565e 100644
--- a/src/widgets/post/ui/failed-message.tsx
+++ b/src/widgets/post/ui/failed-message.tsx
@@ -2,12 +2,8 @@ interface FailedMessageProps {
reaction: string;
}
-export const FailedMessage = (props: FailedMessageProps) => {
- const {reaction} = props;
-
- return (
-
- Failed to toggle {reaction}
-
- );
-};
+export const FailedMessage = (props: FailedMessageProps) => (
+
+ Failed to toggle {props.reaction}
+
+);
diff --git a/src/widgets/thread-waterfall/index.module.scss b/src/widgets/thread-waterfall/index.module.scss
deleted file mode 100644
index 0472644..0000000
--- a/src/widgets/thread-waterfall/index.module.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-.threadWaterfall {
- display: flex;
- flex-direction: column;
-}
-
-span {
- opacity: 1 !important;
-}
diff --git a/src/widgets/thread-waterfall/index.stories.tsx b/src/widgets/thread-waterfall/index.stories.tsx
deleted file mode 100644
index c19a1e4..0000000
--- a/src/widgets/thread-waterfall/index.stories.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import {Meta, StoryObj} from '@storybook/react';
-
-import {ThreadWaterfall} from '.';
-
-const meta: Meta = {
- title: 'widgets/ThreadWaterfall',
- component: ThreadWaterfall,
- tags: ['autodocs'],
-};
-
-export default meta;
-type Story = StoryObj;
-
-export const Default: Story = {};
diff --git a/src/widgets/thread-waterfall/index.tsx b/src/widgets/thread-waterfall/index.tsx
deleted file mode 100644
index 64df98b..0000000
--- a/src/widgets/thread-waterfall/index.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import classNames from 'classnames';
-import {HTMLAttributes, useState} from 'react';
-import StackGrid, {Grid} from 'react-stack-grid';
-import {Waypoint} from 'react-waypoint';
-
-import {Thread, ThreadProps} from '~/features/thread';
-
-import cls from './index.module.scss';
-
-export type ThreadWaterfallProps = HTMLAttributes;
-
-export const ThreadWaterfall = (props: ThreadWaterfallProps) => {
- const {className, ...otherProps} = props;
-
- const [threads, setThreads] = useState([]);
- const [gridRef, setGridRef] = useState();
-
- const createThread = (): ThreadProps => {
- const text = [...Array(Math.floor(Math.random() * 4 + 1))]
- .map(
- () =>
- 'не будем ломать уютненький манямирок лактозного пивозавра м м м что вчера было завтра',
- )
- .join(' ');
-
- return {
- text,
- author: {
- username: 'zendet',
- displayName: 'zendet',
- avatarUrl: 'https://github.com/undrcrxwn/undrcrxwn/blob/main/avatar.jpg?raw=true',
- },
- replyCount: 2,
- replyAuthors: [
- {
- username: 'zendet',
- displayName: 'Z E N D E T',
- },
- {
- username: 'zendet',
- displayName: 'Z E N D E T',
- avatarUrl: 'https://github.com/undrcrxwn/undrcrxwn/blob/main/avatar.jpg?raw=true',
- },
- ],
- onExpanded: () => setInterval(() => gridRef?.updateLayout()),
- };
- };
-
- const appendMoreThreads = () => {
- setThreads([
- ...threads,
- createThread(),
- createThread(),
- createThread(),
- createThread(),
- createThread(),
- ]);
- };
-
- return (
- setGridRef(grid)}
- duration={100}
- columnWidth={360}
- gutterWidth={12}
- gutterHeight={12}
- className={classNames(cls.threadWaterfall, className)}
- {...otherProps}
- >
- {...threads.map((props) => )}
-
-
- );
-};
diff --git a/tailwind.config.js b/tailwind.config.js
deleted file mode 100644
index 13df867..0000000
--- a/tailwind.config.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/** @type {import('tailwindcss').Config} */
-export default {
- darkMode: ['class'],
- content: ['./index.html', './src/**/*.{ts,tsx,js,jsx}'],
- theme: {
- extend: {
- borderRadius: {
- lg: 'var(--radius)',
- md: 'calc(var(--radius) - 2px)',
- sm: 'calc(var(--radius) - 4px)',
- },
- colors: {
- background: 'hsl(var(--background))',
- foreground: 'hsl(var(--foreground))',
- card: {
- DEFAULT: 'hsl(var(--card))',
- foreground: 'hsl(var(--card-foreground))',
- },
- popover: {
- DEFAULT: 'hsl(var(--popover))',
- foreground: 'hsl(var(--popover-foreground))',
- },
- primary: {
- DEFAULT: 'hsl(var(--primary))',
- foreground: 'hsl(var(--primary-foreground))',
- },
- secondary: {
- DEFAULT: 'hsl(var(--secondary))',
- foreground: 'hsl(var(--secondary-foreground))',
- },
- muted: {
- DEFAULT: 'hsl(var(--muted))',
- foreground: 'hsl(var(--muted-foreground))',
- },
- accent: {
- DEFAULT: 'hsl(var(--accent))',
- foreground: 'hsl(var(--accent-foreground))',
- },
- destructive: {
- DEFAULT: 'hsl(var(--destructive))',
- foreground: 'hsl(var(--destructive-foreground))',
- },
- border: 'hsl(var(--border))',
- input: 'hsl(var(--input))',
- ring: 'hsl(var(--ring))',
- chart: {
- 1: 'hsl(var(--chart-1))',
- 2: 'hsl(var(--chart-2))',
- 3: 'hsl(var(--chart-3))',
- 4: 'hsl(var(--chart-4))',
- 5: 'hsl(var(--chart-5))',
- },
- },
- },
- },
- plugins: [require('tailwindcss-animate')],
-};
diff --git a/vite.config.ts b/vite.config.ts
index 880643b..c93f100 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -3,12 +3,14 @@ import babel from '@rollup/plugin-babel';
import svgr from 'vite-plugin-svgr';
import stylelint from 'vite-plugin-stylelint';
import react from '@vitejs/plugin-react';
+import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [
babel({extensions: ['.ts', '.tsx'], babelHelpers: 'bundled', skipPreflightCheck: true}),
+ tailwindcss(),
svgr({
- include: '**/*.svg'
+ include: '**/*.svg',
}),
stylelint({
fix: true,
@@ -29,9 +31,9 @@ export default defineConfig({
changeOrigin: true,
secure: false,
cookieDomainRewrite: {
- '*': 'localhost'
- }
- }
- }
- }
+ '*': 'localhost',
+ },
+ },
+ },
+ },
});