Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions front_end/messages/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1747,5 +1747,6 @@
"noPrivateNotes": "Žádné soukromé poznámky",
"privateNotes": "Soukromé poznámky",
"justNow": "právě teď",
"cmmButtonShort": "Mysl",
"othersCount": "Ostatní ({count})"
}
1 change: 1 addition & 0 deletions front_end/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1741,5 +1741,6 @@
"noPrivateNotes": "No private notes yet",
"privateNotes": "Private Notes",
"justNow": "just now",
"cmmButtonShort": "Mind",
"none": "none"
}
1 change: 1 addition & 0 deletions front_end/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -1747,5 +1747,6 @@
"noPrivateNotes": "Aún no hay notas privadas",
"privateNotes": "Notas privadas",
"justNow": "justo ahora",
"cmmButtonShort": "Mente",
"othersCount": "Otros ({count})"
}
1 change: 1 addition & 0 deletions front_end/messages/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -1745,5 +1745,6 @@
"noPrivateNotes": "Ainda não há notas privadas",
"privateNotes": "Notas Privadas",
"justNow": "agora mesmo",
"cmmButtonShort": "Mente",
"othersCount": "Outros ({count})"
}
1 change: 1 addition & 0 deletions front_end/messages/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -1744,5 +1744,6 @@
"noPrivateNotes": "尚無私人筆記",
"privateNotes": "私人筆記",
"justNow": "剛剛",
"cmmButtonShort": "心智",
"withdrawAfterPercentSetting2": "問題總生命周期後撤回"
}
1 change: 1 addition & 0 deletions front_end/messages/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -1749,5 +1749,6 @@
"noPrivateNotes": "尚無私人筆記",
"privateNotes": "私人筆記",
"justNow": "刚刚",
"cmmButtonShort": "心情",
"othersCount": "其他({count})"
}
61 changes: 20 additions & 41 deletions front_end/src/components/comment_feed/comment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,15 +241,12 @@ const Comment: FC<CommentProps> = ({
const userCanPredict = postData && canPredictQuestion(postData);
const userForecast =
postData?.question?.my_forecasts?.latest?.forecast_values[1] ?? 0.5;
const isCommentAuthor = comment.author.id === user?.id;
const isCmmButtonVisible =
user?.id !== comment.author.id &&
(!!postData?.question ||
!!postData?.group_of_questions ||
!!postData?.conditional);
const isCmmButtonDisabled = !user || !userCanPredict;
// TODO: find a better way to dedect whether on mobile or not. For now we need to know in JS
// too and can't use tw classes
const isMobileScreen = window.innerWidth < 640;
!!postData?.question ||
!!postData?.group_of_questions ||
!!postData?.conditional;
const isCmmButtonDisabled = !user || !userCanPredict || isCommentAuthor;

const {
draftReady: editDraftReady,
Expand Down Expand Up @@ -372,8 +369,6 @@ const Comment: FC<CommentProps> = ({
].includes(postData?.status ?? PostStatus.CLOSED);

const limitNotReached = factorsLimit > 0;
const isCommentAuthor = comment.author.id === user?.id;

const canShowAddKeyFactorsButton =
isCommentAuthor && questionNotClosed && canListKeyFactors;

Expand Down Expand Up @@ -497,22 +492,6 @@ const Comment: FC<CommentProps> = ({
}, [comment.id]);

const menuItems: MenuItemProps[] = [
{
hidden: !isMobileScreen || !isCmmButtonVisible,
id: "cmm",
element: (
<div>
<CmmToggleButton
cmmContext={cmmContext}
comment_id={comment.id}
disabled={isCmmButtonDisabled}
/>
</div>
),
onClick: () => {
return null; // handled by the button element
},
},
{
hidden: !(user?.id === comment.author.id),
id: "edit",
Expand Down Expand Up @@ -839,7 +818,7 @@ const Comment: FC<CommentProps> = ({

<div className="mb-2 mt-1 h-7 overflow-visible">
<div className="flex items-center justify-between text-sm leading-4 text-gray-900 dark:text-gray-900-dark">
<div className="inline-flex items-center gap-2.5">
<div className="flex min-w-0 flex-1 items-center gap-2.5">
<CommentVoter
voteData={{
commentAuthorId: comment.author.id,
Expand Down Expand Up @@ -883,21 +862,15 @@ const Comment: FC<CommentProps> = ({
icon={isKeyfactorsFormOpen ? faXmark : faPlus}
className="size-4 p-1"
/>
{t("addKeyFactor")}
<span className="hidden sm:inline">
{t("addKeyFactor")}
</span>
<span className="sm:hidden">{t("add")}</span>
</div>
</>
</Button>
)}

{isCmmButtonVisible && !isMobileScreen && (
<CmmToggleButton
cmmContext={cmmContext}
comment_id={comment.id}
disabled={isCmmButtonDisabled}
ref={cmmContext.setAnchorRef}
/>
)}

{!onProfile &&
(isReplying ? (
<Button
Expand Down Expand Up @@ -928,12 +901,18 @@ const Comment: FC<CommentProps> = ({
{t("reply")}
</Button>
))}

{isCmmButtonVisible && (
<CmmToggleButton
cmmContext={cmmContext}
comment_id={comment.id}
disabled={isCmmButtonDisabled}
ref={cmmContext.setAnchorRef}
/>
)}
</div>

<div
ref={isMobileScreen ? cmmContext.setAnchorRef : null}
className={cn(treeDepth > 0 && "pr-1.5 md:pr-2")}
>
<div className={cn(treeDepth > 0 && "pr-1.5 md:pr-2")}>
<DropdownMenu items={menuItems} />
</div>
</div>
Expand Down
151 changes: 132 additions & 19 deletions front_end/src/components/comment_feed/comment_cmm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@ import {
import {
faChevronLeft,
faChevronRight,
faCaretUp,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { isNil } from "lodash";
import { useTranslations } from "next-intl";
import React, { useState, forwardRef, FC } from "react";
import React, {
useState,
forwardRef,
FC,
useLayoutEffect,
useCallback,
} from "react";

import { toggleCMMComment } from "@/app/(main)/questions/actions";
import ForecastTextInput from "@/components/forecast_maker/forecast_text_input";
Expand Down Expand Up @@ -292,6 +297,55 @@ const CmmOverlay = ({
);
};

type LabelVariant = "full" | "mid" | "tiny";

function useFittingLabel<
TContainer extends HTMLElement,
TFull extends HTMLElement,
TMid extends HTMLElement,
TTiny extends HTMLElement,
>(params: {
containerRef: React.RefObject<TContainer | null>;
fullRef: React.RefObject<TFull | null>;
midRef: React.RefObject<TMid | null>;
tinyRef: React.RefObject<TTiny | null>;
}) {
const [variant, setVariant] = useState<LabelVariant>("full");

const recompute = useCallback(() => {
const container = params.containerRef.current;
if (!container) return;

const available = container.clientWidth;
const wFull = params.fullRef.current?.offsetWidth ?? 0;
const wMid = params.midRef.current?.offsetWidth ?? 0;
const wTiny = params.tinyRef.current?.offsetWidth ?? 0;

const next =
wFull <= available
? "full"
: wMid <= available
? "mid"
: wTiny <= available
? "tiny"
: "tiny";

setVariant((prev) => (prev === next ? prev : next));
}, [params.containerRef, params.fullRef, params.midRef, params.tinyRef]);

useLayoutEffect(() => {
recompute();
const el = params.containerRef.current;
if (!el) return;

const ro = new ResizeObserver(recompute);
ro.observe(el);
return () => ro.disconnect();
}, [recompute, params.containerRef]);

return variant;
}

interface CmmToggleButtonProps {
comment_id: number;
disabled?: boolean;
Expand Down Expand Up @@ -320,34 +374,72 @@ const CmmToggleButton = forwardRef<HTMLButtonElement, CmmToggleButtonProps>(
}
};

const isDisabled = isLoading || !!disabled;

const count = cmmContext.count;

const fullLabel = `${t("cmmButton")} (${count})`;
const midLabel = `${t("cmmButtonShort")} (${count})`;
const tinyLabel = `(${count})`;

const labelBoxRef = React.useRef<HTMLSpanElement>(null);
const fullMeasureRef = React.useRef<HTMLSpanElement>(null);
const midMeasureRef = React.useRef<HTMLSpanElement>(null);
const tinyMeasureRef = React.useRef<HTMLSpanElement>(null);

const variant = useFittingLabel({
containerRef: labelBoxRef,
fullRef: fullMeasureRef,
midRef: midMeasureRef,
tinyRef: tinyMeasureRef,
});

return (
<Button
size="xxs"
variant="tertiary"
onClick={onChangedMyMind}
aria-label="Changed my mind"
className="whitespace-nowrap border border-blue-400 hover:bg-gray-100 dark:hover:bg-gray-100-dark"
disabled={isLoading || disabled}
aria-label={t("cmmButton")}
disabled={isDisabled}
ref={ref}
{...cmmContext.getReferenceProps()}
className={cn(
"group relative inline-flex min-w-0 items-center gap-1 whitespace-nowrap rounded-sm border px-2 py-1 text-sm font-normal leading-[16px] tracking-tight transition-colors disabled:cursor-not-allowed",
!isDisabled &&
(cmmContext.cmmEnabled
? "hover:bg-olive-50 dark:hover:bg-olive-400/10"
: "hover:bg-blue-50 dark:hover:bg-blue-600/20"),
isDisabled &&
"border-gray-300 bg-gray-100 text-gray-400 hover:bg-gray-100 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-500"
)}
>
<FontAwesomeIcon
icon={faCaretUp}
<DeltaBadge enabled={cmmContext.cmmEnabled} disabled={isDisabled} />

<span
ref={labelBoxRef}
className={cn(
"size-4 rounded-full",
{
"bg-gradient-to-b p-1 text-blue-700 group-hover:from-blue-400 group-hover:to-blue-100 dark:text-blue-700-dark dark:group-hover:from-blue-400-dark dark:group-hover:to-blue-100-dark":
!cmmContext.cmmEnabled,
},
{
"bg-gradient-to-b from-olive-400 to-blue-100 p-1 text-olive-700 group-hover:from-olive-500 group-hover:to-blue-100 dark:from-olive-300-dark dark:to-blue-100-dark dark:text-olive-700-dark dark:group-hover:from-olive-500-dark dark:group-hover:to-blue-100-dark":
cmmContext.cmmEnabled,
}
"min-w-0 flex-1 overflow-hidden whitespace-nowrap",
"text-blue-700 dark:text-blue-700-dark",
isDisabled && "text-current"
)}
/>
>
{variant === "full"
? fullLabel
: variant === "mid"
? midLabel
: tinyLabel}
</span>

<span className="text-blue-700 dark:text-blue-700-dark">
{t("cmmButton")} ({cmmContext.count})
<span className="pointer-events-none absolute -z-10 opacity-0">
<span ref={fullMeasureRef} className="whitespace-nowrap">
{fullLabel}
</span>
<span ref={midMeasureRef} className="whitespace-nowrap">
{midLabel}
</span>
<span ref={tinyMeasureRef} className="whitespace-nowrap">
{tinyLabel}
</span>
</span>
</Button>
// <button
Expand Down Expand Up @@ -381,6 +473,27 @@ const CmmToggleButton = forwardRef<HTMLButtonElement, CmmToggleButtonProps>(
}
);

const DeltaBadge: FC<{ enabled: boolean; disabled?: boolean }> = ({
enabled,
disabled,
}) => {
return (
<span
aria-hidden="true"
className={cn(
"flex size-4 items-center justify-center rounded-full font-semibold leading-none",
"text-[12px] transition-colors",
disabled && "opacity-60",
!enabled && "bg-transparent text-blue-700 dark:text-blue-700-dark",
enabled &&
"bg-gradient-to-b from-olive-400 to-blue-100 p-1 text-olive-700 dark:from-olive-300-dark dark:to-blue-100-dark dark:text-olive-700-dark"
)}
>
</span>
);
};

CmmToggleButton.displayName = "CmmToggleButton";

export { CmmToggleButton, CmmOverlay };