Summary: per title In addition, this diff adds `startUnactivated` option to allow setting up `onSend` mock implementation. Reviewed By: mweststrate Differential Revision: D24477989 fbshipit-source-id: f913574ebacdd436e8511baa43744249a014e90b
236 lines
6.6 KiB
TypeScript
236 lines
6.6 KiB
TypeScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
import {
|
|
ManagedTable,
|
|
Text,
|
|
Heading,
|
|
FlexColumn,
|
|
colors,
|
|
FlexRow,
|
|
ManagedDataInspector,
|
|
styled,
|
|
Select,
|
|
} from 'flipper';
|
|
import {PluginClient, createState, usePlugin, useValue} from 'flipper-plugin';
|
|
import {clone} from 'lodash';
|
|
|
|
import React from 'react';
|
|
|
|
type SharedPreferencesChangeEvent = {
|
|
preferences: string;
|
|
name: string;
|
|
time: number;
|
|
deleted: boolean;
|
|
value?: any;
|
|
};
|
|
type SharedPreferences = Record<string, any>;
|
|
type SharedPreferencesEntry = {
|
|
preferences: SharedPreferences;
|
|
changesList: Array<SharedPreferencesChangeEvent>;
|
|
};
|
|
|
|
export type SetSharedPreferenceParams = {
|
|
sharedPreferencesName: string;
|
|
preferenceName: string;
|
|
preferenceValue: any;
|
|
};
|
|
type DeleteSharedPreferenceParams = {
|
|
sharedPreferencesName: string;
|
|
preferenceName: string;
|
|
};
|
|
|
|
type Events = {sharedPreferencesChange: SharedPreferencesChangeEvent};
|
|
type Methods = {
|
|
getAllSharedPreferences: (params: {}) => Promise<
|
|
Record<string, SharedPreferences>
|
|
>;
|
|
setSharedPreference: (
|
|
params: SetSharedPreferenceParams,
|
|
) => Promise<SharedPreferences>;
|
|
deleteSharedPreference: (
|
|
params: DeleteSharedPreferenceParams,
|
|
) => Promise<SharedPreferences>;
|
|
};
|
|
|
|
export function plugin(client: PluginClient<Events, Methods>) {
|
|
const selectedPreferences = createState<string | null>(null, {
|
|
persist: 'selectedPreferences',
|
|
});
|
|
const setSelectedPreferences = (value: string) =>
|
|
selectedPreferences.set(value);
|
|
const sharedPreferences = createState<Record<string, SharedPreferencesEntry>>(
|
|
{},
|
|
{persist: 'sharedPreferences'},
|
|
);
|
|
|
|
function updateSharedPreferences(update: {name: string; preferences: any}) {
|
|
if (selectedPreferences.get() == null) {
|
|
selectedPreferences.set(update.name);
|
|
}
|
|
sharedPreferences.update((draft) => {
|
|
const entry = draft[update.name] || {changesList: []};
|
|
entry.preferences = update.preferences;
|
|
draft[update.name] = entry;
|
|
});
|
|
}
|
|
|
|
async function setSharedPreference(params: SetSharedPreferenceParams) {
|
|
const results = await client.send('setSharedPreference', params);
|
|
updateSharedPreferences({
|
|
name: params.sharedPreferencesName,
|
|
preferences: results,
|
|
});
|
|
}
|
|
async function deleteSharedPreference(params: DeleteSharedPreferenceParams) {
|
|
const results = await client.send('deleteSharedPreference', params);
|
|
updateSharedPreferences({
|
|
name: params.sharedPreferencesName,
|
|
preferences: results,
|
|
});
|
|
}
|
|
|
|
client.onMessage('sharedPreferencesChange', (change) =>
|
|
sharedPreferences.update((draft) => {
|
|
const entry = draft[change.preferences];
|
|
if (entry == null) {
|
|
return;
|
|
}
|
|
if (change.deleted) {
|
|
delete entry.preferences[change.name];
|
|
} else {
|
|
entry.preferences[change.name] = change.value;
|
|
}
|
|
entry.changesList.unshift(change);
|
|
draft[change.preferences] = entry;
|
|
}),
|
|
);
|
|
client.onConnect(async () => {
|
|
const results = await client.send('getAllSharedPreferences', {});
|
|
Object.entries(results).forEach(([name, prefs]) =>
|
|
updateSharedPreferences({name: name, preferences: prefs}),
|
|
);
|
|
});
|
|
|
|
return {
|
|
selectedPreferences,
|
|
sharedPreferences,
|
|
setSelectedPreferences,
|
|
setSharedPreference,
|
|
deleteSharedPreference,
|
|
};
|
|
}
|
|
|
|
const CHANGELOG_COLUMNS = {
|
|
event: {value: 'Event'},
|
|
name: {value: 'Name'},
|
|
value: {value: 'Value'},
|
|
};
|
|
const CHANGELOG_COLUMN_SIZES = {
|
|
event: '30%',
|
|
name: '30%',
|
|
value: '30%',
|
|
};
|
|
|
|
const UPDATED_LABEL = <Text color={colors.lime}>Updated</Text>;
|
|
const DELETED_LABEL = <Text color={colors.cherry}>Deleted</Text>;
|
|
|
|
const InspectorColumn = styled(FlexColumn)({flexGrow: 0.2});
|
|
const ChangelogColumn = styled(FlexColumn)({
|
|
flexGrow: 0.8,
|
|
paddingLeft: '16px',
|
|
});
|
|
const RootColumn = styled(FlexColumn)({
|
|
paddingLeft: '16px',
|
|
paddingRight: '16px',
|
|
paddingTop: '16px',
|
|
});
|
|
|
|
export function Component() {
|
|
const instance = usePlugin(plugin);
|
|
const selectedPreferences = useValue(instance.selectedPreferences);
|
|
const sharedPreferences = useValue(instance.sharedPreferences);
|
|
|
|
if (selectedPreferences == null) {
|
|
return null;
|
|
}
|
|
const entry = sharedPreferences[selectedPreferences];
|
|
if (entry == null) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<RootColumn grow={true}>
|
|
<Heading>
|
|
<span style={{marginRight: '16px'}}>Preference File</span>
|
|
<Select
|
|
options={Object.keys(sharedPreferences)
|
|
.sort((a, b) => (a.toLowerCase() > b.toLowerCase() ? 1 : -1))
|
|
.reduce((obj, item) => {
|
|
obj[item] = item;
|
|
return obj;
|
|
}, {} as Record<string, string>)}
|
|
selected={selectedPreferences}
|
|
onChange={instance.setSelectedPreferences}
|
|
/>
|
|
</Heading>
|
|
<FlexRow grow={true} scrollable={true}>
|
|
<InspectorColumn>
|
|
<Heading>Inspector</Heading>
|
|
<ManagedDataInspector
|
|
data={entry.preferences}
|
|
setValue={async (path: Array<string>, value: any) => {
|
|
if (entry == null) {
|
|
return;
|
|
}
|
|
const values = entry.preferences;
|
|
let newValue = value;
|
|
if (path.length === 2 && values) {
|
|
newValue = clone(values[path[0]]);
|
|
newValue[path[1]] = value;
|
|
}
|
|
await instance.setSharedPreference({
|
|
sharedPreferencesName: selectedPreferences,
|
|
preferenceName: path[0],
|
|
preferenceValue: newValue,
|
|
});
|
|
}}
|
|
onDelete={async (path: Array<string>) =>
|
|
await instance.deleteSharedPreference({
|
|
sharedPreferencesName: selectedPreferences,
|
|
preferenceName: path[0],
|
|
})
|
|
}
|
|
/>
|
|
</InspectorColumn>
|
|
<ChangelogColumn>
|
|
<Heading>Changelog</Heading>
|
|
<ManagedTable
|
|
columnSizes={CHANGELOG_COLUMN_SIZES}
|
|
columns={CHANGELOG_COLUMNS}
|
|
rowLineHeight={26}
|
|
rows={entry.changesList.map((element, index) => {
|
|
return {
|
|
columns: {
|
|
event: {
|
|
value: element.deleted ? DELETED_LABEL : UPDATED_LABEL,
|
|
},
|
|
name: {value: element.name},
|
|
value: {value: String(element.value)},
|
|
},
|
|
key: String(index),
|
|
};
|
|
})}
|
|
/>
|
|
</ChangelogColumn>
|
|
</FlexRow>
|
|
</RootColumn>
|
|
);
|
|
}
|