11import { relative } from 'node:path'
22import { slash } from '@antfu/utils'
33import { useCommand } from 'reactive-vscode'
4- import { Position , Range , Selection , TextEditorRevealType , Uri , window , workspace } from 'vscode'
4+ import { ConfigurationTarget , window , workspace } from 'vscode'
55import { useDevServer } from './composables/useDevServer'
6- import { useEditingSlideSource } from './composables/useEditingSlideSource'
7- import { useFocusedSlideNo } from './composables/useFocusedSlideNo'
6+ import { useFocusedSlide } from './composables/useFocusedSlide'
87import { configuredPort , forceEnabled , include , previewSync } from './configs'
9- import { activeEntry , activeProject , activeSlidevData , addProject , projects , rescanProjects } from './projects'
8+ import { activeEntry , activeProject , addProject , projects , rescanProjects } from './projects'
109import { findPossibleEntries } from './utils/findPossibleEntries'
10+ import { getSlidesTitle } from './utils/getSlidesTitle'
1111import { usePreviewWebview } from './views/previewWebview'
1212
1313export function useCommands ( ) {
@@ -17,14 +17,32 @@ export function useCommands() {
1717 useCommand ( 'slidev.rescan-projects' , rescanProjects )
1818
1919 useCommand ( 'slidev.choose-entry' , async ( ) => {
20- const entry = await window . showQuickPick ( [ ...projects . keys ( ) ] , {
21- title : 'Choose active slides entry.' ,
22- } )
23- if ( entry )
24- activeEntry . value = entry
20+ while ( true ) {
21+ const addNewEntry = '$(add) Add new slides entry...'
22+ const entry = await window . showQuickPick (
23+ [ ...projects . keys ( ) , addNewEntry ] ,
24+ {
25+ title : 'Choose active slides entry.' ,
26+ } ,
27+ )
28+ if ( entry === addNewEntry ) {
29+ if ( ! await addEntry ( ) ) {
30+ break
31+ }
32+ }
33+ else if ( entry ) {
34+ activeEntry . value = entry
35+ break
36+ }
37+ else {
38+ break
39+ }
40+ }
2541 } )
2642
27- useCommand ( 'slidev.add-entry' , async ( ) => {
43+ useCommand ( 'slidev.add-entry' , addEntry )
44+
45+ async function addEntry ( ) {
2846 const files = await findPossibleEntries ( )
2947 const selected = await window . showQuickPick ( files , {
3048 title : 'Choose Markdown files to add as slides entries.' ,
@@ -37,10 +55,11 @@ export function useCommands() {
3755 const workspaceRoot = workspace . workspaceFolders [ 0 ] . uri . fsPath
3856 const relatives = selected . map ( s => slash ( relative ( workspaceRoot , s ) ) )
3957 // write back to settings.json
40- include . update ( [ ...include . value , ...relatives ] )
58+ await include . update ( [ ...include . value , ...relatives ] )
4159 }
4260 }
43- } )
61+ return ! ! selected
62+ }
4463
4564 useCommand ( 'slidev.remove-entry' , async ( node : any ) => {
4665 const entry = slash ( node . treeItem . resourceUri . fsPath )
@@ -54,66 +73,35 @@ export function useCommands() {
5473 activeEntry . value = entry
5574 } )
5675
57- useCommand ( 'slidev.stop-dev' , async ( node : any ) => {
58- const entry = node ? slash ( node . treeItem . resourceUri . fsPath ) : activeEntry . value
59- if ( ! entry )
60- return
61- const project = projects . get ( entry )
62- const { stop } = useDevServer ( project ! )
63- stop ( )
76+ useCommand ( 'slidev.goto' , ( filepath : string , index : number ) => {
77+ const { gotoSlide } = useFocusedSlide ( )
78+ gotoSlide ( filepath , index )
6479 } )
65-
66- async function gotoSlide ( filepath : string , index : number , getNo ?: ( ) => number | null ) {
67- const { markdown : currrentMarkdown , index : currentIndex } = useEditingSlideSource ( )
68- const sameFile = currrentMarkdown . value ?. filepath === filepath
69- if ( sameFile && currentIndex . value === index )
70- return
71-
72- const slide = activeSlidevData . value ?. markdownFiles [ filepath ] ?. slides [ index ]
73- if ( ! slide )
74- return
75-
76- const uri = Uri . file ( filepath ) . with ( {
77- // Add a fragment to the URI will cause a flush. So we need to remove it if it's the same file.
78- fragment : sameFile ? undefined : `L${ slide . contentStart + 1 } ` ,
79- } )
80- const editor = await window . showTextDocument ( await workspace . openTextDocument ( uri ) )
81-
82- const cursorPos = new Position ( slide . contentStart , 0 )
83- editor . selection = new Selection ( cursorPos , cursorPos )
84-
85- const startPos = new Position ( slide . start , 0 )
86- const endPos = new Position ( slide . end , 0 )
87- const slideRange = new Range ( startPos , endPos )
88- editor . revealRange ( slideRange , TextEditorRevealType . AtTop )
89-
90- const no = getNo ?.( )
91- if ( no ) {
92- const focusedSlideNo = useFocusedSlideNo ( )
93- focusedSlideNo . value = no
94- }
95- }
96-
97- useCommand ( 'slidev.goto' , gotoSlide )
9880 useCommand ( 'slidev.next' , ( ) => {
99- const { markdown, index } = useEditingSlideSource ( )
100- const focusedSlideNo = useFocusedSlideNo ( )
101- gotoSlide ( markdown . value ! . filepath , index . value + 1 , ( ) => focusedSlideNo . value + 1 )
81+ const { focusedMarkdown, focusedSourceSlide, gotoSlide } = useFocusedSlide ( )
82+ if ( ! focusedMarkdown . value || focusedSourceSlide . value == null )
83+ return
84+ gotoSlide ( focusedMarkdown . value . filepath , focusedSourceSlide . value . index + 1 )
10285 } )
10386 useCommand ( 'slidev.prev' , ( ) => {
104- const { markdown, index } = useEditingSlideSource ( )
105- const focusedSlideNo = useFocusedSlideNo ( )
106- gotoSlide ( markdown . value ! . filepath , index . value - 1 , ( ) => focusedSlideNo . value - 1 )
87+ const { focusedMarkdown, focusedSourceSlide, gotoSlide } = useFocusedSlide ( )
88+ if ( ! focusedMarkdown . value || focusedSourceSlide . value == null )
89+ return
90+ gotoSlide ( focusedMarkdown . value . filepath , focusedSourceSlide . value . index - 1 )
10791 } )
10892
109- useCommand ( 'slidev.refresh-preview' , ( ) => {
93+ useCommand ( 'slidev.refresh-preview' , async ( ) => {
11094 const { refresh } = usePreviewWebview ( )
111- refresh ( )
95+ await refresh ( )
11296 } )
11397
11498 useCommand ( 'slidev.config-port' , async ( ) => {
99+ if ( ! activeProject . value ) {
100+ window . showErrorMessage ( 'No active project to configure port.' )
101+ return
102+ }
115103 const port = await window . showInputBox ( {
116- prompt : ' Slidev Preview Port' ,
104+ prompt : ` Slidev Preview Port for ${ getSlidesTitle ( activeProject . value . data ) } ` ,
117105 value : configuredPort . value . toString ( ) ,
118106 validateInput : ( v ) => {
119107 if ( ! v . match ( / ^ \d + $ / ) )
@@ -123,9 +111,9 @@ export function useCommands() {
123111 return null
124112 } ,
125113 } )
126- if ( ! port )
127- return
128- configuredPort . value = + port
114+ if ( port && activeProject . value ) {
115+ activeProject . value . port . value = + port
116+ }
129117 } )
130118
131119 useCommand ( 'slidev.start-dev' , async ( ) => {
@@ -138,12 +126,6 @@ export function useCommands() {
138126 const { start, showTerminal } = useDevServer ( project )
139127 start ( )
140128 showTerminal ( )
141-
142- const { retry } = usePreviewWebview ( )
143- setTimeout ( retry , 3000 )
144- setTimeout ( retry , 5000 )
145- setTimeout ( retry , 7000 )
146- setTimeout ( retry , 9000 )
147129 } )
148130
149131 useCommand ( 'slidev.open-in-browser' , ( ) => usePreviewWebview ( ) . openExternal ( ) )
@@ -153,6 +135,6 @@ export function useCommands() {
153135 useCommand ( 'slidev.preview-prev-slide' , ( ) => usePreviewWebview ( ) . prevSlide ( ) )
154136 useCommand ( 'slidev.preview-next-slide' , ( ) => usePreviewWebview ( ) . nextSlide ( ) )
155137
156- useCommand ( 'slidev.enable-preview-sync' , ( ) => ( previewSync . value = true ) )
157- useCommand ( 'slidev.disable-preview-sync' , ( ) => ( previewSync . value = false ) )
138+ useCommand ( 'slidev.enable-preview-sync' , ( ) => ( previewSync . update ( true , ConfigurationTarget . Global ) ) )
139+ useCommand ( 'slidev.disable-preview-sync' , ( ) => ( previewSync . update ( false , ConfigurationTarget . Global ) ) )
158140}
0 commit comments