11import * as React from 'react' ;
2+ import * as dateFns from 'date-fns' ;
23import { inject , observer } from 'mobx-react' ;
34
45import { css , styled } from '../../styles' ;
5- import { Ctrl } from '../../util/ui' ;
6+ import { Ctrl , saveFile } from '../../util/ui' ;
67import { CollectedEvent } from '../../types' ;
78import { AccountStore } from '../../model/account/account-store' ;
9+ import { generateHar } from '../../model/http/har' ;
810
911import { Icon } from '../../icons' ;
1012import { Button } from '../common/inputs' ;
13+ import { GetProOverlay } from '../account/pro-placeholders' ;
1114
1215import { getEventPreviewContent , getEventMarkerColor , isOpaqueConnection } from './event-rows/event-row' ;
1316
@@ -133,6 +136,29 @@ const PinIcon = styled(Icon).attrs({
133136 ` }
134137` ;
135138
139+ const ProDivider = styled . hr `
140+ width: 100%;
141+ margin: 36px 0;
142+ border: none;
143+ border: solid 1px ${ p => p . theme . mainColor } ;
144+ ` ;
145+
146+ const ProActionsContainer = styled . div `
147+ display: flex;
148+ flex-direction: column;
149+ align-items: stretch;
150+ gap: 10px;
151+ width: 100%;
152+ ` ;
153+
154+ const ProActionsOverlay = styled ( GetProOverlay ) `
155+ min-height: 0;
156+
157+ > button {
158+ top: 50%;
159+ }
160+ ` ;
161+
136162const PREVIEW_COUNT = 10 ;
137163
138164export const MultiSelectionSummaryPane = inject ( 'accountStore' ) ( observer ( ( props : {
@@ -144,6 +170,11 @@ export const MultiSelectionSummaryPane = inject('accountStore')(observer((props:
144170} ) => {
145171 const { selectedEvents } = props ;
146172 const count = selectedEvents . length ;
173+ const isPaidUser = props . accountStore ! . user . isPaidUser ( ) ;
174+
175+ const httpCount = selectedEvents . filter ( e =>
176+ e . isHttp ( ) && ! e . isWebSocket ( )
177+ ) . length ;
147178
148179 const allHttp = count > 0 && selectedEvents . every ( e => e . isHttp ( ) ) ;
149180 const allPinned = selectedEvents . every ( e => e . pinned ) ;
@@ -153,6 +184,36 @@ export const MultiSelectionSummaryPane = inject('accountStore')(observer((props:
153184 // Reverse so the most recent is the front card (index 0).
154185 const previewEvents = selectedEvents . slice ( - PREVIEW_COUNT ) . reverse ( ) ;
155186
187+ const proButtons = < >
188+ < ActionButton
189+ title = { isPaidUser ? `(${ Ctrl } +M)` : 'Requires HTTP Toolkit Pro' }
190+ disabled = { ! isPaidUser || httpCount === 0 }
191+ onClick = { props . onBuildRule }
192+ >
193+ < Icon icon = 'Pencil' fixedWidth />
194+ Create { httpCount } Matching Rule{ httpCount !== 1 ? 's' : '' }
195+ </ ActionButton >
196+ < ActionButton
197+ title = { isPaidUser
198+ ? 'Export selected exchanges as a HAR file'
199+ : 'With Pro: export as HAR'
200+ }
201+ disabled = { ! isPaidUser || count === 0 }
202+ onClick = { async ( ) => {
203+ const harContent = JSON . stringify (
204+ await generateHar ( selectedEvents )
205+ ) ;
206+ const filename = `HTTPToolkit_${
207+ dateFns . format ( Date . now ( ) , 'YYYY-MM-DD_HH-mm' )
208+ } .har`;
209+ saveFile ( filename , 'application/har+json;charset=utf-8' , harContent ) ;
210+ } }
211+ >
212+ < Icon icon = { [ 'fas' , 'save' ] } fixedWidth />
213+ Export as HAR
214+ </ ActionButton >
215+ </ > ;
216+
156217 return < SummaryContainer >
157218 < PreviewStack >
158219 { previewEvents . map ( ( event , index ) => {
@@ -185,6 +246,21 @@ export const MultiSelectionSummaryPane = inject('accountStore')(observer((props:
185246 < Icon icon = { [ 'far' , 'trash-alt' ] } fixedWidth />
186247 Delete { count } { label } { count !== 1 ? 's' : '' }
187248 </ ActionButton >
249+
250+ { isPaidUser
251+ ? proButtons
252+ : < >
253+ < ProDivider />
254+ < ProActionsOverlay
255+ getPro = { props . accountStore ! . getPro }
256+ source = 'multi-selection-pane'
257+ >
258+ < ProActionsContainer >
259+ { proButtons }
260+ </ ProActionsContainer >
261+ </ ProActionsOverlay >
262+ </ >
263+ }
188264 </ ActionsContainer >
189265 </ SummaryContainer > ;
190266} ) ) ;
0 commit comments