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:
committed by
Facebook Github Bot
parent
520ffec7c9
commit
863088e7cf
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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')}
|
||||||
|
|||||||
Reference in New Issue
Block a user