@@ -11,7 +11,6 @@ import {
11
11
ErrorNotificationProvider ,
12
12
InAppNotificationAction ,
13
13
InAppNotificationProvider ,
14
- InAppNotificationTroubleshootInfo ,
15
14
InconsistentVersionNotificationProvider ,
16
15
ReconnectingNotificationProvider ,
17
16
UnsupportedVersionNotificationProvider ,
@@ -43,7 +42,7 @@ interface IProps {
43
42
}
44
43
45
44
export default function NotificationArea ( props : IProps ) {
46
- const { showFullDiskAccessSettings } = useAppContext ( ) ;
45
+ const { showFullDiskAccessSettings, reconnectTunnel } = useAppContext ( ) ;
47
46
48
47
const account = useSelector ( ( state : IReduxState ) => state . account ) ;
49
48
const locale = useSelector ( ( state : IReduxState ) => state . userInterface . locale ) ;
@@ -59,6 +58,15 @@ export default function NotificationArea(props: IProps) {
59
58
60
59
const { hideNewDeviceBanner } = useActions ( accountActions ) ;
61
60
61
+ const [ isModalOpen , setIsModalOpen ] = useState ( false ) ;
62
+
63
+ const { setSplitTunnelingState } = useAppContext ( ) ;
64
+ const disableSplitTunneling = useCallback ( async ( ) => {
65
+ setIsModalOpen ( false ) ;
66
+ await setSplitTunnelingState ( false ) ;
67
+ await reconnectTunnel ( ) ;
68
+ } , [ reconnectTunnel , setSplitTunnelingState ] ) ;
69
+
62
70
const notificationProviders : InAppNotificationProvider [ ] = [
63
71
new ConnectingNotificationProvider ( { tunnelState } ) ,
64
72
new ReconnectingNotificationProvider ( tunnelState ) ,
@@ -67,7 +75,13 @@ export default function NotificationArea(props: IProps) {
67
75
blockWhenDisconnected,
68
76
hasExcludedApps,
69
77
} ) ,
70
- new ErrorNotificationProvider ( { tunnelState, hasExcludedApps, showFullDiskAccessSettings } ) ,
78
+
79
+ new ErrorNotificationProvider ( {
80
+ tunnelState,
81
+ hasExcludedApps,
82
+ showFullDiskAccessSettings,
83
+ disableSplitTunneling,
84
+ } ) ,
71
85
new InconsistentVersionNotificationProvider ( { consistent : version . consistent } ) ,
72
86
new UnsupportedVersionNotificationProvider ( version ) ,
73
87
] ;
@@ -109,7 +123,13 @@ export default function NotificationArea(props: IProps) {
109
123
{ formatHtml ( notification . subtitle ?? '' ) }
110
124
</ NotificationSubtitle >
111
125
</ NotificationContent >
112
- { notification . action && < NotificationActionWrapper action = { notification . action } /> }
126
+ { notification . action && (
127
+ < NotificationActionWrapper
128
+ action = { notification . action }
129
+ isModalOpen = { isModalOpen }
130
+ setIsModalOpen = { setIsModalOpen }
131
+ />
132
+ ) }
113
133
</ NotificationBanner >
114
134
) ;
115
135
} else {
@@ -122,46 +142,51 @@ export default function NotificationArea(props: IProps) {
122
142
return < NotificationBanner className = { props . className } aria-hidden = { true } /> ;
123
143
}
124
144
125
- interface INotificationActionWrapperProps {
145
+ interface NotificationActionWrapperProps {
126
146
action : InAppNotificationAction ;
147
+ isModalOpen : boolean ;
148
+ setIsModalOpen : ( isOpen : boolean ) => void ;
127
149
}
128
150
129
- function NotificationActionWrapper ( props : INotificationActionWrapperProps ) {
151
+ function NotificationActionWrapper ( {
152
+ action,
153
+ isModalOpen,
154
+ setIsModalOpen,
155
+ } : NotificationActionWrapperProps ) {
130
156
const { push } = useHistory ( ) ;
131
157
const { openLinkWithAuth, openUrl } = useAppContext ( ) ;
132
- const [ troubleshootInfo , setTroubleshootInfo ] = useState < InAppNotificationTroubleshootInfo > ( ) ;
158
+
159
+ const closeTroubleshootModal = useCallback ( ( ) => setIsModalOpen ( false ) , [ setIsModalOpen ] ) ;
133
160
134
161
const handleClick = useCallback ( ( ) => {
135
- if ( props . action ) {
136
- switch ( props . action . type ) {
162
+ if ( action ) {
163
+ switch ( action . type ) {
137
164
case 'open-url' :
138
- if ( props . action . withAuth ) {
139
- return openLinkWithAuth ( props . action . url ) ;
165
+ if ( action . withAuth ) {
166
+ return openLinkWithAuth ( action . url ) ;
140
167
} else {
141
- return openUrl ( props . action . url ) ;
168
+ return openUrl ( action . url ) ;
142
169
}
143
170
case 'troubleshoot-dialog' :
144
- setTroubleshootInfo ( props . action . troubleshoot ) ;
171
+ setIsModalOpen ( true ) ;
145
172
break ;
146
173
case 'close' :
147
- props . action . close ( ) ;
174
+ action . close ( ) ;
148
175
break ;
149
176
}
150
177
}
151
178
152
179
return Promise . resolve ( ) ;
153
- } , [ openLinkWithAuth , openUrl , props . action ] ) ;
180
+ } , [ action , setIsModalOpen , openLinkWithAuth , openUrl ] ) ;
154
181
155
182
const goToProblemReport = useCallback ( ( ) => {
156
- setTroubleshootInfo ( undefined ) ;
183
+ closeTroubleshootModal ( ) ;
157
184
push ( RoutePath . problemReport , { transition : transitions . show } ) ;
158
- } , [ push ] ) ;
159
-
160
- const closeTroubleshootInfo = useCallback ( ( ) => setTroubleshootInfo ( undefined ) , [ ] ) ;
185
+ } , [ closeTroubleshootModal , push ] ) ;
161
186
162
187
let actionComponent : React . ReactElement | undefined ;
163
- if ( props . action ) {
164
- switch ( props . action . type ) {
188
+ if ( action ) {
189
+ switch ( action . type ) {
165
190
case 'open-url' :
166
191
actionComponent = < NotificationOpenLinkAction onClick = { handleClick } /> ;
167
192
break ;
@@ -177,7 +202,11 @@ function NotificationActionWrapper(props: INotificationActionWrapperProps) {
177
202
}
178
203
}
179
204
180
- const problemReportButton = troubleshootInfo ?. buttons ? (
205
+ if ( action . type !== 'troubleshoot-dialog' ) {
206
+ return < NotificationActions > { actionComponent } </ NotificationActions > ;
207
+ }
208
+
209
+ const problemReportButton = action . troubleshoot ?. buttons ? (
181
210
< AppButton . BlueButton key = "problem-report" onClick = { goToProblemReport } >
182
211
{ messages . pgettext ( 'in-app-notifications' , 'Send problem report' ) }
183
212
</ AppButton . BlueButton >
@@ -189,17 +218,32 @@ function NotificationActionWrapper(props: INotificationActionWrapperProps) {
189
218
190
219
let buttons = [
191
220
problemReportButton ,
192
- < AppButton . BlueButton key = "back" onClick = { closeTroubleshootInfo } >
221
+ < AppButton . BlueButton key = "back" onClick = { closeTroubleshootModal } >
193
222
{ messages . gettext ( 'Back' ) }
194
223
</ AppButton . BlueButton > ,
195
224
] ;
196
225
197
- if ( troubleshootInfo ?. buttons ) {
198
- const actionButtons = troubleshootInfo . buttons . map ( ( button ) => (
199
- < AppButton . GreenButton key = { button . label } onClick = { button . action } >
200
- { button . label }
201
- </ AppButton . GreenButton >
202
- ) ) ;
226
+ if ( action . troubleshoot ?. buttons ) {
227
+ const actionButtons = action . troubleshoot . buttons . map ( ( { variant, label, action } ) => {
228
+ if ( variant === 'success' )
229
+ return (
230
+ < AppButton . GreenButton key = { label } onClick = { action } >
231
+ { label }
232
+ </ AppButton . GreenButton >
233
+ ) ;
234
+ else if ( variant === 'destructive' )
235
+ return (
236
+ < AppButton . RedButton key = { label } onClick = { action } >
237
+ { label }
238
+ </ AppButton . RedButton >
239
+ ) ;
240
+ else
241
+ return (
242
+ < AppButton . BlueButton key = { label } onClick = { action } >
243
+ { label }
244
+ </ AppButton . BlueButton >
245
+ ) ;
246
+ } ) ;
203
247
204
248
buttons = actionButtons . concat ( buttons ) ;
205
249
}
@@ -208,14 +252,14 @@ function NotificationActionWrapper(props: INotificationActionWrapperProps) {
208
252
< >
209
253
< NotificationActions > { actionComponent } </ NotificationActions >
210
254
< ModalAlert
211
- isOpen = { troubleshootInfo !== undefined }
255
+ isOpen = { isModalOpen }
212
256
type = { ModalAlertType . info }
213
257
buttons = { buttons }
214
- close = { closeTroubleshootInfo } >
215
- < ModalMessage > { troubleshootInfo ?. details } </ ModalMessage >
258
+ close = { closeTroubleshootModal } >
259
+ < ModalMessage > { action . troubleshoot ?. details } </ ModalMessage >
216
260
< ModalMessage >
217
261
< ModalMessageList >
218
- { troubleshootInfo ?. steps . map ( ( step ) => < li key = { step } > { step } </ li > ) }
262
+ { action . troubleshoot ?. steps . map ( ( step ) => < li key = { step } > { step } </ li > ) }
219
263
</ ModalMessageList >
220
264
</ ModalMessage >
221
265
< ModalMessage >
0 commit comments