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
Binary file added chromium-extension/public/icon-16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chromium-extension/public/icon-32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chromium-extension/public/icon_white-16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chromium-extension/public/icon_white-32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chromium-extension/public/icon_white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions chromium-extension/public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"description": "OpenBrowser Agent Extension",
"version": "3.0",
"manifest_version": 3,
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnk6aCCanZ8kXgeZ9DjCSi8m2IhWn+CVGfw9Rm/kGdjGnJrdCCsNi7CwNPqwkC6vW+yRGc1NrBzTTeLzToIeH6p+scCp0zg5iTiOL+xBq1KtyyMGdtH6tb1GvXGud3RwD/GGkmhFsWlRtxzVzyz7NtDBhXlDDDLw/OgDi/DQGYsBfClSSvL1gNToeML+sWiRhBDhUJ+GIRRpOvDCBCXOQXTTwDWiEPFcsmfU2H/nRlWZtfqz8mMPU5ISDTR68dnLc4JhxsegrcQcV9nVxZlUjKXsdR/gdFf3DWCrJQkYwspYyg8MEzqxtRaC/G9RCP88jaBGjf9RFzkB497CpgN5+ywIDAQAB",
"background": {
"type": "module",
"service_worker": "js/background.js"
Expand Down
121 changes: 81 additions & 40 deletions chromium-extension/src/options/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createRoot } from "react-dom/client";
import { Form, Input, Button, message, Select, Checkbox, Spin } from "antd";
import { SaveOutlined, LoadingOutlined } from "@ant-design/icons";
import "../sidebar/index.css";
import { ThemeProvider } from "../sidebar/providers/ThemeProvider";
import {
fetchModelsData,
getProvidersWithImageSupport,
Expand Down Expand Up @@ -49,6 +50,17 @@ const OptionsPage = () => {
Record<string, ModelOption[]>
>({});
const [modelSearchValue, setModelSearchValue] = useState("");
const [isDarkMode, setIsDarkMode] = useState(
window.matchMedia("(prefers-color-scheme: dark)").matches
);

// Listen for theme changes
useEffect(() => {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handleChange = (e: MediaQueryListEvent) => setIsDarkMode(e.matches);
mediaQuery.addEventListener("change", handleChange);
return () => mediaQuery.removeEventListener("change", handleChange);
}, []);

// Fetch models data on component mount
useEffect(() => {
Expand Down Expand Up @@ -142,7 +154,10 @@ const OptionsPage = () => {
webSearchConfig: newWebSearchConfig
},
() => {
message.success("Save Success!");
message.success({
content: "Save Success!",
className: "toast-text-black"
});
}
);
})
Expand Down Expand Up @@ -188,31 +203,47 @@ const OptionsPage = () => {

setConfig(newConfig);
form.setFieldValue(["options", "baseURL"], defaultBaseURL);
message.success("Base URL reset to default");
message.success({
content: "Base URL reset to default",
className: "toast-text-black"
});
};

if (loading) {
return (
<div className="min-h-screen bg-white flex items-center justify-center">
<Spin indicator={<LoadingOutlined style={{ fontSize: 48 }} spin />} />
<div className="min-h-screen bg-theme-primary flex items-center justify-center">
<Spin
indicator={
<LoadingOutlined
className="fill-theme-icon"
style={{ fontSize: 48 }}
spin
/>
}
/>
</div>
);
}

return (
<div className="min-h-screen bg-white">
<div className="min-h-screen bg-theme-primary">
{/* Header */}
<div className="border-b border-gray-200 bg-white">
<div className="border-b border-theme-input bg-theme-primary">
<div className="max-w-3xl mx-auto px-6 py-6">
<div className="flex items-center gap-4">
<img
src="/icon.png"
src={isDarkMode ? "/icon_white.png" : "/icon.png"}
alt="OpenBrowser Logo"
className="w-12 h-12 rounded-lg"
className="w-12 h-12 radius-8px"
/>
<div>
<h1 className="text-2xl font-semibold text-black">Settings</h1>
<p className="text-sm text-gray-500 mt-1">
<h1 className="text-2xl font-semibold text-theme-primary">
Settings
</h1>
<p
className="text-sm text-theme-primary mt-1"
style={{ opacity: 0.7 }}
>
Configure your AI model preferences (vision models only)
</p>
</div>
Expand All @@ -222,12 +253,15 @@ const OptionsPage = () => {

{/* Content */}
<div className="max-w-3xl mx-auto px-6 py-8">
<div className="bg-white border border-gray-200 rounded-xl p-6">
<div
className="bg-theme-primary border-theme-input rounded-xl p-6"
style={{ borderWidth: "1px", borderStyle: "solid" }}
>
<Form form={form} layout="vertical" initialValues={config}>
<Form.Item
name="llm"
label={
<span className="text-sm font-medium text-gray-900">
<span className="text-sm font-medium text-theme-primary">
LLM Provider
</span>
}
Expand All @@ -242,7 +276,8 @@ const OptionsPage = () => {
placeholder="Choose a LLM provider"
onChange={handleLLMChange}
size="large"
className="w-full"
className="w-full bg-theme-input border-theme-input text-theme-primary input-theme-focus radius-8px"
popupClassName="bg-theme-input border-theme-input dropdown-theme-items"
>
{providerOptions.map((provider) => (
<Option key={provider.value} value={provider.value}>
Expand All @@ -260,7 +295,7 @@ const OptionsPage = () => {
<Form.Item
name="modelName"
label={
<span className="text-sm font-medium text-gray-900">
<span className="text-sm font-medium text-theme-primary">
Model Name
</span>
}
Expand All @@ -275,12 +310,13 @@ const OptionsPage = () => {
key={config.llm}
placeholder="Select or enter model name"
size="large"
className="w-full"
className="w-full bg-theme-input border-theme-input text-theme-primary input-theme-focus radius-8px"
popupClassName="bg-theme-input border-theme-input dropdown-theme-items"
showSearch
allowClear
searchValue={modelSearchValue}
onSearch={setModelSearchValue}
onDropdownVisibleChange={(open) => {
onOpenChange={(open) => {
if (open) setModelSearchValue("");
}}
optionFilterProp="children"
Expand All @@ -300,7 +336,7 @@ const OptionsPage = () => {
<Form.Item
name="apiKey"
label={
<span className="text-sm font-medium text-gray-900">
<span className="text-sm font-medium text-theme-primary">
API Key
</span>
}
Expand All @@ -314,22 +350,28 @@ const OptionsPage = () => {
<Input.Password
placeholder="Enter your API key"
size="large"
className="w-full"
className="w-full bg-theme-input border-theme-input text-theme-primary input-theme-focus radius-8px"
/>
</Form.Item>

<Form.Item
name={["options", "baseURL"]}
label={
<div className="flex items-center justify-between">
<span className="text-sm font-medium text-gray-900">
Base URL <span className="text-gray-400">(Optional)</span>
<span className="text-sm font-medium text-theme-primary">
Base URL{" "}
<span
className="text-theme-primary"
style={{ opacity: 0.5 }}
>
(Optional)
</span>
</span>
<Button
type="link"
type="text"
size="small"
onClick={handleResetBaseURL}
className="text-xs px-0"
className="text-xs px-0 text-theme-icon"
>
Reset to default
</Button>
Expand All @@ -339,18 +381,18 @@ const OptionsPage = () => {
<Input
placeholder="Enter custom base URL"
size="large"
className="w-full"
className="w-full bg-theme-input border-theme-input text-theme-primary input-theme-focus radius-8px"
/>
</Form.Item>

<div className="border-t border-gray-200 pt-6 mt-6">
<div className="border-t border-theme-input pt-6 mt-6">
<Form.Item
name="webSearchEnabled"
valuePropName="checked"
className="mb-4"
>
<Checkbox>
<span className="text-sm font-medium text-gray-900">
<Checkbox className="checkbox-theme text-theme-primary">
<span className="text-sm font-medium text-theme-primary">
Enable web search (Exa AI)
</span>
</Checkbox>
Expand All @@ -367,17 +409,22 @@ const OptionsPage = () => {
<Form.Item
name="exaApiKey"
label={
<span className="text-sm font-medium text-gray-900">
<span className="text-sm font-medium text-theme-primary">
Exa API Key{" "}
<span className="text-gray-400">(Optional)</span>
<span
className="text-theme-primary"
style={{ opacity: 0.5 }}
>
(Optional)
</span>
</span>
}
tooltip="Uses free tier if not provided"
>
<Input.Password
placeholder="sk-..."
size="large"
className="w-full"
className="w-full bg-theme-input border-theme-input text-theme-primary input-theme-focus radius-8px"
allowClear
/>
</Form.Item>
Expand All @@ -391,18 +438,10 @@ const OptionsPage = () => {
onClick={handleSave}
size="large"
icon={<SaveOutlined />}
className="w-full bg-black hover:bg-gray-800 border-black text-white"
className="w-full bg-inverted"
block
style={{
backgroundColor: "#000000",
borderColor: "#000000",
color: "#ffffff"
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = "#1f2937";
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = "#000000";
borderColor: "inherit"
}}
>
Save Settings
Expand All @@ -419,6 +458,8 @@ const root = createRoot(document.getElementById("root")!);

root.render(
<React.StrictMode>
<OptionsPage />
<ThemeProvider>
<OptionsPage />
</ThemeProvider>
</React.StrictMode>
);
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const AgentExecutionCard: React.FC<AgentExecutionCardProps> = ({
return (
<Collapse
size="small"
className={`agent-collapse mb-2 border-l-4 ${getBorderColor()}`}
className={`agent-collapse mb-2 border-l-4 ${getBorderColor()} bg-theme-input border-theme-input`}
activeKey={activeKey}
onChange={(keys) => {
setIsCollapsed(!(keys as string[]).includes("agent"));
Expand All @@ -90,7 +90,7 @@ export const AgentExecutionCard: React.FC<AgentExecutionCardProps> = ({
<div
className={`flex-1 min-w-0 ${isCollapsed ? "truncate" : "whitespace-normal"}`}
>
<Text strong className="text-sm">
<Text strong className="text-sm text-theme-primary">
{agentNode.task || agentNode.name}
</Text>
</div>
Expand Down
22 changes: 11 additions & 11 deletions chromium-extension/src/sidebar/components/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const ChatInput: React.FC<ChatInputProps> = ({
const isEmpty = !inputValue.trim() && uploadedFiles.length === 0;

return (
<div className="p-4 bg-gray-100">
<div className="p-4">
{/* Uploaded Files */}
{uploadedFiles.length > 0 && (
<div className="mb-3">
Expand All @@ -56,7 +56,7 @@ export const ChatInput: React.FC<ChatInputProps> = ({
return (
<div
key={file.id}
className="inline-flex items-center px-2 py-1 bg-gray-100 rounded border border-gray-200"
className="inline-flex items-center px-2 py-1 bg-theme-input rounded border-theme-input"
>
{isImage ? (
<Image
Expand All @@ -70,9 +70,9 @@ export const ChatInput: React.FC<ChatInputProps> = ({
preview={false}
/>
) : (
<FileOutlined className="mr-2" />
<FileOutlined className="mr-2 fill-theme-icon" />
)}
<Text className="text-xs mr-2 max-w-[150px] overflow-hidden text-ellipsis whitespace-nowrap">
<Text className="text-xs mr-2 max-w-[150px] overflow-hidden text-ellipsis whitespace-nowrap text-theme-primary">
{file.filename}
</Text>
<Button
Expand All @@ -90,7 +90,7 @@ export const ChatInput: React.FC<ChatInputProps> = ({
)}

{/* Floating Chat Input Box */}
<div className="relative bg-white border border-gray-300 rounded-xl shadow-sm hover:shadow-md transition-shadow">
<div className="bg-theme-input border-theme-input relative shadow-sm hover:shadow-md transition-shadow radius-8px" style={{borderWidth: '1px', borderStyle: 'solid', overflow: 'hidden'}}>
<input
ref={fileInputRef}
type="file"
Expand Down Expand Up @@ -142,26 +142,26 @@ export const ChatInput: React.FC<ChatInputProps> = ({
<Button
type="text"
danger
icon={<StopOutlined />}
icon={<StopOutlined className="fill-red-500" />}
onClick={onStop}
className="text-red-500 hover:text-red-600"
className="text-red-500"
/>
) : isEmpty ? (
<Button
type="text"
icon={<PlusOutlined />}
icon={<PlusOutlined className="fill-theme-icon" />}
onClick={onNewSession}
disabled={sending}
className="text-blue-500 hover:text-blue-600 disabled:text-gray-300"
className="text-theme-icon"
/>
) : (
<Button
type="text"
icon={<SendOutlined />}
icon={<SendOutlined className="fill-theme-icon" />}
onClick={onSend}
loading={sending}
disabled={sending}
className="text-blue-500 hover:text-blue-600 disabled:text-gray-300"
className="text-theme-icon"
/>
)}
</div>
Expand Down
Loading