Skip to content

Commit ff0fcd6

Browse files
committed
Add cancellable progress tracking with elapsed time display for website fetching
1 parent 65fd999 commit ff0fcd6

8 files changed

Lines changed: 76 additions & 45 deletions

File tree

‎apps/editor/src/views/panel/backend/message-handlers/handle-paste-url.ts‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as vscode from 'vscode'
2+
import axios from 'axios'
23
import { PasteUrlMessage } from '../../types/messages'
34
import { PanelProvider } from '../panel-provider'
45
import * as fs from 'fs'
@@ -31,7 +32,23 @@ export const handle_paste_url = async (
3132
return
3233
}
3334

34-
const content = await fetch_and_save_website(url)
35+
const cancel_token_source = axios.CancelToken.source()
36+
panel_provider.api_call_cancel_token_source = cancel_token_source
37+
38+
panel_provider.send_message({
39+
command: 'SHOW_PROGRESS',
40+
title: 'Fetching website...',
41+
show_elapsed_time: true,
42+
cancellable: true
43+
})
44+
45+
let content: string | null = null
46+
try {
47+
content = await fetch_and_save_website(url, cancel_token_source.token)
48+
} finally {
49+
panel_provider.send_message({ command: 'HIDE_PROGRESS' })
50+
panel_provider.api_call_cancel_token_source = null
51+
}
3552

3653
if (content) {
3754
panel_provider.add_text_at_cursor_position(`#Website(${url})`)

‎apps/editor/src/views/panel/backend/utils/website-fetcher.ts‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import axios from 'axios'
1+
import axios, { CancelToken } from 'axios'
22
import { JSDOM } from 'jsdom'
33
import { Readability, isProbablyReaderable } from '@mozilla/readability'
44
import createDOMPurify from 'dompurify'
@@ -99,7 +99,8 @@ export const get_website_file_path = (url: string) => {
9999
}
100100

101101
export const fetch_and_save_website = async (
102-
url: string
102+
url: string,
103+
cancel_token?: CancelToken
103104
): Promise<string | null> => {
104105
try {
105106
const file_path = get_website_file_path(url)
@@ -109,7 +110,8 @@ export const fetch_and_save_website = async (
109110
'User-Agent':
110111
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36'
111112
},
112-
timeout: 5000
113+
timeout: 5000,
114+
cancelToken: cancel_token
113115
})
114116

115117
if (response.status == 200 && typeof response.data == 'string') {

‎packages/ui/src/components/editor/panel/modals/ApiManagerModal/ApiManagerModal.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export const ApiManagerModal: React.FC<Props> = (props) => {
151151
{item.total_tokens !== undefined && (
152152
<div>({format_tokens(item.total_tokens)})</div>
153153
)}
154-
{item.show_elapsed_time !== false && (
154+
{item.show_elapsed_time && (
155155
<div>{(elapsed_ms / 1000).toFixed(1)}s</div>
156156
)}
157157
</div>

‎packages/ui/src/components/editor/panel/modals/Modal/Modal.module.scss‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@
5656
}
5757
}
5858

59+
.elapsed-time {
60+
position: absolute;
61+
top: 5px;
62+
right: 7px;
63+
font-size: 11px;
64+
font-variant-numeric: tabular-nums;
65+
color: var(--cwc-text-color-dimmed);
66+
}
67+
5968
.content {
6069
padding: 8px 12px 12px 12px;
6170
display: flex;

‎packages/ui/src/components/editor/panel/modals/Modal/Modal.tsx‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useEffect, useState } from 'react'
12
import cn from 'classnames'
23
import { Scrollable } from '../../Scrollable'
34
import styles from './Modal.module.scss'
@@ -10,15 +11,34 @@ type Props = {
1011
content_max_height?: string
1112
use_full_width?: boolean
1213
on_background_click?: () => void
14+
show_elapsed_time?: boolean
1315
}
1416

1517
export const Modal: React.FC<Props> = (props) => {
18+
const [elapsed_time, set_elapsed_time] = useState(0)
19+
1620
const handle_background_click = (e: React.MouseEvent<HTMLDivElement>) => {
1721
if (e.target == e.currentTarget) {
1822
props.on_background_click?.()
1923
}
2024
}
2125

26+
useEffect(() => {
27+
let elapsed_time_timer: NodeJS.Timeout | undefined
28+
29+
if (props.show_elapsed_time) {
30+
set_elapsed_time(0)
31+
const start_time = Date.now()
32+
elapsed_time_timer = setInterval(() => {
33+
set_elapsed_time((Date.now() - start_time) / 1000)
34+
}, 100)
35+
}
36+
37+
return () => {
38+
if (elapsed_time_timer) clearInterval(elapsed_time_timer)
39+
}
40+
}, [props.show_elapsed_time])
41+
2242
return (
2343
<div className={styles.overlay} onClick={handle_background_click}>
2444
<div
@@ -47,6 +67,12 @@ export const Modal: React.FC<Props> = (props) => {
4767
</div>
4868
)}
4969

70+
{props.show_elapsed_time && (
71+
<div className={styles['elapsed-time']}>
72+
{elapsed_time.toFixed(1)}s
73+
</div>
74+
)}
75+
5076
{props.content_slot &&
5177
(props.content_max_height ? (
5278
<div className={styles.scrollable}>

‎packages/ui/src/components/editor/panel/modals/ProgressModal/ProgressModal.module.scss‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
.elapsed-time {
2-
text-align: center;
3-
font-size: 18px;
4-
font-variant-numeric: tabular-nums;
5-
}
6-
71
.tokens-per-second {
82
text-align: center;
93
color: var(--cwc-text-color-dimmed);

‎packages/ui/src/components/editor/panel/modals/ProgressModal/ProgressModal.stories.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const WithProgress = () => {
5050
title="Receiving..."
5151
progress={progress}
5252
tokens_per_second={250}
53+
show_elapsed_time={true}
5354
on_cancel={handle_cancel}
5455
/>
5556
) : null

‎packages/ui/src/components/editor/panel/modals/ProgressModal/ProgressModal.tsx‎

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const format_tokens_per_second = (tps: number): string => {
2222

2323
export const ProgressModal: React.FC<Props> = (props) => {
2424
const [is_visible, set_is_visible] = useState(!props.delay_visibility)
25-
const [elapsed_time, set_elapsed_time] = useState(0)
2625

2726
useEffect(() => {
2827
let visibility_timer: NodeJS.Timeout | undefined
@@ -35,58 +34,41 @@ export const ProgressModal: React.FC<Props> = (props) => {
3534
set_is_visible(true)
3635
}
3736

38-
let elapsed_time_timer: NodeJS.Timeout | undefined
39-
if (props.show_elapsed_time !== false) {
40-
set_elapsed_time(0)
41-
const start_time = Date.now()
42-
elapsed_time_timer = setInterval(() => {
43-
set_elapsed_time((Date.now() - start_time) / 1000)
44-
}, 100)
45-
}
46-
4737
return () => {
4838
clearTimeout(visibility_timer)
49-
clearInterval(elapsed_time_timer)
5039
}
51-
}, [props.show_elapsed_time, props.delay_visibility])
40+
}, [props.delay_visibility])
5241

5342
return is_visible ? (
5443
<div
5544
onKeyDown={(e) => {
56-
if (e.key === 'Escape') {
45+
if (e.key == 'Escape') {
5746
e.stopPropagation()
5847
props.on_cancel?.()
5948
}
6049
}}
6150
>
6251
<Modal
6352
title={props.title}
53+
show_elapsed_time={props.show_elapsed_time}
6454
content_slot={
65-
<>
66-
{props.show_elapsed_time !== false && (
67-
<div className={styles['elapsed-time']}>
68-
{elapsed_time.toFixed(1)}s
55+
<div className={styles.content}>
56+
{props.tokens_per_second !== undefined && (
57+
<div className={styles['tokens-per-second']}>
58+
{format_tokens_per_second(props.tokens_per_second)} tokens/s
6959
</div>
7060
)}
71-
72-
<div className={styles.content}>
73-
{props.tokens_per_second !== undefined && (
74-
<div className={styles['tokens-per-second']}>
75-
{format_tokens_per_second(props.tokens_per_second)} tokens/s
76-
</div>
61+
<div className={styles.progress}>
62+
{props.progress !== undefined ? (
63+
<div
64+
className={styles.progress__fill}
65+
style={{ width: `${props.progress}%` }}
66+
/>
67+
) : (
68+
<div className={styles['progress__fill--indeterminate']} />
7769
)}
78-
<div className={styles.progress}>
79-
{props.progress !== undefined ? (
80-
<div
81-
className={styles.progress__fill}
82-
style={{ width: `${props.progress}%` }}
83-
/>
84-
) : (
85-
<div className={styles['progress__fill--indeterminate']} />
86-
)}
87-
</div>
8870
</div>
89-
</>
71+
</div>
9072
}
9173
footer_slot={
9274
props.on_cancel ? (

0 commit comments

Comments
 (0)