Skip to content

Commit 01e7fab

Browse files
committed
feat: add quick capture
Signed-off-by: EINDEX <snowstarlbk@gmail.com>
1 parent e11c88a commit 01e7fab

File tree

11 files changed

+192
-19
lines changed

11 files changed

+192
-19
lines changed

package-lock.json

Lines changed: 28 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
"@types/marked": "^4.0.8",
2323
"lodash": "^4.17.21",
2424
"marked": "^4.2.12",
25+
"markit": "^0.2.0",
2526
"react": "^18.2.0",
26-
"react-dom": "^18.2.0"
27+
"react-dom": "^18.2.0",
28+
"turndown": "^7.1.1"
2729
},
2830
"devDependencies": {
2931
"@semantic-release/changelog": "^6.0.2",
@@ -34,6 +36,7 @@
3436
"@semantic-release/release-notes-generator": "^10.0.3",
3537
"@types/react": "^18.0.26",
3638
"@types/react-dom": "^18.0.10",
39+
"@types/turndown": "^5.0.1",
3740
"@types/webextension-polyfill": "^0.10.0",
3841
"archiver": "^5.3.1",
3942
"autoprefixer": "^10.4.13",

src/config.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@ import Browser from 'webextension-polyfill';
33
export type LogseqCopliotConfig = {
44
logseqHost: string;
55
logseqAuthToken: string;
6+
enableQuickCapture: boolean;
67
};
78

89
export const getLogseqCopliotConfig =
910
async (): Promise<LogseqCopliotConfig> => {
10-
const { logseqHost = 'http://localhost:12315', logseqAuthToken = '' } =
11-
await Browser.storage.local.get();
11+
const {
12+
logseqHost = 'http://localhost:12315',
13+
logseqAuthToken = '',
14+
enableQuickCapture = true,
15+
} = await Browser.storage.local.get();
1216
return {
1317
logseqHost,
1418
logseqAuthToken,
19+
enableQuickCapture,
1520
};
1621
};
1722

src/manifest.json.cjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const ReleaseFor = {
1515
default_popup: 'popup.html',
1616
default_title: 'Logseq Copilot',
1717
},
18+
"host_permissions" : ["*://*/*"]
1819
},
1920
edge: {
2021
manifest_version: 3,
@@ -63,7 +64,7 @@ const build = (releaseFor) => {
6364
css: ['content-script.css'],
6465
},
6566
],
66-
permissions: ['storage', 'tabs'],
67+
permissions: ['storage', 'tabs', 'scripting', 'activeTab'],
6768
options_ui: {
6869
page: 'options.html',
6970
browser_style: false,

src/pages/background/index.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { removeUrlHash } from '../../utils';
55
import { setExtensionBadge } from './utils';
66

77
const logseqClient = new LogseqClient();
8+
// const connect = Browser.runtime.connect();
89

910
Browser.runtime.onConnect.addListener((port) => {
1011
port.onMessage.addListener((msg) => {
@@ -17,10 +18,24 @@ Browser.runtime.onConnect.addListener((port) => {
1718
promise.catch((err) => console.error(err));
1819
} else if (msg.type === 'open-options') {
1920
Browser.runtime.openOptionsPage();
21+
} else if (msg.type === 'quick-capture') {
22+
quickCapture(msg.data);
23+
} else {
24+
console.debug(msg);
2025
}
2126
});
2227
});
2328

29+
const quickCapture = async (data: string) => {
30+
const tab = await Browser.tabs.query({ active: true, currentWindow: true });
31+
if (!tab) return;
32+
const activeTab = tab[0];
33+
const url = `logseq://x-callback-url/quickCapture?title=${
34+
activeTab.title
35+
}&url=${encodeURIComponent(activeTab.url)}&content=${data}`;
36+
Browser.tabs.update(activeTab.id, { url: url });
37+
};
38+
2439
Browser.runtime.onInstalled.addListener(() => {
2540
const promise = new Promise(async () => {
2641
const { logseqAuthToken } = await getLogseqCopliotConfig();

src/pages/content/LogseqCopliot.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from 'react';
22
import { LogseqSearchResult } from '@/types/logseqBlock';
33
import { LogseqResponseType } from '../logseq/client';
44
import { LogseqBlock } from '@components/LogseqBlock';
5-
import { LogseqPageContent } from '@components/LogseqPageContent';
65
import LogseqPageLink from '@components/LogseqPage';
76
import Browser from 'webextension-polyfill';
87
import styles from './index.module.scss';

src/pages/content/QuickCapture.tsx

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import _ from 'lodash';
2+
import { useEffect, useState } from 'react';
3+
import { createRoot } from 'react-dom/client';
4+
import TurndownService from 'turndown';
5+
import Browser from 'webextension-polyfill';
6+
import logo from '../../assets/img/logo.png';
7+
import scssStyles from './index.module.scss';
8+
9+
const logseqCopilotPopupId = 'logseq-copilot-popup';
10+
export const zIndex = '2147483647';
11+
12+
const connect = Browser.runtime.connect();
13+
14+
const QuickCapture = () => {
15+
const [position, setPostion] = useState({
16+
x: 0,
17+
y: 0,
18+
});
19+
const [show, setShow] = useState(false);
20+
21+
const clicked = (event: MouseEvent) => {
22+
if (show) {
23+
return;
24+
}
25+
const selection = getSelection();
26+
if (selection && selection.toString().trim() !== '') {
27+
setShow(true);
28+
setPostion({ x: event.pageX + 10, y: event.pageY + 10 });
29+
console.log('clicked');
30+
}
31+
};
32+
33+
const release = (event: MouseEvent) => {
34+
setShow(false);
35+
};
36+
37+
// const capture = async (data: string) => {
38+
// const tab = await Browser.tabs.query({ active: true, currentWindow: true });
39+
// if (!tab) return;
40+
// const activeTab = tab[0];
41+
// window.open(
42+
// `logseq://x-callback-url/quickCapture?title=${
43+
// activeTab.title
44+
// }&url=${encodeURIComponent(activeTab.url)}&content=${data}`,
45+
// );
46+
// };
47+
48+
const quickCapture = () => {
49+
setShow(false);
50+
const selection = getSelection();
51+
const range = selection!.getRangeAt(0);
52+
const clonedSelection = range.cloneContents();
53+
const turndownService = new TurndownService();
54+
selection?.removeAllRanges();
55+
connect.postMessage({
56+
type: 'quick-capture',
57+
data: turndownService.turndown(clonedSelection),
58+
});
59+
console.log('quick-capture');
60+
};
61+
62+
useEffect(() => {
63+
document.addEventListener('mouseup', _.debounce(clicked, 100));
64+
document.addEventListener('mousedown', _.debounce(release, 100));
65+
});
66+
67+
const styles = (): React.CSSProperties => {
68+
return {
69+
display: show ? 'block' : 'none',
70+
position: 'absolute',
71+
left: `${position.x}px`,
72+
top: `${position.y}px`,
73+
zIndex: zIndex,
74+
background: '#fff',
75+
};
76+
};
77+
78+
return (
79+
<div className={scssStyles.popupButton} style={styles()}>
80+
<img
81+
className={scssStyles.popupButton}
82+
src={logo}
83+
onClick={quickCapture}
84+
alt={'logseq-quickcapture-button'}
85+
/>
86+
</div>
87+
);
88+
};
89+
90+
const mountQuickCapture = () => {
91+
const contrainer = document.createElement('div');
92+
contrainer.id = logseqCopilotPopupId;
93+
document.getElementsByTagName('body')[0].appendChild(contrainer);
94+
const root = createRoot(contrainer);
95+
96+
root.render(<QuickCapture />);
97+
};
98+
99+
export default mountQuickCapture;

src/pages/content/index.module.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,7 @@
4040
@apply text-gray-500 no-underline hover:underline;
4141
}
4242
}
43+
44+
.popupButton {
45+
@apply rounded-lg h-6 w-6;
46+
}

src/pages/content/index.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import { getLogseqCopliotConfig } from '@/config';
12
import { createRoot } from 'react-dom/client';
23
import Browser from 'webextension-polyfill';
34
import { LogseqCopliot } from './LogseqCopliot';
5+
import mountQuickCapture from './QuickCapture';
46
import searchEngines, {
57
Baidu,
68
Bing,
@@ -9,7 +11,6 @@ import searchEngines, {
911
SearX,
1012
Yandex,
1113
} from './searchingEngines/searchingEngines';
12-
import _ from 'lodash';
1314

1415
const connect = Browser.runtime.connect();
1516

@@ -51,4 +52,9 @@ if (searchEngine) {
5152
if (searchEngine.reload) {
5253
searchEngine.reload(() => run(searchEngine));
5354
}
54-
}
55+
}
56+
57+
getLogseqCopliotConfig().then(({ enableQuickCapture }) => {
58+
if (!enableQuickCapture) return;
59+
mountQuickCapture();
60+
});

src/pages/logseq/client.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616

1717
marked.setOptions({
1818
gfm: true,
19+
tables: true,
1920
});
2021

2122
type Graph = {

0 commit comments

Comments
 (0)