mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-10-11 11:32:26 +08:00
feat(desktop): add promotion marquee and proxy fix
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import type { RefObject } from "react";
|
||||
import { useLayoutEffect, useRef, useState, type RefObject } from "react";
|
||||
import { Marquee } from "react-css-marquee";
|
||||
import { Icon } from "../../shared/ui/Icon";
|
||||
import { windowCloseIcon } from "../../shared/ui/icons";
|
||||
import type { AdSlot } from "./types";
|
||||
@@ -14,6 +15,32 @@ type AdMenuProps = {
|
||||
onDismiss: (ad: AdSlot) => void;
|
||||
};
|
||||
|
||||
type OverflowTextProps = {
|
||||
children: string;
|
||||
className: string;
|
||||
};
|
||||
|
||||
function OverflowText({ children, className }: OverflowTextProps) {
|
||||
const text = useRef<HTMLSpanElement>(null);
|
||||
const [overflowing, setOverflowing] = useState(false);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const element = text.current;
|
||||
if (!element) return;
|
||||
const update = () => setOverflowing(element.scrollWidth > element.clientWidth + 1);
|
||||
update();
|
||||
const observer = new ResizeObserver(update);
|
||||
observer.observe(element);
|
||||
if (element.parentElement) observer.observe(element.parentElement);
|
||||
return () => observer.disconnect();
|
||||
}, [children]);
|
||||
|
||||
if (!overflowing) return <span ref={text} className={className}>{children}</span>;
|
||||
return <Marquee className={styles.menuMarquee} repeat loop={0} speed={4} gap={24}>
|
||||
<span ref={text} className={className}>{children}</span>
|
||||
</Marquee>;
|
||||
}
|
||||
|
||||
export function AdMenu({ ads, activeAdId, dismissingAdId, readAdIds, triggerRefs, onOpen, onDismiss }: AdMenuProps) {
|
||||
return <div className={styles.menuSlots} aria-label={t("推荐内容")}>
|
||||
{ads.map((ad) => <div key={ad.id} className={styles.menuSlotContainer}>
|
||||
@@ -34,8 +61,8 @@ export function AdMenu({ ads, activeAdId, dismissingAdId, readAdIds, triggerRefs
|
||||
{!readAdIds.has(ad.id) && <span className={styles.unreadDot} aria-hidden="true" />}
|
||||
<img className={styles.menuImage} src={ad.target.imageUrl} alt="" />
|
||||
<span className={styles.menuCopy}>
|
||||
<span className={styles.menuTitle}>{ad.target.title}</span>
|
||||
<span className={styles.menuSubtitle}>{ad.target.description}</span>
|
||||
<OverflowText className={styles.menuTitle}>{ad.target.title}</OverflowText>
|
||||
<OverflowText className={styles.menuSubtitle}>{ad.target.description}</OverflowText>
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
|
||||
@@ -25,18 +25,13 @@
|
||||
color: inherit;
|
||||
text-align: left;
|
||||
background: color-mix(in srgb, var(--vscode-foreground) 4%, transparent);
|
||||
border: 1px solid var(--vscode-sideBar-border);
|
||||
border: 2px solid #be8d180d;
|
||||
border-radius: 6px;
|
||||
|
||||
&:hover,
|
||||
&[aria-expanded="true"] {
|
||||
background: color-mix(in srgb, var(--vscode-foreground) 9%, transparent);
|
||||
border-color: var(--vscode-sideBar-border);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 1px solid var(--vscode-focusBorder);
|
||||
outline-offset: 1px;
|
||||
border-color: #be8d180d;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +42,7 @@
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: color-mix(in srgb, var(--vscode-descriptionForeground) 42%, transparent);
|
||||
@@ -66,6 +61,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.menuSlotContainer:hover .menuDismiss {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.unreadDot {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
@@ -93,11 +92,24 @@
|
||||
|
||||
.menuTitle,
|
||||
.menuSubtitle {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.menuMarquee {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.menuMarquee .menuTitle,
|
||||
.menuMarquee .menuSubtitle {
|
||||
width: max-content;
|
||||
overflow: visible;
|
||||
text-overflow: clip;
|
||||
}
|
||||
|
||||
.menuTitle {
|
||||
font-size: type.$font-size-xs;
|
||||
font-weight: 500;
|
||||
@@ -121,9 +133,9 @@
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
color: var(--vscode-foreground);
|
||||
background: var(--vscode-editorWidget-background);
|
||||
background: color-mix(in srgb, var(--vscode-editorWidget-background) 92%, var(--vscode-foreground) 8%);
|
||||
border-radius: 15px;
|
||||
border: none;
|
||||
border: 1px solid color-mix(in srgb, var(--vscode-foreground) 12%, transparent);
|
||||
box-shadow: 0 24px 20px rgb(0 0 0 / 28%);
|
||||
animation: ad-enter 180ms ease-out;
|
||||
|
||||
@@ -132,6 +144,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
:global(:root[data-theme="default-light"]) .floatingAd {
|
||||
background: var(--vscode-editorWidget-background);
|
||||
}
|
||||
|
||||
.hero {
|
||||
flex: 0 0 112px;
|
||||
position: relative;
|
||||
|
||||
Reference in New Issue
Block a user