Photoshop crashing on attempting to write `kuiBrightness` value to Redux store

I’m trying to dynamically change Spectrum theme based on kuiBrightness changes by passing the value (after mapping it to the appropriate Spectrum value) into a Redux store. Everything works as expected until Photoshop crashes as soon as a new kuiBrightness value is clicked on in the PS preferences dialog. After debugging I can trace it to when Redux tries to update the store. When I console.log the payload value it’s as expected.

Elsewhere in my code I have a menu to select Spectrum theme and passing the string value from there successfully updates the store.

I get a crash report but I’ll save posting it until someone asks as it’s long.

/**
* App.jsx
*/

addNotificationListener(
  [
    {
      event: "uiBrightnessChanged",
    },
  ],
  (e, data) => {
    const ThemeList = {
      DARKEST: "darkest",
      DARK: "dark",
      LIGHT: "light",
      LIGHTEST: "lightest",
    };
    
    const ThemeMap = new Map([
      ["kPanelBrightnessDarkGray", ThemeList.DARKEST],
      ["kPanelBrightnessMediumGray", ThemeList.DARK],
      ["kPanelBrightnessLightGray", ThemeList.LIGHT],
      ["kPanelBrightnessOriginal", ThemeList.LIGHTEST],
    ]);

    const themeName = ThemeMap.get(data.kuiBrightnessLevel._value);

    setTheme(themeName);  // store action - see other code block
  }
);
/**
 *  store.js
 */

export const store = createStore({
  spectrum: { theme: "darkest", scale: "medium", activeSize: "m" },
  setTheme: action((state, payload) => {
    state.spectrum.theme = payload;
  }),
});

I’m using easy peasy v5 for Redux.

Not sure if this will help, but could you try one of the two options?

// Option 1
export const store = createStore({
  spectrum: { theme: "darkest", scale: "medium", activeSize: "m" },
  setTheme: action((state, payload) => {
    state.spectrum = {...state.spectrum, theme: payload};
  }),
});
// Option 2
export const store = createStore({
  spectrum: {
    theme: "darkest",
    scale: "medium",
    activeSize: "m",
    setTheme: action((state, payload) => {
      state.theme = payload;
    }),
  },
});

I use the second option all over my plugin. Don’t recall for sure now, but I think I saw some recommendation somewhere to keep related actions and thunks inside the state, which they are interacting with.

But honestly I don’t see anything wrong with your code too :confused:
How do you get setTheme() action in App.jsx?

Thanks, I’ll try scoping the action later.
The weird thing is that also I call the same setTheme action outside of the <Storeprovider> like this and it works.

store.getActions().setTheme(getTheme());
const getTheme = () => {
  const result = batchPlay(
    [
      {
        _obj: "get",
        _target: [
          { _property: "kuiBrightnessLevel" },
          { _ref: "application", _enum: "ordinal", _value: "targetEnum" },
        ],
        _options: { dialogOptions: "dontDisplay" },
      },
    ],
    { synchronousExecution: true }
  );

  const pinned = result[0].kuiBrightnessLevel._value;

  return ThemeMap.get(pinned) ?? ThemeList.DARK;
};

I meant the action setTheme - how do you get it inside App.jsx?

Oh yeah, sorry!

const { setTheme } = useStoreActions((actions) => actions);

It executes fine, I can log the payload from within the action.

1 Like

After some further testing I can see that what was actually causing the crash was the Menu component I have for selecting the Spectrum theme elsewhere in my code:

<Menu selects="single" onchange={props.handleComponentSelect}>
  {props.list.map((component, index) => {
    return (
      <MenuItem
        key={index}
        value={component.name}
        selected={props.selected === component.name ? true : false}
      >
        {component.label}
      </MenuItem>
    );
  })}
</Menu>

and more specifically the selected attribute:

selected={props.selected === component.name ? true : false}

props.selected is spectrum.theme from the store. I guess what’s happening is that changing selected triggers the parent Menu onchange event and bam, stack overflow.

I’ve removed the selected ternary and am moving on with my life, I can live without the tick indicator as I display the selected value in the PickerButton.

So is it because of infinite loop? Also I thought that false === true in spectrum attributes so you have to assign undefined instead of false to make it work.

I’ve got to assume as much, but having stopped the crash I’m happy not knowing for sure :laughing:

At least in the case of MenuItem false and undefined both work.

Oh yes… I’m just using null instead of undefined. false didn’t work for me in some cases

I find null usually works too