/** * Copyright 2018-present Facebook. * 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 {FlipperPlugin} from 'flipper'; const {clone} = require('lodash'); type SharedPreferencesChangeEvent = {| preferences: string, name: string, time: number, deleted: boolean, value: string, |}; export type SharedPreferences = {| [name: string]: any, |}; type SharedPreferencesEntry = { preferences: SharedPreferences, changesList: Array, }; type SharedPreferencesMap = { [name: string]: SharedPreferencesEntry, }; type SharedPreferencesState = {| selectedPreferences: ?string, sharedPreferences: SharedPreferencesMap, |}; 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 = Updated; const DELETED_LABEL = Deleted; 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 default class extends FlipperPlugin { state = { selectedPreferences: null, sharedPreferences: {}, }; reducers = { UpdateSharedPreferences(state: SharedPreferencesState, results: Object) { let update = results.update; let entry = state.sharedPreferences[update.name] || {changesList: []}; entry.preferences = update.preferences; state.sharedPreferences[update.name] = entry; return { selectedPreferences: state.selectedPreferences || update.name, sharedPreferences: state.sharedPreferences, }; }, ChangeSharedPreferences(state: SharedPreferencesState, event: Object) { const change = event.change; const entry = state.sharedPreferences[change.preferences]; if (entry == null) { return; } if (change.deleted) { delete entry.preferences[change.name]; } else { entry.preferences[change.name] = change.value; } entry.changesList = [change, ...entry.changesList]; return { selectedPreferences: state.selectedPreferences, sharedPreferences: state.sharedPreferences, }; }, UpdateSelectedSharedPreferences( state: SharedPreferencesState, event: Object, ) { return { selectedPreferences: event.selected, sharedPreferences: state.sharedPreferences, }; }, }; init() { this.client .call('getAllSharedPreferences') .then((results: {[name: string]: SharedPreferences}) => { Object.entries(results).forEach(([name, prefs]) => { const update = {name: name, preferences: prefs}; this.dispatchAction({update, type: 'UpdateSharedPreferences'}); }); }); this.client.subscribe( 'sharedPreferencesChange', (change: SharedPreferencesChangeEvent) => { this.dispatchAction({change, type: 'ChangeSharedPreferences'}); }, ); } onSharedPreferencesChanged = (path: Array, value: any) => { const selectedPreferences = this.state.selectedPreferences; if (selectedPreferences == null) { return; } const entry = this.state.sharedPreferences[selectedPreferences]; 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; } this.client .call('setSharedPreference', { sharedPreferencesName: this.state.selectedPreferences, preferenceName: path[0], preferenceValue: newValue, }) .then((results: SharedPreferences) => { let update = { name: this.state.selectedPreferences, preferences: results, }; this.dispatchAction({update, type: 'UpdateSharedPreferences'}); }); }; onSharedPreferencesSelected = (selected: string) => { this.dispatchAction({ selected: selected, type: 'UpdateSelectedSharedPreferences', }); }; render() { const selectedPreferences = this.state.selectedPreferences; if (selectedPreferences == null) { return null; } const entry = this.state.sharedPreferences[selectedPreferences]; if (entry == null) { return null; } return ( Preference File