Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export const CommentDrawerMobile = ({
<MobileInlineComment
activeDraft={activeDraft}
activeDraftId={activeDraftId}
isConnected={isConnected}
isDiscardCommentOverlayVisible={isDiscardCommentOverlayVisible}
mobileDraftRef={mobileDraftRef}
onAttemptClose={onAttemptCloseNewComment}
Expand Down
16 changes: 14 additions & 2 deletions package/components/inline-comment/comment-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { CommentCard } from './comment-card';
import { CommentDropdownProps } from './types';
import { useCommentStore } from '../../stores/comment-store';
import { useCommentRefs } from '../../stores/comment-store-provider';
import { useCommentDraftAutoSubmitCountdown } from './use-comment-draft-auto-submit-countdown';

export const CommentDropdown = ({
activeCommentId,
Expand Down Expand Up @@ -99,6 +100,15 @@ export const CommentDropdown = ({
submitInlineDraft(activeDraftId);
handleCancel();
};
const { handleDraftBlur, handleDraftFocus, submitLabel } =
useCommentDraftAutoSubmitCountdown({
draftId: activeDraftId,
canAutoSubmit:
isConnected &&
Boolean(activeDraftId) &&
Boolean(activeDraft?.text.trim()),
onSubmit: handleClick,
});

const handleReplySubmit = () => {
if (!isConnected) {
Expand Down Expand Up @@ -205,6 +215,8 @@ export const CommentDropdown = ({
updateInlineDraftText(activeDraftId, event.target.value);
}
}}
onFocus={handleDraftFocus}
onBlur={handleDraftBlur}
onKeyDown={handleKeyDown}
className="color-bg-default w-full text-body-sm color-text-default min-h-[40px] overflow-y-auto no-scrollbar px-3 py-2 whitespace-pre-wrap"
placeholder="Type your comment"
Expand All @@ -222,10 +234,10 @@ export const CommentDropdown = ({
<Button
data-testid="comment-dropdown-send"
onClick={handleClick}
className="px-4 py-2 w-20 min-w-20 h-9 font-medium text-sm"
className="px-4 py-2 min-w-[96px] h-9 font-medium text-sm"
disabled={!activeDraft?.text.trim()}
>
Send
{submitLabel}
</Button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { nameFormatter } from '../../../utils/helpers';
import verifiedMark from '../../../assets/ens-check.svg';
import EnsLogo from '../../../assets/ens.svg';
import { useEnsStatus } from '../use-ens-status';
import { useCommentDraftAutoSubmitCountdown } from '../use-comment-draft-auto-submit-countdown';

export const DraftFloatingCard = ({
draft,
Expand Down Expand Up @@ -108,7 +109,17 @@ const InputField = ({
const updateInlineDraftText = useCommentStore((s) => s.updateInlineDraftText);

const cancelInlineDraft = useCommentStore((s) => s.cancelInlineDraft);
const isConnected = useCommentStore((s) => s.isConnected);
const draftTextareaRef = useRef<HTMLTextAreaElement | null>(null);
const handleSubmit = useCallback(() => {
submitInlineDraft(draft.draftId);
}, [draft.draftId, submitInlineDraft]);
const { handleDraftBlur, handleDraftFocus, submitLabel } =
useCommentDraftAutoSubmitCountdown({
draftId: draft.draftId,
canAutoSubmit: isConnected && Boolean(draftState.text.trim()),
onSubmit: handleSubmit,
});

useEffect(() => {
if (!draftTextareaRef.current) {
Expand All @@ -128,11 +139,13 @@ const InputField = ({
updateInlineDraftText(draft.draftId, event.target.value);
resizeInlineCommentTextarea(event.currentTarget);
}}
onFocus={handleDraftFocus}
onBlur={handleDraftBlur}
onInput={(event) => resizeInlineCommentTextarea(event.currentTarget)}
onKeyDown={(event) => {
if (event.key === 'Enter' && (!event.shiftKey || event.metaKey)) {
event.preventDefault();
submitInlineDraft(draft.draftId);
handleSubmit();
}
}}
className="color-bg-default w-full text-body-sm color-text-default !p-0 !border-none h-[20px] max-h-[296px] overflow-y-auto no-scrollbar whitespace-pre-wrap"
Expand All @@ -148,11 +161,11 @@ const InputField = ({
Cancel
</Button>
<Button
className="w-20 min-w-20"
className="min-w-[96px]"
disabled={!draftState.text.trim()}
onClick={() => submitInlineDraft(draft.draftId)}
onClick={handleSubmit}
>
Send
{submitLabel}
</Button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { SuggestionDiffSummary } from '../suggestion-diff-summary';
import EnsLogo from '../../../assets/ens.svg';
import { dateFormatter, nameFormatter } from '../../../utils/helpers';
import verifiedMark from '../../../assets/ens-check.svg';
import { useSuggestionAutoSubmitCountdown } from '../use-suggestion-auto-submit-countdown';

/**
* SuggestionDraftFloatingCard
Expand Down Expand Up @@ -40,6 +41,14 @@ export const SuggestionDraftFloatingCard = ({
const canSubmit = hasOriginal || hasInserted || hasLink;
const username = useCommentStore((s) => s.username);
const ensStatus = useEnsStatus(username);
const handleSubmit = useCallback(() => {
submitDraft(card.suggestionId);
}, [card.suggestionId, submitDraft]);
const { submitLabel } = useSuggestionAutoSubmitCountdown({
suggestionId: card.suggestionId,
canAutoSubmit: isConnected && canSubmit,
onSubmit: handleSubmit,
});
const handleCardNode = useCallback(
(node: HTMLDivElement | null) => {
registerCardNode(card.floatingCardId, node);
Expand Down Expand Up @@ -121,10 +130,10 @@ export const SuggestionDraftFloatingCard = ({
<Button
size="sm"
disabled={!canSubmit}
onClick={() => submitDraft(card.suggestionId)}
onClick={handleSubmit}
className="!min-w-[80px]"
>
Submit
{submitLabel}
</Button>
</div>
</div>
Expand Down
37 changes: 32 additions & 5 deletions package/components/inline-comment/mobile-inline-comment-sheet.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import { useRef } from 'react';
import { Avatar, IconButton, TextAreaFieldV2 } from '@fileverse/ui';
import {
Avatar,
Button,
IconButton,
LucideIcon,
TextAreaFieldV2,
} from '@fileverse/ui';
import { DeleteConfirmOverlay } from './delete-confirm-overlay';
import { resizeInlineCommentTextarea } from './resize-inline-comment-textarea';
import type { InlineCommentDraft } from './context/types';
import { useCommentStore } from '../../stores/comment-store';
import { useEnsStatus } from './use-ens-status';
import EnsLogo from '../../assets/ens.svg';
import { useCommentDraftAutoSubmitCountdown } from './use-comment-draft-auto-submit-countdown';

interface MobileInlineCommentProps {
activeDraft: InlineCommentDraft | null;
activeDraftId: string | null;
isConnected: boolean;
isDiscardCommentOverlayVisible: boolean;
mobileDraftRef: React.RefObject<HTMLDivElement>;
onAttemptClose: () => void;
Expand All @@ -22,6 +30,7 @@ interface MobileInlineCommentProps {
export const MobileInlineComment = ({
activeDraft,
activeDraftId,
isConnected,
isDiscardCommentOverlayVisible,
mobileDraftRef,
onAttemptClose,
Expand All @@ -33,6 +42,16 @@ export const MobileInlineComment = ({
const mobileDraftTextareaRef = useRef<HTMLTextAreaElement | null>(null);
const username = useCommentStore((s) => s.username);
const ensStatus = useEnsStatus(username);
const { handleDraftBlur, handleDraftFocus, submitLabel } =
useCommentDraftAutoSubmitCountdown({
draftId: activeDraftId,
canAutoSubmit:
isConnected &&
Boolean(activeDraftId) &&
Boolean(activeDraft?.text.trim()) &&
!isDiscardCommentOverlayVisible,
onSubmit,
});

return (
<div
Expand Down Expand Up @@ -73,6 +92,8 @@ export const MobileInlineComment = ({

resizeInlineCommentTextarea(event.currentTarget);
}}
onFocus={handleDraftFocus}
onBlur={handleDraftBlur}
onInput={(event) => resizeInlineCommentTextarea(event.currentTarget)}
onKeyDown={(event) => {
if (event.key === 'Enter' && (!event.shiftKey || event.metaKey)) {
Expand All @@ -83,13 +104,19 @@ export const MobileInlineComment = ({
className="color-bg-default w-full text-body-sm color-text-default !p-0 !border-none h-[20px] max-h-[296px] overflow-y-auto no-scrollbar whitespace-pre-wrap"
placeholder="Add a comment"
/>
<IconButton
<Button
size="sm"
onClick={onSubmit}
icon={'SendHorizontal'}
variant="ghost"
disabled={!activeDraft?.text.trim()}
className="!min-w-[24px] !w-[24px] !min-h-[24px] !h-[24px]"
/>
title={submitLabel}
className="!min-w-[96px] shrink-0 !px-2"
>
<span className="inline-flex items-center gap-1 whitespace-nowrap">
<LucideIcon name="SendHorizontal" size="sm" />
{submitLabel}
</span>
</Button>
</div>
<DeleteConfirmOverlay
isVisible={isDiscardCommentOverlayVisible}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import verifiedMark from '../../assets/ens-check.svg';
import { dateFormatter, nameFormatter } from '../../utils/helpers';
import type { SuggestionFloatingDraftCard } from './context/types';
import { SuggestionDiffSummary } from './suggestion-diff-summary';
import { useSuggestionAutoSubmitCountdown } from './use-suggestion-auto-submit-countdown';

interface MobileSuggestionDraftProps {
activeSuggestionDraftCard: SuggestionFloatingDraftCard;
Expand Down Expand Up @@ -37,6 +38,12 @@ export const MobileSuggestionDraft = ({
const hasSuggestionLink = Boolean(activeSuggestionDraftCard.linkHref);
const canSubmitSuggestion =
hasSuggestionOriginal || hasSuggestionInserted || hasSuggestionLink;
const { submitLabel } = useSuggestionAutoSubmitCountdown({
suggestionId: activeSuggestionDraftCard.suggestionId,
canAutoSubmit:
isConnected && canSubmitSuggestion && !isDiscardSuggestionOverlayVisible,
onSubmit,
});
const suggestionType = hasSuggestionLink
? 'link'
: hasSuggestionOriginal
Expand Down Expand Up @@ -128,7 +135,7 @@ export const MobileSuggestionDraft = ({
onClick={onSubmit}
className="!min-w-[80px]"
>
Submit
{submitLabel}
</Button>
</div>
</div>
Expand Down
59 changes: 59 additions & 0 deletions package/components/inline-comment/use-auto-submit-countdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { useEffect, useRef, useState } from 'react';

const AUTO_SUBMIT_COUNTDOWN_SECONDS = 5;

interface UseAutoSubmitCountdownProps {
label: string;
onSubmit: () => void;
resetKey: string | null;
shouldRun: boolean;
}

export const useAutoSubmitCountdown = ({
label,
onSubmit,
resetKey,
shouldRun,
}: UseAutoSubmitCountdownProps) => {
const [remainingSeconds, setRemainingSeconds] = useState(
AUTO_SUBMIT_COUNTDOWN_SECONDS,
);
const hasSubmittedRef = useRef(false);

useEffect(() => {
hasSubmittedRef.current = false;
setRemainingSeconds(AUTO_SUBMIT_COUNTDOWN_SECONDS);
}, [resetKey]);

useEffect(() => {
if (!shouldRun) {
hasSubmittedRef.current = false;
setRemainingSeconds((current) =>
current === AUTO_SUBMIT_COUNTDOWN_SECONDS
? current
: AUTO_SUBMIT_COUNTDOWN_SECONDS,
);
return;
}

const timeoutId = window.setTimeout(() => {
if (remainingSeconds <= 1) {
if (!hasSubmittedRef.current) {
hasSubmittedRef.current = true;
onSubmit();
}
return;
}

setRemainingSeconds(remainingSeconds - 1);
}, 1000);

return () => {
window.clearTimeout(timeoutId);
};
}, [onSubmit, remainingSeconds, shouldRun]);

return {
submitLabel: shouldRun ? `${label} (${remainingSeconds})` : label,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useCallback, useEffect, useState } from 'react';
import { useAutoSubmitCountdown } from './use-auto-submit-countdown';

interface UseCommentDraftAutoSubmitCountdownProps {
draftId: string | null;
canAutoSubmit: boolean;
onSubmit: () => void;
}

export const useCommentDraftAutoSubmitCountdown = ({
draftId,
canAutoSubmit,
onSubmit,
}: UseCommentDraftAutoSubmitCountdownProps) => {
const [isDraftFocused, setIsDraftFocused] = useState(true);

const handleDraftFocus = useCallback(() => {
setIsDraftFocused(true);
}, []);

const handleDraftBlur = useCallback(() => {
setIsDraftFocused(false);
}, []);

useEffect(() => {
setIsDraftFocused(true);
}, [draftId]);

const { submitLabel } = useAutoSubmitCountdown({
label: 'Send',
onSubmit,
resetKey: draftId,
shouldRun: canAutoSubmit && !isDraftFocused,
});

return {
handleDraftBlur,
handleDraftFocus,
submitLabel,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useCommentStore } from '../../stores/comment-store';
import { useAutoSubmitCountdown } from './use-auto-submit-countdown';

interface UseSuggestionAutoSubmitCountdownProps {
suggestionId: string;
canAutoSubmit: boolean;
onSubmit: () => void;
}

export const useSuggestionAutoSubmitCountdown = ({
suggestionId,
canAutoSubmit,
onSubmit,
}: UseSuggestionAutoSubmitCountdownProps) => {
const activeSuggestionDraftIdAtCursor = useCommentStore(
(state) => state.activeSuggestionDraftIdAtCursor,
);
const { submitLabel } = useAutoSubmitCountdown({
label: 'Submit',
onSubmit,
resetKey: suggestionId,
shouldRun: canAutoSubmit && activeSuggestionDraftIdAtCursor !== suggestionId,
});

return {
submitLabel,
};
};
Loading