@@ -48,10 +48,34 @@ export const CanvasProvider: React.FC<Props> = props => {
4848 addSnapshot
4949 ) ;
5050
51- const selectionInfo = useSelection ( document , setDocument ) ;
51+ const [ isDirty , setIsDirty ] = React . useState ( false ) ;
52+
53+ const setDocumentAndMarkDirtyState = (
54+ updater : DocumentModel | ( ( prev : DocumentModel ) => DocumentModel ) ,
55+ isDirty = true
56+ ) => {
57+ setDocument ( updater ) ;
58+ setIsDirty ( isDirty ) ;
59+ } ;
60+
61+ const selectionInfo = useSelection (
62+ document ,
63+ setDocument ,
64+ setDocumentAndMarkDirtyState
65+ ) ;
66+
67+ React . useEffect ( ( ) => {
68+ const handleBeforeUnload = ( e : BeforeUnloadEvent ) => {
69+ if ( isDirty ) {
70+ e . preventDefault ( ) ;
71+ }
72+ } ;
73+ window . addEventListener ( 'beforeunload' , handleBeforeUnload ) ;
74+ return ( ) => window . removeEventListener ( 'beforeunload' , handleBeforeUnload ) ;
75+ } , [ isDirty ] ) ;
5276
5377 const addNewPage = ( ) => {
54- setDocument ( lastDocument =>
78+ setDocumentAndMarkDirtyState ( lastDocument =>
5579 produce ( lastDocument , draft => {
5680 const newActiveIndex = draft . pages . length ;
5781 draft . pages . push ( {
@@ -73,7 +97,7 @@ export const CanvasProvider: React.FC<Props> = props => {
7397 }
7498 ) ;
7599
76- setDocument ( lastDocument =>
100+ setDocumentAndMarkDirtyState ( lastDocument =>
77101 produce ( lastDocument , draft => {
78102 const newPage = {
79103 id : uuidv4 ( ) ,
@@ -93,7 +117,7 @@ export const CanvasProvider: React.FC<Props> = props => {
93117 ? document . pages [ pageIndex + 1 ] . id // If it's not the last page, select the next one
94118 : document . pages [ pageIndex - 1 ] . id ; // Otherwise, select the previous one
95119
96- setDocument ( lastDocument =>
120+ setDocumentAndMarkDirtyState ( lastDocument =>
97121 produce ( lastDocument , draft => {
98122 draft . pages = draft . pages . filter (
99123 currentPage => document . pages [ pageIndex ] . id !== currentPage . id
@@ -116,7 +140,7 @@ export const CanvasProvider: React.FC<Props> = props => {
116140 selectionInfo . clearSelection ( ) ;
117141 selectionInfo . shapeRefs . current = { } ;
118142
119- setDocument ( lastDocument =>
143+ setDocumentAndMarkDirtyState ( lastDocument =>
120144 produce ( lastDocument , draft => {
121145 const pageIndex = draft . pages . findIndex ( page => page . id === pageId ) ;
122146 if ( pageIndex !== - 1 ) {
@@ -127,15 +151,15 @@ export const CanvasProvider: React.FC<Props> = props => {
127151 } ;
128152
129153 const editPageTitle = ( pageIndex : number , newName : string ) => {
130- setDocument ( lastDocument =>
154+ setDocumentAndMarkDirtyState ( lastDocument =>
131155 produce ( lastDocument , draft => {
132156 draft . pages [ pageIndex ] . name = newName ;
133157 } )
134158 ) ;
135159 } ;
136160
137161 const swapPages = ( id1 : string , id2 : string ) => {
138- setDocument ( lastDocument =>
162+ setDocumentAndMarkDirtyState ( lastDocument =>
139163 produce ( lastDocument , draft => {
140164 const index1 = draft . pages . findIndex ( page => page . id === id1 ) ;
141165 const index2 = draft . pages . findIndex ( page => page . id === id2 ) ;
@@ -156,7 +180,7 @@ export const CanvasProvider: React.FC<Props> = props => {
156180 } ) ;
157181
158182 if ( isPageIndexValid ( document ) ) {
159- setDocument ( lastDocument =>
183+ setDocumentAndMarkDirtyState ( lastDocument =>
160184 produce ( lastDocument , draft => {
161185 draft . pages [ lastDocument . activePageIndex ] . shapes . push ( ...newShapes ) ;
162186 } )
@@ -197,12 +221,13 @@ export const CanvasProvider: React.FC<Props> = props => {
197221 const createNewFullDocument = ( ) => {
198222 setDocument ( createDefaultDocumentModel ( ) ) ;
199223 setCanvasSize ( createDefaultCanvasSize ( ) ) ;
224+ setDocumentAndMarkDirtyState ( createDefaultDocumentModel ( ) , false ) ;
200225 setFileName ( '' ) ;
201226 } ;
202227
203228 const deleteSelectedShapes = ( ) => {
204229 if ( isPageIndexValid ( document ) ) {
205- setDocument ( lastDocument =>
230+ setDocumentAndMarkDirtyState ( lastDocument =>
206231 produce ( lastDocument , draft => {
207232 draft . pages [ lastDocument . activePageIndex ] . shapes =
208233 removeShapesFromList (
@@ -228,7 +253,7 @@ export const CanvasProvider: React.FC<Props> = props => {
228253
229254 const newShape = createShape ( { x, y } , type , otherProps ) ;
230255
231- setDocument ( lastDocument =>
256+ setDocumentAndMarkDirtyState ( lastDocument =>
232257 produce ( lastDocument , draft => {
233258 draft . pages [ lastDocument . activePageIndex ] . shapes . push ( newShape ) ;
234259 } )
@@ -258,7 +283,7 @@ export const CanvasProvider: React.FC<Props> = props => {
258283 } ) ;
259284 } ) ;
260285 } else {
261- setDocument ( fullDocument => {
286+ setDocumentAndMarkDirtyState ( fullDocument => {
262287 return produce ( fullDocument , draft => {
263288 draft . pages [ document . activePageIndex ] . shapes = draft . pages [
264289 document . activePageIndex
@@ -272,7 +297,7 @@ export const CanvasProvider: React.FC<Props> = props => {
272297
273298 const updateShapePosition = ( id : string , { x, y } : Coord ) => {
274299 if ( isPageIndexValid ( document ) ) {
275- setDocument ( fullDocument => {
300+ setDocumentAndMarkDirtyState ( fullDocument => {
276301 return produce ( fullDocument , draft => {
277302 draft . pages [ document . activePageIndex ] . shapes = draft . pages [
278303 document . activePageIndex
@@ -305,6 +330,7 @@ export const CanvasProvider: React.FC<Props> = props => {
305330 } ;
306331
307332 const loadDocument = ( document : DocumentModel ) => {
333+ setDocumentAndMarkDirtyState ( document , false ) ;
308334 loadSampleDocument && setLoadSampleDocument ( false ) ;
309335 setDocument ( document ) ;
310336 setHowManyLoadedDocuments ( numberOfDocuments => numberOfDocuments + 1 ) ;
@@ -373,6 +399,7 @@ export const CanvasProvider: React.FC<Props> = props => {
373399 updateColorSlot,
374400 dropRef,
375401 setDropRef,
402+ setIsDirty,
376403 loadSampleDocument,
377404 setLoadSampleDocument,
378405 } }
0 commit comments