Skip to content

Commit 674ecbc

Browse files
committed
fix(better-code-blocks): overflowing detection
1 parent d1ed416 commit 674ecbc

File tree

20 files changed

+176
-273
lines changed

20 files changed

+176
-273
lines changed

src/components/CodeHighlighter.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ComponentProps } from "react";
1+
import { ComponentProps, RefObject } from "react";
22
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
33
import lightStyle from "react-syntax-highlighter/dist/esm/styles/prism/vs";
44
import darkStyle from "react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus";
@@ -14,8 +14,11 @@ const INTERPRETED_LANGUAGES: Record<string, string> = {
1414
const CodeHighlighter = memo(function CodeHighlighter({
1515
children,
1616
language,
17+
codeRef,
1718
...props
18-
}: ComponentProps<typeof SyntaxHighlighter>) {
19+
}: ComponentProps<typeof SyntaxHighlighter> & {
20+
codeRef?: RefObject<HTMLDivElement | null>;
21+
}) {
1922
const colorScheme = useColorSchemeStore((state) => state.colorScheme);
2023

2124
const interpretedLanguage = language
@@ -34,6 +37,7 @@ const CodeHighlighter = memo(function CodeHighlighter({
3437
codeTagProps={{
3538
className: "x-font-mono",
3639
style: {},
40+
ref: codeRef,
3741
}}
3842
language={targetLanguage}
3943
{...props}

src/entrypoints/options-page/dashboard/pages/plugins/hooks/usePluginsStates.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ export default function usePluginsStates() {
2424
useExtensionUpdate();
2525

2626
const isLoading =
27-
isFetchingFeatureCompat || isFetchingFeatureFlags || isLoadingLatestVersion;
27+
!featureCompat &&
28+
!featureFlags &&
29+
!latestVersion &&
30+
(isFetchingFeatureCompat ||
31+
isFetchingFeatureFlags ||
32+
isLoadingLatestVersion);
2833

2934
const userGroup: UserGroup = "anon";
3035

src/plugins/_api/spa-router/spa-router.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ export async function waitForRouteChangeComplete(
116116

117117
async function checkThreadLoaded() {
118118
await UiUtils.waitForSpaIdle();
119-
120-
return UiUtils.getMessageBlocks().length >= 1;
119+
return $(DOM_SELECTORS.THREAD.MESSAGE.WRAPPER).length > 0;
121120
}
122121

123122
function checkHomeLoaded() {

src/plugins/_core/dom-observers/thread/code-blocks/types.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
export type CodeBlock = {
22
nodes: {
33
$wrapper: JQuery<Element>;
4-
$pre: JQuery<Element>;
5-
$code: JQuery<Element>;
6-
$nativeHeader: JQuery<Element>;
74
$nativeCopyButton: JQuery<Element>;
85
};
96
content: {

src/plugins/_core/dom-observers/thread/code-blocks/utils.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,6 @@ export async function parseCodeBlocks(
2424
)
2525
.attr("data-index", j);
2626

27-
const $pre = $codeBlock.find("pre");
28-
const $code = $pre.find("code");
29-
const $nativeHeader = $codeBlock.find(
30-
DOM_SELECTORS.THREAD.MESSAGE.CODE_BLOCK.NATIVE_HEADER,
31-
);
3227
const $nativeCopyButton = $codeBlock.find(
3328
DOM_SELECTORS.THREAD.MESSAGE.CODE_BLOCK.NATIVE_COPY_BUTTON,
3429
);
@@ -41,9 +36,6 @@ export async function parseCodeBlocks(
4136
return {
4237
nodes: {
4338
$wrapper: $codeBlock,
44-
$pre,
45-
$code,
46-
$nativeHeader,
4739
$nativeCopyButton,
4840
},
4941
content,

src/plugins/export-thread/ExportButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ const ExportButton = memo(function ExportButton() {
101101
<Button
102102
variant={isMobile ? "default" : "outline"}
103103
size="sm"
104-
className="x-h-8 x-px-2"
104+
className="x-box-content x-h-8 x-px-2"
105105
>
106106
{isFetching ? defaultIdleText : (copyConfirmText ?? defaultIdleText)}
107107
</Button>

src/plugins/sidebar-toggleable-recent-threads/index.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
import { Portal } from "@/components/ui/portal";
2+
import { useInsertCss } from "@/hooks/useInsertCss";
23
import { useSidebarDomObserverStore } from "@/plugins/_core/dom-observers/sidebar/store";
4+
import styles from "@/plugins/sidebar-toggleable-recent-threads/styles.css?inline";
35
import SidebarToggleableRecentThreadsToggleButton from "@/plugins/sidebar-toggleable-recent-threads/ToggleButton";
46
import { INTERNAL_ATTRIBUTES } from "@/utils/dom-selectors";
57

68
export default function SidebarToggleableRecentThreadsWrapper() {
9+
useInsertCss({
10+
css: styles,
11+
id: "sidebar-toggleable-recent-threads",
12+
});
13+
714
const libraryButtonWrapper = useSidebarDomObserverStore(
815
(state) => state.$libraryButtonWrapper?.[0],
916
deepEqual,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[data-cplx-component="sidebar-library-button-wrapper"]
2+
[data-cplx-component="sidebar-library-button-trigger-buttons-portal-container"]
3+
> :last-child {
4+
@apply x-mr-1;
5+
}

src/plugins/thread-better-code-blocks/MirroredCodeBlockContext.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,18 @@ type MirroredCodeBlockStore = {
1313
setIsWrapped: (isWrapped: boolean) => void;
1414
maxHeight: number;
1515
setMaxHeight: (maxHeight: number) => void;
16+
isHorizontalOverflowing: boolean;
17+
setIsHorizontalOverflowing: (isHorizontalOverflowing: boolean) => void;
18+
isVerticalOverflowing: boolean;
19+
setIsVerticalOverflowing: (isVerticalOverflowing: boolean) => void;
1620
};
1721

1822
type InitialState = Omit<
1923
MirroredCodeBlockStore,
20-
"setIsWrapped" | "setMaxHeight"
24+
| "setIsWrapped"
25+
| "setMaxHeight"
26+
| "setIsHorizontalOverflowing"
27+
| "setIsVerticalOverflowing"
2128
>;
2229

2330
export const createStore = (initialState: InitialState) =>
@@ -36,6 +43,16 @@ export const createStore = (initialState: InitialState) =>
3643
state.maxHeight = maxHeight;
3744
});
3845
},
46+
setIsHorizontalOverflowing: (isHorizontalOverflowing) => {
47+
set((state) => {
48+
state.isHorizontalOverflowing = isHorizontalOverflowing;
49+
});
50+
},
51+
setIsVerticalOverflowing: (isVerticalOverflowing) => {
52+
set((state) => {
53+
state.isVerticalOverflowing = isVerticalOverflowing;
54+
});
55+
},
3956
}),
4057
),
4158
),

src/plugins/thread-better-code-blocks/index.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
createMirroredPortalContainer,
1212
getBetterCodeBlockOptions,
1313
} from "@/plugins/thread-better-code-blocks/utils";
14+
import { ExtensionLocalStorageService } from "@/services/extension-local-storage";
1415

1516
export default function BetterCodeBlocksWrapper() {
1617
const codeBlocksChunks = useThreadCodeBlocksDomObserverStore(
@@ -61,9 +62,11 @@ function ContextWrapper({
6162

6263
if (!codeBlock) return null;
6364

64-
const finegrainedSettings = getBetterCodeBlockOptions(
65-
codeBlock.content.language,
66-
);
65+
const settings =
66+
getBetterCodeBlockOptions(codeBlock.content.language) ??
67+
ExtensionLocalStorageService.getCachedSync().plugins[
68+
"thread:betterCodeBlocks"
69+
];
6770

6871
const portalContainer = createMirroredPortalContainer(
6972
codeBlock,
@@ -76,12 +79,13 @@ function ContextWrapper({
7679
storeValue={{
7780
sourceMessageBlockIndex,
7881
sourceCodeBlockIndex,
79-
isWrapped: !finegrainedSettings.unwrap.enabled,
82+
isWrapped: !settings.unwrap.enabled,
8083
maxHeight:
81-
finegrainedSettings.maxHeight.enabled &&
82-
finegrainedSettings.maxHeight.collapseByDefault
83-
? finegrainedSettings.maxHeight.value
84+
settings.maxHeight.enabled && settings.maxHeight.collapseByDefault
85+
? settings.maxHeight.value
8486
: 9999,
87+
isHorizontalOverflowing: false,
88+
isVerticalOverflowing: false,
8589
}}
8690
>
8791
{children}

src/plugins/thread-better-code-blocks/utils.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { BetterCodeBlockFineGrainedOptions } from "@/data/dashboard/better-code-blocks/better-code-blocks-options.types";
22
import { CodeBlock } from "@/plugins/_core/dom-observers/thread/code-blocks/types";
3-
import { ExtensionLocalStorageService } from "@/services/extension-local-storage";
43
import { betterCodeBlocksFineGrainedOptionsQueries } from "@/services/indexed-db/better-code-blocks/query-keys";
54
import { INTERNAL_ATTRIBUTES } from "@/utils/dom-selectors";
65
import { queryClient } from "@/utils/ts-query-client";
@@ -33,12 +32,9 @@ export function createMirroredPortalContainer(
3332
return $portalContainer[0];
3433
}
3534

36-
export function getBetterCodeBlockOptions(language: string | null) {
37-
const globalSettings =
38-
ExtensionLocalStorageService.getCachedSync().plugins[
39-
"thread:betterCodeBlocks"
40-
];
41-
35+
export function getBetterCodeBlockOptions(
36+
language: string | null,
37+
): BetterCodeBlockFineGrainedOptions | undefined | null {
4238
const fineGrainedSettings = language
4339
? queryClient
4440
.getQueryData<
@@ -47,5 +43,5 @@ export function getBetterCodeBlockOptions(language: string | null) {
4743
?.find((option) => option.language === language)
4844
: null;
4945

50-
return fineGrainedSettings || globalSettings;
46+
return fineGrainedSettings;
5147
}

src/plugins/thread-better-code-blocks/variants/HighlightedCode.tsx

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
import { ReactNode } from "react";
1+
import { useWindowSize } from "@uidotdev/usehooks";
2+
import { ReactNode, RefObject } from "react";
23

34
import CodeHighlighter from "@/components/CodeHighlighter";
5+
import { BetterCodeBlockFineGrainedOptions } from "@/data/dashboard/better-code-blocks/better-code-blocks-options.types";
46
import { getInterpretedCanvasLanguage } from "@/plugins/canvas/canvas.types";
57
import { useMirroredCodeBlockContext } from "@/plugins/thread-better-code-blocks/MirroredCodeBlockContext";
8+
import { getBetterCodeBlockOptions } from "@/plugins/thread-better-code-blocks/utils";
9+
import { ExtensionLocalStorageService } from "@/services/extension-local-storage";
10+
import { ExtensionLocalStorage } from "@/services/extension-local-storage/extension-local-storage.types";
611

712
const HighlightedCodeWrapper = memo(() => {
813
const { codeBlock, maxHeight, isWrapped } = useMirroredCodeBlockContext();
@@ -13,10 +18,26 @@ const HighlightedCodeWrapper = memo(() => {
1318

1419
const interpretedLanguage = getInterpretedCanvasLanguage(language ?? "text");
1520

21+
const wrapperRef = useRef<HTMLDivElement>(null);
22+
const codeRef = useRef<HTMLDivElement>(null);
23+
24+
const fineGrainedSettings = getBetterCodeBlockOptions(language ?? "text");
25+
const globalSettings =
26+
ExtensionLocalStorageService.getCachedSync().plugins[
27+
"thread:betterCodeBlocks"
28+
];
29+
30+
useOverflowing({
31+
wrapperRef,
32+
codeRef,
33+
fineGrainedSettings: fineGrainedSettings ?? globalSettings,
34+
});
35+
1636
if (!codeBlock) return null;
1737

1838
return (
1939
<div
40+
ref={wrapperRef}
2041
style={{
2142
maxHeight,
2243
}}
@@ -26,13 +47,17 @@ const HighlightedCodeWrapper = memo(() => {
2647
className={cn(
2748
"[&>pre]:x-m-0 [&>pre]:x-rounded-t-none [&>pre]:!x-p-2 [&>pre]:!x-px-4",
2849
{
29-
"[&_code]:!x-whitespace-pre-wrap": isWrapped,
50+
"x-text-pretty [&_code]:!x-whitespace-pre-wrap": isWrapped,
3051
"[&_span]:x-duration-300 [&_span]:x-animate-in [&_span]:x-fade-in":
3152
isInFlight,
3253
},
3354
)}
3455
>
35-
<CodeHighlighter language={interpretedLanguage} PreTag={PreTag}>
56+
<CodeHighlighter
57+
language={interpretedLanguage}
58+
codeRef={codeRef}
59+
PreTag={PreTag}
60+
>
3661
{code}
3762
</CodeHighlighter>
3863
</div>
@@ -45,3 +70,45 @@ function PreTag({ children }: { children: ReactNode }) {
4570
}
4671

4772
export default HighlightedCodeWrapper;
73+
74+
function useOverflowing({
75+
wrapperRef,
76+
codeRef,
77+
fineGrainedSettings,
78+
}: {
79+
wrapperRef: RefObject<HTMLDivElement | null>;
80+
codeRef: RefObject<HTMLDivElement | null>;
81+
fineGrainedSettings:
82+
| BetterCodeBlockFineGrainedOptions
83+
| ExtensionLocalStorage["plugins"]["thread:betterCodeBlocks"];
84+
}) {
85+
useWindowSize();
86+
87+
const [initialWidth, setInitialWidth] = useState(0);
88+
89+
const { setIsHorizontalOverflowing, setIsVerticalOverflowing } =
90+
useMirroredCodeBlockContext();
91+
92+
useEffect(() => {
93+
if (!wrapperRef.current) {
94+
return;
95+
}
96+
97+
if (initialWidth === 0) {
98+
setInitialWidth(wrapperRef.current.scrollWidth);
99+
}
100+
}, [initialWidth, wrapperRef]);
101+
102+
if (!wrapperRef.current || !codeRef.current) {
103+
return;
104+
}
105+
106+
setIsHorizontalOverflowing(
107+
codeRef.current.getBoundingClientRect().width >
108+
wrapperRef.current.getBoundingClientRect().width,
109+
);
110+
setIsVerticalOverflowing(
111+
codeRef.current.getBoundingClientRect().height >
112+
fineGrainedSettings.maxHeight.value,
113+
);
114+
}

0 commit comments

Comments
 (0)