Skip to content

Commit

Permalink
Merge pull request #53 from refly-ai/feat/isomorphic-copilot-for-exte…
Browse files Browse the repository at this point in the history
…nsion

Feat/isomorphic copilot for extension
  • Loading branch information
mrcfps authored Jun 10, 2024
2 parents 6f3d3f4 + c8ee176 commit c81c517
Show file tree
Hide file tree
Showing 45 changed files with 457 additions and 374 deletions.
2 changes: 1 addition & 1 deletion apps/extension-wxt/src/components/home/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import FullScreenSVG from '@/assets/side/full-screen.svg';
import { IconTip } from './icon-tip';
import { Avatar } from '@arco-design/web-react';
// stores
import { useSiderStore } from '@/stores/sider';
import { useSiderStore } from '@refly/ai-workspace-common/stores/sider';
import { useNavigate } from '@refly/ai-workspace-common/utils/router';
import { getClientOrigin } from '@/utils/url';
import { useUserStore } from '@/stores/user';
Expand Down
2 changes: 1 addition & 1 deletion apps/extension-wxt/src/components/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { ContentSelectorBtn } from '@/components/content-selector-btn/index';
import { useQuickActionStore } from '../../stores/quick-action';
import { useChatStore } from '../../stores/chat';
import { useMessageStateStore } from '@/stores/message-state';
import { useSiderStore } from '@/stores/sider';
import { useSiderStore } from '@refly/ai-workspace-common/stores/sider';
import { useWeblinkStore } from '@/stores/weblink';
import { SearchTarget, useSearchStateStore } from '@/stores/search-state';
import { useContentSelectorStore } from '@/stores/content-selector';
Expand Down
73 changes: 31 additions & 42 deletions apps/extension-wxt/src/components/thread-item/header.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
import Logo from "@/assets/logo.svg";
import CloseGraySVG from "@/assets/side/close.svg";
import SendSVG from "@/assets/side/send.svg";
import NotificationSVG from "@/assets/side/notification.svg";
import SettingGraySVG from "@/assets/side/setting.svg";
import FullScreenSVG from "@/assets/side/full-screen.svg";
import { IconTip } from "@/components/home/icon-tip";
import { Avatar, Button, Message as message } from "@arco-design/web-react";
import { useSiderStore } from "@/stores/sider";
import { useNavigate } from "react-router-dom";
import { useUserStore } from "@/stores/user";
import { getClientOrigin } from "@/utils/url";
import {
IconClockCircle,
IconHome,
IconPlus,
IconShareExternal,
} from "@arco-design/web-react/icon";
import { time } from "@/utils/time";
import Logo from '@/assets/logo.svg';
import CloseGraySVG from '@/assets/side/close.svg';
import SendSVG from '@/assets/side/send.svg';
import NotificationSVG from '@/assets/side/notification.svg';
import SettingGraySVG from '@/assets/side/setting.svg';
import FullScreenSVG from '@/assets/side/full-screen.svg';
import { IconTip } from '@/components/home/icon-tip';
import { Avatar, Button, Message as message } from '@arco-design/web-react';
import { useSiderStore } from '@refly/ai-workspace-common/stores/sider';
import { useNavigate } from 'react-router-dom';
import { useUserStore } from '@/stores/user';
import { getClientOrigin } from '@/utils/url';
import { IconClockCircle, IconHome, IconPlus, IconShareExternal } from '@arco-design/web-react/icon';
import { time } from '@/utils/time';
// types
import type { Conversation } from "@/types/conversation";
import type { Conversation } from '@/types/conversation';
// 第三方库
import copyToClipboard from "copy-to-clipboard";
import { useHomeStateStore } from "@/stores/home-state";
import { useTranslation } from "react-i18next";
import { LOCALE } from "@/types";
import copyToClipboard from 'copy-to-clipboard';
import { useHomeStateStore } from '@/stores/home-state';
import { useTranslation } from 'react-i18next';
import { LOCALE } from '@/types';

interface ThreadHeaderProps {
thread: Conversation;
Expand All @@ -41,14 +36,11 @@ export const Header = (props: ThreadHeaderProps) => {

return (
<header>
<div
className="refly-brand-container"
style={{ display: "flex", flexDirection: "row", alignItems: "center" }}
>
<div className="refly-brand-container" style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
<div
className="brand"
onClick={() => {
window.open(`${getClientOrigin()}/`, "_blank");
window.open(`${getClientOrigin()}/`, '_blank');
}}
>
<img src={Logo} alt="Refly" />
Expand All @@ -57,36 +49,33 @@ export const Header = (props: ThreadHeaderProps) => {
<Button
type="primary"
onClick={() => {
navigate("/");
homeStateStore.setActiveTab("home");
navigate('/');
homeStateStore.setActiveTab('home');
}}
style={{ borderRadius: 4, marginLeft: 12 }}
>
<span
style={{
fontSize: uiLocale === LOCALE.EN ? 12 : 14,
fontWeight: "normal",
color: "#fff",
fontWeight: 'normal',
color: '#fff',
}}
>
{t("threadDetail.header.newThread")}
{t('threadDetail.header.newThread')}
</span>
</Button>
</div>
<div className="funcs">
<span key={2} style={{ display: "inline-block", marginRight: 12 }}>
<IconClockCircle style={{ fontSize: 14, color: "#64645F" }} />
<span
className="thread-library-list-item-text"
style={{ fontSize: uiLocale === LOCALE.EN ? 12 : 14 }}
>
<span key={2} style={{ display: 'inline-block', marginRight: 12 }}>
<IconClockCircle style={{ fontSize: 14, color: '#64645F' }} />
<span className="thread-library-list-item-text" style={{ fontSize: uiLocale === LOCALE.EN ? 12 : 14 }}>
{time(props.thread?.updatedAt, uiLocale).utc().fromNow()}
</span>
</span>
<IconTip text={t("loggedHomePage.homePage.header.close")}>
<IconTip text={t('loggedHomePage.homePage.header.close')}>
<img
src={CloseGraySVG}
alt={t("loggedHomePage.homePage.header.close")}
alt={t('loggedHomePage.homePage.header.close')}
onClick={(_) => siderStore.setShowSider(false)}
/>
</IconTip>
Expand Down
14 changes: 11 additions & 3 deletions apps/extension-wxt/src/entrypoints/background/events/activated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@ import { Tabs, browser } from 'wxt/browser';

export const sendHeartBeatMessage = (activeInfo: Tabs.OnActivatedActiveInfoType) => {
// 给 tab 发消息,进行 userProfile 检查,包括更新 i18n 和登录状态
browser.tabs.sendMessage(activeInfo.tabId, {
name: 'refly-status-check',
});
try {
browser.tabs
.sendMessage(activeInfo.tabId, {
name: 'refly-status-check',
})
.catch((err) => {
console.log('send heart beat error: ', err);
});
} catch (err) {
console.log('send heart beat error: ', err);
}
};

export const onActivated = (activeInfo: Tabs.OnActivatedActiveInfoType) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ export const onExternalMessage = async (

if (!userProfile) {
// 回复消息,关闭弹窗
browser.tabs.sendMessage(sender?.tab?.id!, {
name: 'refly-login-notify',
});
browser.tabs
.sendMessage(sender?.tab?.id!, {
name: 'refly-login-notify',
})
.catch((err) => {
console.log('onExternalMessage refly-login-notify send message error', err);
});

const lastActiveTab = await getLastActiveTab();

Expand All @@ -32,13 +36,25 @@ export const onExternalMessage = async (
}

await storage.setItem('sync:refly-login-notify', JSON.stringify(msg));
await browser.tabs
.sendMessage(lastActiveTab?.id as number, {
name: 'refly-login-notify',
data: JSON.stringify(msg),
})
.catch((err) => {
console.log('onExternalMessage refly-login-notify send message error', err);
});
}
}

if (msg?.name === 'logout-notify') {
await storage.removeItem('sync:refly-login-notify');
browser.tabs.sendMessage(sender?.tab?.id!, {
name: 'refly-logout-notify',
});
browser.tabs
.sendMessage(sender?.tab?.id!, {
name: 'refly-logout-notify',
})
.catch((err) => {
console.log('onExternalMessage logout-notify send message error', err);
});
}
};
16 changes: 11 additions & 5 deletions apps/extension-wxt/src/entrypoints/background/events/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,14 @@ export const handleRequestReflect = async (msg: BackgroundMessage) => {
body: res,
});
} else if (msg?.source === 'extension-sidepanel') {
await browser.runtime.sendMessage({
name: msg?.name,
body: res,
});
try {
await browser.runtime.sendMessage({
name: msg?.name,
body: res,
});
} catch (err) {
console.log('handleRequestReflect send message error', err);
}
}
};

Expand All @@ -76,12 +80,14 @@ export const handleRegisterSidePanel = async (msg: BackgroundMessage) => {
browser.browserAction.openPopup();
browser.action.openPopup();
});
browser.action.setPopup({ popup: path });
console.log('register popup success');
} else {
// @ts-ignore
browser?.sidePanel
.setPanelBehavior({ openPanelOnActionClick: true })
.then(() => {
console.log('open sidePanel success');
console.log('register sidePanel success');
})
.catch((error: any) => console.error(`sidePanel open error: `, error));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,7 @@ export const onPort = async (port: Runtime.Port) => {
if (comingPort.name === 'streaming-chat') {
return handleStreamingChat(message, {
send: async (msg: any) => {
const runtime = message?.source;

if (runtime === 'extension-csui') {
const tab = await getCurrentTab();
browser.tabs.sendMessage(tab?.id as number, msg);
} else if (runtime === 'extension-sidepanel') {
port?.postMessage(msg);
}
port?.postMessage(msg);
},
});
}
Expand Down
26 changes: 14 additions & 12 deletions apps/extension-wxt/src/entrypoints/main-csui.content/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ import { useProcessLoginNotify } from '@/hooks/use-process-login-notify';
import { useBindCommands } from '@/hooks/use-bind-commands';
import { useSetContainerDimension } from '@/hooks/use-set-container-dimension';
// stores
import { useSiderStore } from '@/stores/sider';
import { useSiderStore } from '@refly/ai-workspace-common/stores/sider';
import { useQuickActionStore } from '@/stores/quick-action';
import { useUserStore } from '@refly/ai-workspace-common/stores/user';

// 组件
import { Message, Spin } from '@arco-design/web-react';
import { AppRouter } from '@/routes/index';
import { Markdown } from '@/components/markdown';

// utils
import { checkPageUnsupported } from '@refly/ai-workspace-common/utils/extension/check';

// 加载国际化
import '@/i18n/config';
Expand All @@ -30,8 +32,6 @@ import '@/styles/style.css';
import './App.scss';
import { getPopupContainer } from '@refly/ai-workspace-common/utils/ui';
import { checkBrowserArc } from '@/utils/browser';
import { useChatStore } from '@refly/ai-workspace-common/stores/chat';
import { fakeMessages } from '../../fake-data/message';
// 设置 runtime 环境
import { getEnv, setRuntime } from '@refly/ai-workspace-common/utils/env';
const Sentry = _Sentry;
Expand Down Expand Up @@ -77,15 +77,17 @@ const App = () => {
});
}, []);
useEffect(() => {
checkBrowserArc();
/**
* 如果决定是否使用 SidePanel 还是 Content Script UI?
*
* 1. 如果页面支持 CSUI 注入,判断是否是 Arc,直接处理
* 2. 如果不支持 CSUI 注入,比如 extension://url,则打开 Popup 要求跳转到支持页面,然后处理
*/
if (!checkPageUnsupported(location.href)) {
checkBrowserArc();
}
setRuntime('extension-csui');
userStore.setRuntime('extension-sidepanel');
}, []);

const chatStore = useChatStore();

useEffect(() => {
chatStore.setMessages(fakeMessages as any);
userStore.setRuntime('extension-csui');
}, []);

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import ReactDOM from 'react-dom/client';
import { defineContentScript } from 'wxt/sandbox';
import { createShadowRootUi } from 'wxt/client';

import App from './App';
import { setRuntime } from '@refly/ai-workspace-common/utils/env';

export default defineContentScript({
matches: ['<all_urls>'],
// 2. Set cssInjectionMode
cssInjectionMode: 'ui',

async main(ctx) {
setRuntime('extension-csui');

console.log('ctx', ctx);
// 3. Define your UI
// 3. Define your UI`
const ui = await createShadowRootUi(ctx, {
name: 'refly-main-app',
position: 'inline',
Expand Down
39 changes: 6 additions & 33 deletions apps/extension-wxt/src/entrypoints/popup/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,11 @@ import './App.scss';

import { IconRefresh, IconBulb } from '@arco-design/web-react/icon';

import Logo from '~/assets/logo.svg';
import Logo from '@/assets/logo.svg';
import { useStorage } from '@/hooks/use-storage';
import { browser } from 'wxt/browser';
import { getCurrentTab } from '@/utils/extension/tabs';

const getActiveTab = async () => {
const [tab] = await browser.tabs.query({
active: true,
currentWindow: true,
});
return tab;
};

const checkPageUnsupported = (pageUrl: string) => {
console.log('checking page url', JSON.stringify(pageUrl));

if (pageUrl) {
const checkBrowserSettingPage =
pageUrl.startsWith('chrome://') || pageUrl.startsWith('edge://') || pageUrl.startsWith('about:');
const checkBrowserExtensionStorePage = [
'https://browser.google.com/webstore',
'https://microsoftedge.microsoft.com/addons',
'https://addons.mozilla.org/en-US/firefox',
].some((url) => pageUrl.startsWith(url));

return checkBrowserSettingPage || checkBrowserExtensionStorePage;
}

return true;
};
import { getCurrentTab } from '@refly/ai-workspace-common/utils/extension/tabs';
import { checkPageUnsupported } from '@refly/ai-workspace-common/utils/extension/check';

/**
* 打开 popup 页面的规则
Expand All @@ -54,7 +29,7 @@ const App = () => {
const [pageUnsupported, setPageUnsupported] = useState(false);

const refreshPage = async () => {
const activeTab = await getActiveTab();
const activeTab = await getCurrentTab();

if (activeTab?.id) {
await browser.tabs.reload(activeTab?.id);
Expand All @@ -80,16 +55,14 @@ const App = () => {
};

const handleRunRefly = async () => {
const activeTab = await getActiveTab();
const activeTab = await getCurrentTab();
setCurrentTabUrl(activeTab?.url || '');
currentTabUrlRef.current = activeTab?.url || '';
console.log('activeTab', activeTab);

if (activeTab) {
console.log('activeTab', browser.tabs.sendMessage);
const res = await browser.tabs.sendMessage(activeTab?.id as number, {
data: { name: 'runRefly', toggle: !isSideBarOpen },
});
const res = await browser.tabs.sendMessage(activeTab?.id as number, { name: 'runRefly', toggle: !isSideBarOpen });

setIsSideBarOpen(!isSideBarOpen);

Expand Down
Loading

0 comments on commit c81c517

Please sign in to comment.