@@ -51,10 +51,34 @@ export const CanvasProvider: React.FC<Props> = props => {
5151 addSnapshot
5252 ) ;
5353
54- const selectionInfo = useSelection ( document , setDocument ) ;
54+ const [ isDirty , setIsDirty ] = React . useState ( false ) ;
55+
56+ const setDocumentAndMarkDirtyState = (
57+ updater : DocumentModel | ( ( prev : DocumentModel ) => DocumentModel ) ,
58+ isDirty = true
59+ ) => {
60+ setDocument ( updater ) ;
61+ setIsDirty ( isDirty ) ;
62+ } ;
63+
64+ const selectionInfo = useSelection (
65+ document ,
66+ setDocument ,
67+ setDocumentAndMarkDirtyState
68+ ) ;
69+
70+ React . useEffect ( ( ) => {
71+ const handleBeforeUnload = ( e : BeforeUnloadEvent ) => {
72+ if ( isDirty ) {
73+ e . preventDefault ( ) ;
74+ }
75+ } ;
76+ window . addEventListener ( 'beforeunload' , handleBeforeUnload ) ;
77+ return ( ) => window . removeEventListener ( 'beforeunload' , handleBeforeUnload ) ;
78+ } , [ isDirty ] ) ;
5579
5680 const addNewPage = ( ) => {
57- setDocument ( lastDocument =>
81+ setDocumentAndMarkDirtyState ( lastDocument =>
5882 produce ( lastDocument , draft => {
5983 const newActiveIndex = draft . pages . length ;
6084 draft . pages . push ( {
@@ -76,7 +100,7 @@ export const CanvasProvider: React.FC<Props> = props => {
76100 }
77101 ) ;
78102
79- setDocument ( lastDocument =>
103+ setDocumentAndMarkDirtyState ( lastDocument =>
80104 produce ( lastDocument , draft => {
81105 const newPage = {
82106 id : uuidv4 ( ) ,
@@ -96,7 +120,7 @@ export const CanvasProvider: React.FC<Props> = props => {
96120 ? document . pages [ pageIndex + 1 ] . id // If it's not the last page, select the next one
97121 : document . pages [ pageIndex - 1 ] . id ; // Otherwise, select the previous one
98122
99- setDocument ( lastDocument =>
123+ setDocumentAndMarkDirtyState ( lastDocument =>
100124 produce ( lastDocument , draft => {
101125 draft . pages = draft . pages . filter (
102126 currentPage => document . pages [ pageIndex ] . id !== currentPage . id
@@ -119,7 +143,7 @@ export const CanvasProvider: React.FC<Props> = props => {
119143 selectionInfo . clearSelection ( ) ;
120144 selectionInfo . shapeRefs . current = { } ;
121145
122- setDocument ( lastDocument =>
146+ setDocumentAndMarkDirtyState ( lastDocument =>
123147 produce ( lastDocument , draft => {
124148 const pageIndex = draft . pages . findIndex ( page => page . id === pageId ) ;
125149 if ( pageIndex !== - 1 ) {
@@ -130,15 +154,15 @@ export const CanvasProvider: React.FC<Props> = props => {
130154 } ;
131155
132156 const editPageTitle = ( pageIndex : number , newName : string ) => {
133- setDocument ( lastDocument =>
157+ setDocumentAndMarkDirtyState ( lastDocument =>
134158 produce ( lastDocument , draft => {
135159 draft . pages [ pageIndex ] . name = newName ;
136160 } )
137161 ) ;
138162 } ;
139163
140164 const swapPages = ( id1 : string , id2 : string ) => {
141- setDocument ( lastDocument =>
165+ setDocumentAndMarkDirtyState ( lastDocument =>
142166 produce ( lastDocument , draft => {
143167 const index1 = draft . pages . findIndex ( page => page . id === id1 ) ;
144168 const index2 = draft . pages . findIndex ( page => page . id === id2 ) ;
@@ -159,7 +183,7 @@ export const CanvasProvider: React.FC<Props> = props => {
159183 } ) ;
160184
161185 if ( isPageIndexValid ( document ) ) {
162- setDocument ( lastDocument =>
186+ setDocumentAndMarkDirtyState ( lastDocument =>
163187 produce ( lastDocument , draft => {
164188 draft . pages [ lastDocument . activePageIndex ] . shapes . push ( ...newShapes ) ;
165189 } )
@@ -198,13 +222,13 @@ export const CanvasProvider: React.FC<Props> = props => {
198222 ) ;
199223
200224 const createNewFullDocument = ( ) => {
201- setDocument ( createDefaultDocumentModel ( ) ) ;
225+ setDocumentAndMarkDirtyState ( createDefaultDocumentModel ( ) , false ) ;
202226 setFileName ( '' ) ;
203227 } ;
204228
205229 const deleteSelectedShapes = ( ) => {
206230 if ( isPageIndexValid ( document ) ) {
207- setDocument ( lastDocument =>
231+ setDocumentAndMarkDirtyState ( lastDocument =>
208232 produce ( lastDocument , draft => {
209233 draft . pages [ lastDocument . activePageIndex ] . shapes =
210234 removeShapesFromList (
@@ -230,7 +254,7 @@ export const CanvasProvider: React.FC<Props> = props => {
230254
231255 const newShape = createShape ( { x, y } , type , otherProps ) ;
232256
233- setDocument ( lastDocument =>
257+ setDocumentAndMarkDirtyState ( lastDocument =>
234258 produce ( lastDocument , draft => {
235259 draft . pages [ lastDocument . activePageIndex ] . shapes . push ( newShape ) ;
236260 } )
@@ -260,7 +284,7 @@ export const CanvasProvider: React.FC<Props> = props => {
260284 } ) ;
261285 } ) ;
262286 } else {
263- setDocument ( fullDocument => {
287+ setDocumentAndMarkDirtyState ( fullDocument => {
264288 return produce ( fullDocument , draft => {
265289 draft . pages [ document . activePageIndex ] . shapes = draft . pages [
266290 document . activePageIndex
@@ -274,7 +298,7 @@ export const CanvasProvider: React.FC<Props> = props => {
274298
275299 const updateShapePosition = ( id : string , { x, y } : Coord ) => {
276300 if ( isPageIndexValid ( document ) ) {
277- setDocument ( fullDocument => {
301+ setDocumentAndMarkDirtyState ( fullDocument => {
278302 return produce ( fullDocument , draft => {
279303 draft . pages [ document . activePageIndex ] . shapes = draft . pages [
280304 document . activePageIndex
@@ -307,6 +331,7 @@ export const CanvasProvider: React.FC<Props> = props => {
307331 } ;
308332
309333 const loadDocument = ( document : DocumentModel ) => {
334+ setDocumentAndMarkDirtyState ( document , false ) ;
310335 loadSampleDocument && setLoadSampleDocument ( false ) ;
311336 setDocument ( document ) ;
312337 setHowManyLoadedDocuments ( numberOfDocuments => numberOfDocuments + 1 ) ;
@@ -373,6 +398,7 @@ export const CanvasProvider: React.FC<Props> = props => {
373398 updateColorSlot,
374399 dropRef,
375400 setDropRef,
401+ setIsDirty,
376402 loadSampleDocument,
377403 setLoadSampleDocument,
378404 } }
0 commit comments