Filter Images by surfaces

Summary:
Adds a capability to filter images by surfaces.

Note: I will allow multi select in the next diff, stacked on the current one.

Reviewed By: passy

Differential Revision: D14158223

fbshipit-source-id: d96d73b94a8a442f3b60f656bc573b328c5500ad
This commit is contained in:
Pritesh Nandgaonkar
2019-02-21 09:40:32 -08:00
committed by Facebook Github Bot
parent 520ffec7c9
commit 863088e7cf
3 changed files with 84 additions and 1 deletions

View File

@@ -18,6 +18,7 @@ import {
FlexColumn, FlexColumn,
LoadingIndicator, LoadingIndicator,
styled, styled,
Select,
} from 'flipper'; } from 'flipper';
import type {ImagesMap} from './ImagePool.js'; import type {ImagesMap} from './ImagePool.js';
import {clipboard} from 'electron'; import {clipboard} from 'electron';
@@ -32,6 +33,9 @@ function formatKB(bytes: number) {
} }
type ImagesCacheOverviewProps = { type ImagesCacheOverviewProps = {
surfaceOptions: {[key: string]: string},
selectedSurface: string,
onChangeSurface: (key: string) => void,
images: ImagesList, images: ImagesList,
onClear: (type: string) => void, onClear: (type: string) => void,
onTrimMemory: () => void, onTrimMemory: () => void,
@@ -50,6 +54,12 @@ type ImagesCacheOverviewState = {|
size: number, size: number,
|}; |};
const StyledSelect = styled(Select)(props => ({
marginLeft: 6,
marginRight: 6,
height: '100%',
}));
export default class ImagesCacheOverview extends PureComponent< export default class ImagesCacheOverview extends PureComponent<
ImagesCacheOverviewProps, ImagesCacheOverviewProps,
ImagesCacheOverviewState, ImagesCacheOverviewState,
@@ -133,6 +143,11 @@ export default class ImagesCacheOverview extends PureComponent<
<Button onClick={this.onEnableAutoRefreshToggled}> <Button onClick={this.onEnableAutoRefreshToggled}>
Auto Refresh {this.props.isAutoRefreshEnabled ? 'ON' : 'OFF'} Auto Refresh {this.props.isAutoRefreshEnabled ? 'ON' : 'OFF'}
</Button> </Button>
<StyledSelect
options={this.props.surfaceOptions}
selected={this.props.selectedSurface}
onChange={this.props.onChangeSurface}
/>
<Spacer /> <Spacer />
<input <input
type="range" type="range"

View File

@@ -37,6 +37,7 @@ export type ImageData = {|
height: number, height: number,
sizeBytes: number, sizeBytes: number,
data: ImageBytes, data: ImageBytes,
surface?: string,
|}; |};
// getImage({imageId: string}) -> ImageData // getImage({imageId: string}) -> ImageData

View File

@@ -12,6 +12,7 @@ import type {
ImagesListResponse, ImagesListResponse,
ImageEvent, ImageEvent,
FrescoDebugOverlayEvent, FrescoDebugOverlayEvent,
CacheInfo,
} from './api.js'; } from './api.js';
import type {ImagesMap} from './ImagePool.js'; import type {ImagesMap} from './ImagePool.js';
@@ -31,15 +32,18 @@ import ImagePool from './ImagePool.js';
export type ImageEventWithId = ImageEvent & {eventId: number}; export type ImageEventWithId = ImageEvent & {eventId: number};
type PersistedState = { type PersistedState = {
surfaceList: Set<string>,
images: ImagesList, images: ImagesList,
events: Array<ImageEventWithId>, events: Array<ImageEventWithId>,
imagesMap: ImagesMap, imagesMap: ImagesMap,
}; };
type PluginState = { type PluginState = {
selectedSurface: string,
selectedImage: ?ImageId, selectedImage: ?ImageId,
isDebugOverlayEnabled: boolean, isDebugOverlayEnabled: boolean,
isAutoRefreshEnabled: boolean, isAutoRefreshEnabled: boolean,
images: ImagesList,
}; };
const EmptySidebar = styled(FlexRow)({ const EmptySidebar = styled(FlexRow)({
@@ -51,12 +55,14 @@ const EmptySidebar = styled(FlexRow)({
}); });
const DEBUG = false; const DEBUG = false;
const surfaceDefaultText = 'SELECT ALL SURFACES';
export default class extends FlipperPlugin<PluginState, *, PersistedState> { export default class extends FlipperPlugin<PluginState, *, PersistedState> {
static defaultPersistedState: PersistedState = { static defaultPersistedState: PersistedState = {
images: [], images: [],
events: [], events: [],
imagesMap: {}, imagesMap: {},
surfaceList: new Set(),
}; };
state: PluginState; state: PluginState;
@@ -64,9 +70,11 @@ export default class extends FlipperPlugin<PluginState, *, PersistedState> {
nextEventId: number = 1; nextEventId: number = 1;
state = { state = {
selectedSurface: surfaceDefaultText,
selectedImage: null, selectedImage: null,
isDebugOverlayEnabled: false, isDebugOverlayEnabled: false,
isAutoRefreshEnabled: false, isAutoRefreshEnabled: false,
images: [],
}; };
init() { init() {
@@ -76,6 +84,14 @@ export default class extends FlipperPlugin<PluginState, *, PersistedState> {
} }
this.updateCaches('init'); this.updateCaches('init');
this.client.subscribe('events', (event: ImageEvent) => { this.client.subscribe('events', (event: ImageEvent) => {
const {surfaceList} = this.props.persistedState;
const {attribution} = event;
if (attribution instanceof Array && attribution.length > 0) {
const surface = attribution[0].trim();
if (surface.length > 0) {
surfaceList.add(surface);
}
}
this.props.setPersistedState({ this.props.setPersistedState({
events: [ events: [
{eventId: this.nextEventId, ...event}, {eventId: this.nextEventId, ...event},
@@ -100,6 +116,40 @@ export default class extends FlipperPlugin<PluginState, *, PersistedState> {
this.imagePool.clear(); this.imagePool.clear();
} }
filterImages = (
images: ImagesList,
events: Array<ImageEventWithId>,
surface: string,
): ImagesList => {
if (!surface || surface === surfaceDefaultText) {
return images;
}
const imageList = images.map((image: CacheInfo) => {
const imageIdList = image.imageIds.filter(imageID => {
const filteredEvents = events.filter((event: ImageEventWithId) => {
return (
event.attribution &&
event.attribution.length > 0 &&
event.attribution[0] == surface &&
event.imageIds &&
event.imageIds.includes(imageID)
);
});
return filteredEvents.length > 0;
});
return {...image, imageIds: imageIdList};
});
return imageList;
};
updateImagesOnUI = (images: ImagesList, surface: string) => {
const filteredImages = this.filterImages(
images,
this.props.persistedState.events,
surface,
);
this.setState({selectedSurface: surface, images: filteredImages});
};
updateCaches = (reason: string) => { updateCaches = (reason: string) => {
if (DEBUG) { if (DEBUG) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
@@ -110,6 +160,10 @@ export default class extends FlipperPlugin<PluginState, *, PersistedState> {
this.imagePool.fetchImages(data.imageIds), this.imagePool.fetchImages(data.imageIds),
); );
this.props.setPersistedState({images: response.levels}); this.props.setPersistedState({images: response.levels});
this.updateImagesOnUI(
this.props.persistedState.images,
this.state.selectedSurface,
);
}); });
}; };
@@ -178,11 +232,24 @@ export default class extends FlipperPlugin<PluginState, *, PersistedState> {
return <ImagesSidebar image={maybeImage} events={events} />; return <ImagesSidebar image={maybeImage} events={events} />;
}; };
onSurfaceChange = (surface: string) => {
this.updateImagesOnUI(this.props.persistedState.images, surface);
};
render() { render() {
const options = [...this.props.persistedState.surfaceList].reduce(
(acc, item) => {
return {...acc, [item]: item};
},
{[surfaceDefaultText]: surfaceDefaultText},
);
return ( return (
<React.Fragment> <React.Fragment>
<ImagesCacheOverview <ImagesCacheOverview
images={this.props.persistedState.images} surfaceOptions={options}
selectedSurface={this.state.selectedSurface}
onChangeSurface={this.onSurfaceChange}
images={this.state.images}
onClear={this.onClear} onClear={this.onClear}
onTrimMemory={this.onTrimMemory} onTrimMemory={this.onTrimMemory}
onRefresh={() => this.updateCaches('refresh')} onRefresh={() => this.updateCaches('refresh')}