facebook / flipper

A desktop debugging platform for mobile developers.
https://fbflipper.com/
MIT License
13.31k stars 954 forks source link

flipper/desktop/plugins/public/shared_preferences is a WIP plugin #4937

Open haifengkao opened 1 year ago

haifengkao commented 1 year ago

🐛 Bug Report

<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],
              })
            }
          />

The above code says the setValue in shared preferences viewer only handles at most two levels setting in NSUserDefaults. If the user defaults contains three levels, e.g. { "UserProfile": [ { name: "John"}, { name: "Mary"} ] } path: ["UserProfile", "0", "name"] newValue: "Jack"

The user defaults will become { "UserProfile": "Jack" }

Expected result: { "UserProfile": [ { name: "Jack"}, { name: "Mary"} ] }

Same for onDelete. { "UserProfile": [ { name: "John"}, { name: "Mary"} ] } path: ["UserProfile", "0"]

The user defaults will become { }

Expected result: { "UserProfile": [ { name: "Mary"} ] }

The problem is that the path array isn't fully read at all. I think the plugin is not finished.

FreakWolf commented 1 year ago
      `<ManagedDataInspector
        data={entry.preferences}
        setValue={async (path: Array<string>, value: any) => {
          if (entry == null) {
            return;
          }
          const values = entry.preferences;
          let newValue = value;
          // Traverse the path to the nested preference and update it
          let current = values;
          for (let i = 0; i < path.length - 1; i++) {
            current = current[path[i]];
          }
          current[path[path.length - 1]] = newValue;

          await instance.setSharedPreference({
            sharedPreferencesName: selectedPreferences,
            preferenceName: path[0],
            preferenceValue: values, // Send the updated preferences object
          });
        }}
        onDelete={async (path: Array<string>) =>
          await instance.deleteSharedPreference({
            sharedPreferencesName: selectedPreferences,
            preferenceName: path[0],
          })
        }
      />`

In the modified code:

We traverse the path array to reach the nested preference that needs to be updated. We then update the corresponding value in the preferences object. Instead of sending just newValue to setSharedPreference, we send the entire updated values object, which now includes the changes.

I think this should solve the bug

FreakWolf commented 1 year ago

i have updated this in my PR too https://github.com/facebook/flipper/pull/5065