Skip to content

Commit

Permalink
Merge branch 'dev-0.0.12'
Browse files Browse the repository at this point in the history
crazygo committed Jan 23, 2025
2 parents 655caf8 + 38eb4eb commit 14faea9
Showing 12 changed files with 232 additions and 89 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -22,4 +22,5 @@ public/manifest.json
*.code-workspace
.shire
.vscode
.cursor
.cursor
.cursorrules
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "askman-chrome-extension",
"version": "0.0.11",
"version": "0.0.12",
"description": "Askman is an open-source browser extension that connects AI to web pages",
"license": "GPL-3.0-only",
"repository": {
12 changes: 6 additions & 6 deletions src/chat/chat.ts
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ export class ChatCoreContext implements ChatCoreInterface {
private async initSystemMessage() {
try {
const systemPrompt = await StorageManager.getSystemPrompt();
this.history.push(new SystemInvisibleMessage(systemPrompt));
this.history.push(new SystemInvisibleMessage(systemPrompt.content));
} catch (e) {
console.error('Failed to initialize system message:', e);
}
@@ -188,7 +188,7 @@ export class ChatCoreContext implements ChatCoreInterface {
await this.createModelClient(currentModel);

// 2. 系统提示词:临时提示词优先于存储的提示词
const systemPrompt = options?.overrideSystem || (await StorageManager.getSystemPrompt());
const systemPrompt = options?.overrideSystem || (await StorageManager.getSystemPrompt()).content;
// Remove old system message if exists
this.history = this.history.filter(msg => !(msg instanceof SystemInvisibleMessage));
// Add new system message
@@ -222,7 +222,7 @@ export class ChatCoreContext implements ChatCoreInterface {
return;
}

this.history.push(new HumanMessage({ content: prompt, name: 'human' }));
this.history.push(new HumanMessage({ content: prompt }));
if (this._onDataListener) {
setTimeout(() => this._onDataListener(this.history));
}
@@ -233,7 +233,7 @@ export class ChatCoreContext implements ChatCoreInterface {
console.warn('no this._onDataListener');
}

const pendingResponse = new AIMessage({ content: 'Just Guessing ...', name: 'hint' });
const pendingResponse = new AIMessage({ content: 'Thinking ...' });
let hasResponse = false;
setTimeout(() => {
this.history.push(pendingResponse);
@@ -250,11 +250,11 @@ export class ChatCoreContext implements ChatCoreInterface {
for await (const chunk of stream) {
chunks.push(chunk);
const content = chunks.reduce((acc, cur) => acc + cur.content, '');
const name = chunk.name;
// const name = chunk.name;
if (content.trim() === '') continue;

pendingResponse.content = content;
pendingResponse.name = name || 'ai';
// pendingResponse.name = name || 'ai';
hasResponse = true;
if (this._onDataListener) {
setTimeout(() => this._onDataListener(this.history));
8 changes: 4 additions & 4 deletions src/components/ask-message.tsx
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ export enum AskMessageType {
interface AskMessageItem {
type: AskMessageType | string;
text: string;
name?: string;
role?: string;
}

function decodeEntities(text: string): string {
@@ -25,7 +25,7 @@ function decodeEntities(text: string): string {
}

function AskMessage(props: AskMessageItem) {
const { type, text, name } = props;
const { type, text, role } = props;
const [codeHover, setCodeHover] = useState<number | null>(null);
const { isVisible, handlers } = useCopyButton(type !== AskMessageType.CODE);
let messageItem = <div>{text}</div>;
@@ -93,11 +93,11 @@ function AskMessage(props: AskMessageItem) {
<div
className={classNames(
'relative',
name === 'ai' ? 'text-gray-800 mb-3 leading-relaxed' : 'text-sky-600 mb-1 leading-relaxed max-h-16',
role === 'assistant' ? 'text-gray-800 mb-3 leading-relaxed' : 'text-sky-600 mb-1 leading-relaxed max-h-16',
'font-bold',
)}
{...handlers}>
<div className={classNames('pr-8', name === 'human' ? `max-h-16 ${SCROLLBAR_STYLES}` : '')}>{messageItem}</div>
<div className={classNames('pr-8', role === 'user' ? `max-h-16 ${SCROLLBAR_STYLES}` : '')}>{messageItem}</div>
{isVisible && type !== AskMessageType.CODE && (
<CopyButton text={text} className="top-[-6px] right-1 bg-gray-100 hover:bg-gray-200" />
)}
168 changes: 117 additions & 51 deletions src/components/ask-panel.tsx
Original file line number Diff line number Diff line change
@@ -6,9 +6,8 @@ import { ChatPopupContext } from '../chat/chat';
import ToolDropdown, { tools } from './ask-tooldropdown';
import ModelDropdown from './ask/ModelDropDown';
import TextareaAutosize from 'react-textarea-autosize';
import { ArrowsPointingInIcon, ArrowsPointingOutIcon, XMarkIcon } from '@heroicons/react/20/solid';
import { ArrowsPointingInIcon, ArrowsPointingOutIcon, XMarkIcon, PlusIcon } from '@heroicons/react/20/solid';
import AskMessage from './ask-message';
import AskButton from './ask-button';
import {
ToolsPromptInterface,
AIInvisibleMessage,
@@ -23,6 +22,7 @@ import SystemPromptDropdown from './system-prompt-dropdown';
import { StorageManager } from '../utils/StorageManager';
import { Handlebars } from '../../third-party/kbn-handlebars/src/handlebars';
import { SCROLLBAR_STYLES_HIDDEN_X } from '../styles/common';
import { HumanMessage } from '@langchain/core/messages';

interface AskPanelProps extends React.HTMLAttributes<HTMLDivElement> {
code: string;
@@ -78,7 +78,7 @@ function AskPanel(props: AskPanelProps) {
const [userInput, setUserInput] = useState<string>('');
const [askPanelVisible, setAskPanelVisible] = useState<boolean>(visible);
//TODO 需要定义一个可渲染、可序列号的类型,疑似是 StoredMessage
const [history, setHistory] = useState<{ id: string; name: string; type: string; text: string }[]>([]);
const [history, setHistory] = useState<{ id: string; role: string; type: string; text: string }[]>([]);
const [initQuotes, setInitQuotes] = useState<Array<QuoteContext>>([]);
const [pageContext, setPageContext] = useState<QuoteContext>(new QuoteContext());
const inputRef = useRef<HTMLTextAreaElement>(null);
@@ -93,7 +93,6 @@ function AskPanel(props: AskPanelProps) {
const [isSystemPromptDropdownOpen, setIsSystemPromptDropdownOpen] = useState(false);

const showToolDropdown = () => {
// console.log('isToolDropdownOpen = ' + isToolDropdownOpen, 'set to true');
setIsToolDropdownOpen(true);
setIsQuoteDropdownOpen(false);
setIsModelDropdownOpen(false);
@@ -200,15 +199,25 @@ function AskPanel(props: AskPanelProps) {
),
)
.map((message, idx) => {
let role = 'assistant';
if (message instanceof HumanMessage) {
role = 'user';
}
if (message instanceof HumanAskMessage) {
return { type: 'text', id: `history-${idx}`, text: message.rendered, name: message.name };
return {
type: 'text',
id: `history-${idx}`,
text: message.rendered,
role: role,
name: 'HumanAskMessage',
};
} else if (typeof message.content == 'string') {
return { type: 'text', id: `history-${idx}`, text: message.content, name: message.name };
return { type: 'text', id: `history-${idx}`, text: message.content, role: role, name: 'AIMessage' };
} else if (message.content instanceof Array) {
return {
type: 'text',
id: `history-${idx}`,
name: message.name,
role: role,
text: message.content.reduce((acc, cur) => {
if (cur.type == 'text') {
return acc + '\n' + cur.text;
@@ -268,19 +277,19 @@ function AskPanel(props: AskPanelProps) {
e.stopPropagation();

if (e.key === 'ArrowRight') {
if (isToolDropdownOpen) {
if (isSystemPromptDropdownOpen) {
showModelDropdown();
} else if (isModelDropdownOpen) {
showSystemPromptDropdown();
} else if (isSystemPromptDropdownOpen) {
showToolDropdown();
} else if (isToolDropdownOpen) {
showSystemPromptDropdown();
}
} else if (e.key === 'ArrowLeft') {
if (isToolDropdownOpen) {
showSystemPromptDropdown();
} else if (isModelDropdownOpen) {
if (isSystemPromptDropdownOpen) {
showToolDropdown();
} else if (isSystemPromptDropdownOpen) {
} else if (isModelDropdownOpen) {
showSystemPromptDropdown();
} else if (isToolDropdownOpen) {
showModelDropdown();
}
}
@@ -377,6 +386,17 @@ function AskPanel(props: AskPanelProps) {
setDropdownPosition({ left, top });
}

// 清空历史记录和输入框
const clearHistory = () => {
// 保留系统消息
const systemMessages = chatContext.history.filter(message => message instanceof SystemInvisibleMessage);
chatContext.history = systemMessages;
// 清空可见消息
setHistory([]);
// 清空输入框
setUserInput('');
};

// myObject.test('你是谁');
// console.log('history = ' + JSON.stringify(history));
return (
@@ -389,6 +409,21 @@ function AskPanel(props: AskPanelProps) {
: 'w-[473px] min-w-80 max-w-lg min-h-[155px]',
`${askPanelVisible ? 'visible' : 'invisible'}`,
)}
onKeyDown={e => {
if (
e.key === 'Escape' &&
(isQuoteDropdownOpen || isToolDropdownOpen || isModelDropdownOpen || isSystemPromptDropdownOpen)
) {
setIsQuoteDropdownOpen(false);
setIsToolDropdownOpen(false);
setIsModelDropdownOpen(false);
setIsSystemPromptDropdownOpen(false);
inputRef.current?.focus();
e.stopPropagation();
e.preventDefault();
}
}}
tabIndex={-1}
{...rest}>
<div className="font-medium rounded-lg bg-transparent bg-gradient-to-r from-white via-white to-white/60 mb-2 text-base flex justify-between">
<span>
@@ -403,6 +438,21 @@ function AskPanel(props: AskPanelProps) {

<div className="grow"></div>

<button
title="New Chat"
aria-label="Start a new chat"
className="bg-gray-100 text-gray-600 rounded-full p-1 hover:bg-black hover:text-white mr-2 transition-colors duration-200"
onClick={() => {
clearHistory();
setUserTools(null);
// 将焦点设置到输入框
setTimeout(() => {
inputRef.current?.focus();
}, 100);
}}>
<PlusIcon className="w-4 h-4 cursor-pointer" aria-hidden="true" />
</button>

<button
className="bg-gray-100 text-gray-600 rounded-full p-1 hover:bg-black hover:text-white mr-2"
onClick={() => setIsMaximized(!isMaximized)}>
@@ -423,9 +473,9 @@ function AskPanel(props: AskPanelProps) {
</button>
</div>
<div className={classNames('py-2 mb-2', SCROLLBAR_STYLES_HIDDEN_X, isMaximized ? 'flex-grow' : 'max-h-80')}>
{history.map(message => (
<AskMessage key={message.id} {...message} />
))}
{history.map(message => {
return <AskMessage key={message.id} {...message} />;
})}

{history.length > 0 && (
<div className="pt-32">
@@ -493,7 +543,28 @@ function AskPanel(props: AskPanelProps) {
onKeyDown={e => {
// 检测 ESC 键
if (e.key === 'Escape') {
if (isQuoteDropdownOpen || isToolDropdownOpen || isModelDropdownOpen) {
console.log('ESC key detected in textarea', {
isQuoteDropdownOpen,
isToolDropdownOpen,
isModelDropdownOpen,
isSystemPromptDropdownOpen,
});
if (
isQuoteDropdownOpen ||
isToolDropdownOpen ||
isModelDropdownOpen ||
isSystemPromptDropdownOpen
) {
setIsQuoteDropdownOpen(false);
setIsToolDropdownOpen(false);
setIsModelDropdownOpen(false);
setIsSystemPromptDropdownOpen(false);
e.stopPropagation();
e.preventDefault();
return;
} else {
setAskPanelVisible(false);
onHide();
e.stopPropagation();
e.preventDefault();
return;
@@ -539,17 +610,26 @@ function AskPanel(props: AskPanelProps) {
}
// 检测左右方向键
if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
if (isToolDropdownOpen || isModelDropdownOpen) {
if (isToolDropdownOpen || isModelDropdownOpen || isSystemPromptDropdownOpen) {
e.preventDefault();
e.stopPropagation();
if (isToolDropdownOpen && e.key === 'ArrowRight') {
showModelDropdown();
} else if (isModelDropdownOpen && e.key === 'ArrowRight') {
showToolDropdown();
} else if (isToolDropdownOpen && e.key === 'ArrowLeft') {
showModelDropdown();
} else if (isModelDropdownOpen && e.key === 'ArrowLeft') {
showToolDropdown();

if (e.key === 'ArrowRight') {
if (isSystemPromptDropdownOpen) {
showModelDropdown();
} else if (isModelDropdownOpen) {
showToolDropdown();
} else if (isToolDropdownOpen) {
showSystemPromptDropdown();
}
} else if (e.key === 'ArrowLeft') {
if (isSystemPromptDropdownOpen) {
showToolDropdown();
} else if (isModelDropdownOpen) {
showSystemPromptDropdown();
} else if (isToolDropdownOpen) {
showModelDropdown();
}
}
return;
}
@@ -592,17 +672,6 @@ function AskPanel(props: AskPanelProps) {
}
}}
/>
<ToolDropdown
initOpen={isToolDropdownOpen}
statusListener={updateToolDropdownStatus}
className="inline-block relative"
onItemClick={(item, withCommand) => {
setUserTools(item);
if (withCommand) {
onSend(item); // 按了 Command 键直接发送,使用临时工具
}
}}
/>
<ModelDropdown
initOpen={isModelDropdownOpen}
className="relative"
@@ -614,20 +683,17 @@ function AskPanel(props: AskPanelProps) {
statusListener={updateModelDropdownStatus}
/>
<div className="grow"></div>
<AskButton
primary
disabled={!(userInput || initQuotes.length)}
onClick={() => {
onSend();
<div className="w-px h-6 bg-gray-200 mx-2 my-auto"></div>
<ToolDropdown
initOpen={isToolDropdownOpen}
statusListener={updateToolDropdownStatus}
className="inline-block relative"
onItemClick={(_item, _withCommand) => {
setUserTools(_item);
onSend(_item); // 直接发送,不需要修改按钮文字
}}
onKeyDown={e => {
if (e.key === 'Enter' && !e.shiftKey && !e.ctrlKey && !e.altKey) {
e.preventDefault();
onSend();
}
}}>
</AskButton>
buttonDisplay="➔"
/>
</div>
</div>
</div>
32 changes: 27 additions & 5 deletions src/components/ask-tooldropdown.tsx
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ interface ToolDropdownProps {
onItemClick: (_tool: ToolsPromptInterface, _withCommand?: boolean) => void;
statusListener: (_status: boolean) => void;
initOpen: boolean;
buttonDisplay?: string;
}

const tools: ToolsPromptInterface[] = [];
@@ -31,13 +32,29 @@ for (const k in defaultTools) {

export { tools };

export default function ToolDropdown({ className, onItemClick, initOpen, statusListener }: ToolDropdownProps) {
export default function ToolDropdown({
className,
onItemClick,
initOpen,
statusListener,
buttonDisplay,
}: ToolDropdownProps) {
const [allTools, setAllTools] = useState<ToolsPromptInterface[]>([]);
const [selectedTool, setSelectedTool] = useState<string | null>(null);
const [selectedToolName, setSelectedToolName] = useState<string>('Frame'); // 默认显示 Frame
const { showPreview, previewPos, previewContent, showToolPreview, hideToolPreview } = useToolPreview();
const baseDropdownRef = useRef<HTMLDivElement>(null);

const handleMainButtonClick = (_e: React.MouseEvent) => {
// 直接使用当前选中的工具或第一个工具
const targetTool = selectedTool ? allTools.find(t => t.id === selectedTool) : allTools[0];

if (targetTool) {
console.log('[AskToolDropdown] main button clicked, sending tool:', targetTool.name);
handleToolClick(targetTool, _e.metaKey || _e.ctrlKey);
}
};

useEffect(() => {
const fetchTools = async () => {
try {
@@ -71,8 +88,8 @@ export default function ToolDropdown({ className, onItemClick, initOpen, statusL
}, []);

const handleToolClick = async (tool: ToolsPromptInterface, isCommandPressed: boolean) => {
// Command+Enter 不保存设置
if (!isCommandPressed) {
// TODO: Use cmd to pin the tool, it's not working now
if (isCommandPressed) {
await StorageManager.setCurrentTool(tool.id);
setSelectedTool(tool.id);
setSelectedToolName(tool.name);
@@ -88,8 +105,10 @@ export default function ToolDropdown({ className, onItemClick, initOpen, statusL
active ? 'bg-black text-white' : 'text-gray-900'
} group flex w-full items-center rounded-md px-2 py-2 text-sm focus:outline-none`}
onMouseEnter={e => {
// e.current is any item of dropdown menu
// baseDropdownRef is the outsite button of the dropdown menu
if (baseDropdownRef.current) {
showToolPreview(e.currentTarget, baseDropdownRef.current, tool.hbs);
showToolPreview(e.currentTarget, baseDropdownRef.current, 'right', tool.hbs);
}
}}
onMouseLeave={hideToolPreview}
@@ -107,7 +126,7 @@ export default function ToolDropdown({ className, onItemClick, initOpen, statusL
className={`ml-2 opacity-0 transition-all duration-100 ${active || 'group-hover:opacity-100'} ${
active && 'opacity-100'
}`}>
[{navigator.platform.includes('Mac') ? '⌘' : 'Ctrl'} + enter]
[{navigator.platform.includes('Mac') ? '⌘' : 'Ctrl'} + Enter to Pin]
</span>
</span>
</button>
@@ -126,6 +145,9 @@ export default function ToolDropdown({ className, onItemClick, initOpen, statusL
selectedId={selectedTool}
shortcutKey={navigator.platform.includes('Mac') ? '⌘ K' : 'Ctrl K'}
renderItem={renderToolItem}
align="right"
buttonDisplay={buttonDisplay}
onMainButtonClick={handleMainButtonClick}
/>
{showPreview && <ToolPreview content={previewContent} x={previewPos.x} y={previewPos.y} />}
</div>
10 changes: 9 additions & 1 deletion src/components/ask/ModelDropDown.tsx
Original file line number Diff line number Diff line change
@@ -22,6 +22,14 @@ export default function ModelDropdown({ className, onItemClick, statusListener,
const [selectedModelName, setSelectedModelName] = useState<string>('free'); // 默认显示 free
const baseDropdownRef = useRef<HTMLDivElement>(null);

// 辅助函数:简化模型名称显示
const simplifyModelName = (name: string): string => {
if (!name) return name;
const parts = name.split('/').filter(part => part.trim() !== '');
if (parts.length === 0) return name;
return parts[parts.length - 1] || parts[parts.length - 2] || name;
};

useEffect(() => {
const fetchModels = async () => {
const userModels = (await configStorage.getModelConfig()) || [];
@@ -93,7 +101,7 @@ export default function ModelDropdown({ className, onItemClick, statusListener,
return (
<div ref={baseDropdownRef} className="relative">
<BaseDropdown
displayName={selectedModelName}
displayName={simplifyModelName(selectedModelName)}
className={className}
onItemClick={handleModelClick}
statusListener={statusListener}
39 changes: 37 additions & 2 deletions src/components/base/BaseDropdown.tsx
Original file line number Diff line number Diff line change
@@ -20,6 +20,8 @@ export interface BaseDropdownProps {
selectedId?: string;
showShortcut?: boolean;
align?: 'left' | 'right';
buttonDisplay?: string;
onMainButtonClick?: (_e: React.MouseEvent) => void;
}

export function BaseDropdown({
@@ -34,6 +36,8 @@ export function BaseDropdown({
selectedId,
showShortcut = true,
align = 'left',
buttonDisplay,
onMainButtonClick,
}: BaseDropdownProps) {
const [isOpened, setIsOpen] = useState(initOpen);
const [isCommandPressed, setIsCommandPressed] = useState(false);
@@ -50,7 +54,6 @@ export function BaseDropdown({
buttonRef.current?.click();
}
}, [initOpen, isOpened]);

useEffect(() => {
statusListener(isOpened);
if (isOpened) {
@@ -65,6 +68,15 @@ export function BaseDropdown({
setIsCommandPressed(true);
}

// ESC 键处理
if (e.key === 'Escape' && isOpened) {
e.preventDefault();
e.stopPropagation();
setIsOpen(false);
statusListener(false);
return;
}

// Enter 时直接发送
if (e.key === 'Enter') {
e.preventDefault();
@@ -152,6 +164,17 @@ export function BaseDropdown({
<MenuButton
ref={buttonRef}
className="group inline-flex max-w-[12rem] justify-center rounded-md text-sm text-gray-600 bg-white px-2 py-1 text-sm font-medium text-black hover:bg-black/10 focus:outline-none"
onClick={e => {
e.stopPropagation();
// const target = e.target as Element;
// const currentTarget = e.currentTarget as Element;
// 区分真实点击和虚拟点击
if (e.isTrusted) {
// console.log('[BaseDropdown] MenuButton real click - target:', target.tagName, 'currentTarget:', currentTarget.tagName);
// 调用外部传入的点击处理函数
onMainButtonClick?.(e);
}
}}
onMouseEnter={() => {
setIsOpen(true);
}}
@@ -174,7 +197,11 @@ export function BaseDropdown({
</div>
</div>
{showShortcut && <span className="flex-shrink-0 pl-1">{shortcutKey}</span>}
<ChevronDownIcon className="-mr-1 h-5 w-5 text-violet-200 flex-shrink-0" />
{buttonDisplay ? (
<span className="-mr-1 h-5 w-5 ml-1 text-violet-200 flex-shrink-0">{buttonDisplay}</span>
) : (
<ChevronDownIcon className="-mr-1 h-5 w-5 text-violet-200 flex-shrink-0" />
)}
</>
);
}}
@@ -193,6 +220,14 @@ export function BaseDropdown({
className={`absolute ${
align === 'left' ? 'left-0' : 'right-0'
} mt-0 min-w-[10rem] origin-top-right divide-y divide-gray-100 rounded bg-white shadow-lg ring-1 ring-black/5 focus:outline-none z-10`}
onKeyDown={e => {
if (e.key === 'Escape') {
e.preventDefault();
e.stopPropagation();
setIsOpen(false);
statusListener(false);
}
}}
onMouseEnter={() => {
setIsOpen(true);
}}
2 changes: 1 addition & 1 deletion src/components/system-prompt-dropdown.tsx
Original file line number Diff line number Diff line change
@@ -65,7 +65,7 @@ export default function SystemPromptDropdown({
}}
onMouseEnter={e => {
if (baseDropdownRef.current) {
showToolPreview(e.currentTarget, baseDropdownRef.current, preset.hbs);
showToolPreview(e.currentTarget, baseDropdownRef.current, 'left', preset.hbs);
}
}}
onMouseLeave={hideToolPreview}>
2 changes: 0 additions & 2 deletions src/pages/content/injected/toggleTheme.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import exampleThemeStorage from '@src/shared/storages/exampleThemeStorage';

async function toggleTheme() {
console.log('initial theme', await exampleThemeStorage.get());
await exampleThemeStorage.toggle();
console.log('toggled theme', await exampleThemeStorage.get());
}

void toggleTheme();
31 changes: 22 additions & 9 deletions src/shared/hooks/useToolPreview.ts
Original file line number Diff line number Diff line change
@@ -5,19 +5,32 @@ export function useToolPreview() {
const [previewPos, setPreviewPos] = useState({ x: 0, y: 0 });
const [previewContent, setPreviewContent] = useState('');

const showToolPreview = (element: HTMLElement, baseDropdownElement: HTMLElement, content: string) => {
const buttonRect = element.getBoundingClientRect();
const dropdownRect = baseDropdownElement.getBoundingClientRect();
const showToolPreview = (
menuItem: HTMLElement,
menuButton: HTMLElement,
align: 'left' | 'right',
content: string,
) => {
const menuItemRect = menuItem.getBoundingClientRect();
const menuButtonRect = menuButton.getBoundingClientRect();

// Calculate the relative position between the menu item and dropdown
const relativeY = buttonRect.top - dropdownRect.top;
const relativeY = menuItemRect.top - menuButtonRect.top;

// console.log('buttonRect', buttonRect, 'dropdownRect', dropdownRect);
console.log('menuItemRect-width', menuItemRect.width, 'menuButtonRect-width', menuButtonRect.width);

if (align === 'right') {
setPreviewPos({
x: menuItemRect.width,
y: relativeY,
});
} else {
setPreviewPos({
x: menuButtonRect.width,
y: relativeY,
});
}

setPreviewPos({
x: dropdownRect.width,
y: relativeY,
});
setPreviewContent(content);
setShowPreview(true);
};
12 changes: 6 additions & 6 deletions src/utils/StorageManager.ts
Original file line number Diff line number Diff line change
@@ -61,7 +61,7 @@ export const StorageManager = {
},
get: (key: string) => {
return chrome.storage.local.get([key]).then(result => {
logger.debug(`Value for ${key} is`, result[key]);
// logger.debug(`Value for ${key} is`, result[key]);
return result[key];
});
},
@@ -114,20 +114,20 @@ export const StorageManager = {
const systemConfigPath = chrome.runtime.getURL('assets/conf/preferences.toml');
const systemConfigResponse = await fetch(systemConfigPath);
const systemConfigStr = await systemConfigResponse.text();
logger.debug('Loaded preferences.toml:', systemConfigStr);
// logger.debug('Loaded preferences.toml:', systemConfigStr);

const parsedConfig = TOML.parse(systemConfigStr);
logger.debug('Parsed config:', parsedConfig);
// logger.debug('Parsed config:', parsedConfig);

const defaultPreferences: UserPreferences = {
USER_LANGUAGE: parsedConfig.USER_LANGUAGE as string,
ASK_BUTTON: parsedConfig.ASK_BUTTON as boolean,
ASK_BUTTON_BLOCK_PAGE: parsedConfig.ASK_BUTTON_BLOCK_PAGE as string[],
};
logger.debug('Default preferences:', defaultPreferences);
// logger.debug('Default preferences:', defaultPreferences);

const preferences = await StorageManager.get(USER_PREFERENCES_KEY);
logger.debug('Stored preferences:', preferences);
// logger.debug('Stored preferences:', preferences);

if (preferences) {
const mergedPreferences = {
@@ -138,7 +138,7 @@ export const StorageManager = {
ASK_BUTTON_BLOCK_PAGE: preferences.ASK_BUTTON_BLOCK_PAGE,
}),
};
logger.debug('Merged preferences:', mergedPreferences);
// logger.debug('Merged preferences:', mergedPreferences);
return mergedPreferences;
}
return defaultPreferences;

0 comments on commit 14faea9

Please sign in to comment.