1
1
import { subscribe , type AsyncSubscription } from '@parcel/watcher' ;
2
- import { DefaultSettings } from '@onlook/models/constants' ;
2
+ import { DefaultSettings , MainChannels } from '@onlook/models/constants' ;
3
3
import * as pathModule from 'path' ;
4
4
import { scanFonts } from './scanner' ;
5
5
import fs from 'fs' ;
@@ -8,16 +8,20 @@ import { removeFontVariableFromLayout } from './layout';
8
8
import { removeFontFromTailwindConfig , updateTailwindFontConfig } from './tailwind' ;
9
9
import type { Font } from '@onlook/models/assets' ;
10
10
import { detectRouterType } from '../../pages' ;
11
+ import { mainWindow } from '../../index' ;
11
12
12
13
export class FontFileWatcher {
13
14
private subscription : AsyncSubscription | null = null ;
14
15
private previousFonts : Font [ ] = [ ] ;
16
+ private selfModified : Set < string > = new Set ( ) ;
15
17
16
18
async watch ( projectRoot : string ) {
17
19
await this . clearSubscription ( ) ;
18
20
19
- const fontPath = pathModule . resolve ( projectRoot , DefaultSettings . FONT_CONFIG ) ;
20
- const fontDir = pathModule . dirname ( fontPath ) ;
21
+ const _fontPath = pathModule . resolve ( projectRoot , DefaultSettings . FONT_CONFIG ) ;
22
+ const fontDir = pathModule . dirname ( _fontPath ) ;
23
+ let _layoutPath : string = '' ;
24
+ let _appPath : string = '' ;
21
25
22
26
if ( ! fs . existsSync ( fontDir ) ) {
23
27
console . error ( `Font directory does not exist: ${ fontDir } ` ) ;
@@ -30,6 +34,15 @@ export class FontFileWatcher {
30
34
this . previousFonts = [ ] ;
31
35
}
32
36
37
+ const routerConfig = await detectRouterType ( projectRoot ) ;
38
+ if ( routerConfig ) {
39
+ if ( routerConfig . type === 'app' ) {
40
+ _layoutPath = pathModule . join ( routerConfig . basePath , 'layout.tsx' ) ;
41
+ } else {
42
+ _appPath = pathModule . join ( routerConfig . basePath , '_app.tsx' ) ;
43
+ }
44
+ }
45
+
33
46
try {
34
47
this . subscription = await subscribe (
35
48
fontDir ,
@@ -42,10 +55,16 @@ export class FontFileWatcher {
42
55
if ( events . length > 0 ) {
43
56
for ( const event of events ) {
44
57
const eventPath = pathModule . normalize ( event . path ) ;
45
- const expectedPath = pathModule . normalize ( fontPath ) ;
58
+ const fontPath = pathModule . normalize ( _fontPath ) ;
59
+ const layoutPath = pathModule . normalize ( _layoutPath ) ;
60
+ const appPath = pathModule . normalize ( _appPath ) ;
61
+ if ( this . selfModified . has ( eventPath ) ) {
62
+ this . selfModified . delete ( eventPath ) ;
63
+ continue ;
64
+ }
46
65
47
66
if (
48
- ( eventPath === expectedPath ||
67
+ ( eventPath === fontPath ||
49
68
eventPath . endsWith ( DefaultSettings . FONT_CONFIG ) ) &&
50
69
( event . type === 'update' || event . type === 'create' )
51
70
) {
@@ -55,6 +74,17 @@ export class FontFileWatcher {
55
74
console . error ( 'Error syncing fonts with configs:' , error ) ;
56
75
}
57
76
}
77
+ if (
78
+ ( eventPath === layoutPath || eventPath === appPath ) &&
79
+ ( event . type === 'update' || event . type === 'create' )
80
+ ) {
81
+ this . selfModified . add ( eventPath ) ;
82
+ try {
83
+ mainWindow ?. webContents . send ( MainChannels . GET_DEFAULT_FONT ) ;
84
+ } catch ( error ) {
85
+ console . error ( 'Error syncing fonts with configs:' , error ) ;
86
+ }
87
+ }
58
88
}
59
89
}
60
90
} ,
@@ -78,17 +108,19 @@ export class FontFileWatcher {
78
108
) ;
79
109
80
110
const addedFonts = currentFonts . filter (
81
- ( currFont ) => ! this . previousFonts . some ( ( prevFont ) => prevFont . id === currFont . id ) ,
111
+ ( currFont ) => ! this . previousFonts . some ( ( prevFont ) => currFont . id === prevFont . id ) ,
82
112
) ;
83
113
84
114
for ( const font of removedFonts ) {
85
115
const routerConfig = await detectRouterType ( projectRoot ) ;
86
116
if ( routerConfig ) {
87
117
if ( routerConfig . type === 'app' ) {
88
118
const layoutPath = pathModule . join ( routerConfig . basePath , 'layout.tsx' ) ;
119
+ this . selfModified . add ( layoutPath ) ;
89
120
await removeFontVariableFromLayout ( layoutPath , font . id , [ 'html' ] ) ;
90
121
} else {
91
122
const appPath = pathModule . join ( routerConfig . basePath , '_app.tsx' ) ;
123
+ this . selfModified . add ( appPath ) ;
92
124
await removeFontVariableFromLayout ( appPath , font . id , [
93
125
'div' ,
94
126
'main' ,
@@ -98,16 +130,40 @@ export class FontFileWatcher {
98
130
}
99
131
}
100
132
133
+ const tailwindConfigPath = pathModule . join ( projectRoot , 'tailwind.config.ts' ) ;
134
+ this . selfModified . add ( tailwindConfigPath ) ;
101
135
await removeFontFromTailwindConfig ( projectRoot , font ) ;
102
136
}
103
137
104
138
if ( addedFonts . length > 0 ) {
105
139
for ( const font of addedFonts ) {
140
+ const tailwindConfigPath = pathModule . join ( projectRoot , 'tailwind.config.ts' ) ;
141
+ this . selfModified . add ( tailwindConfigPath ) ;
106
142
await updateTailwindFontConfig ( projectRoot , font ) ;
107
- await addFontVariableToLayout ( projectRoot , font . id ) ;
143
+
144
+ const routerConfig = await detectRouterType ( projectRoot ) ;
145
+ if ( routerConfig ) {
146
+ if ( routerConfig . type === 'app' ) {
147
+ const layoutPath = pathModule . join ( routerConfig . basePath , 'layout.tsx' ) ;
148
+ this . selfModified . add ( layoutPath ) ;
149
+ await addFontVariableToLayout ( projectRoot , font . id ) ;
150
+ } else {
151
+ const appPath = pathModule . join ( routerConfig . basePath , '_app.tsx' ) ;
152
+ this . selfModified . add ( appPath ) ;
153
+ await addFontVariableToLayout ( projectRoot , font . id ) ;
154
+ }
155
+ }
108
156
}
109
157
}
110
158
159
+ if ( removedFonts . length > 0 || addedFonts . length > 0 ) {
160
+ mainWindow ?. webContents . send ( MainChannels . FONTS_CHANGED , {
161
+ currentFonts,
162
+ removedFonts,
163
+ addedFonts,
164
+ } ) ;
165
+ }
166
+
111
167
this . previousFonts = currentFonts ;
112
168
} catch ( error ) {
113
169
console . error ( 'Error syncing fonts:' , error ) ;
0 commit comments