Store storage quota in Redux, handle WS event and expose useStorageStatus hook

Summary

Add a dedicated storageQuotaChanged Redux action + reducer in configSlice that updates the tariff's usedQuota (and optionally quotas) in-place when the WebSocket fires. Wire the handler in the core signaling message handler. Expose a useStorageStatus computed hook that derives all storage status flags needed by the UI.

Implementation details

  1. In configSlice, add a reducer action:
reducers: {
  update: ...,
  storageQuotaChanged: (state, { payload }: PayloadAction<{ total?: number; used: number }>) => {
    state.tariff.usedQuota['maxStorage'] = payload.used;
    if (payload.total !== undefined) {
      state.tariff.quotas['maxStorage'] = payload.total;
    }
  },
},

Add selectors:

export const selectStorageUsed = (state: RootState) => state.config.tariff.usedQuota['maxStorage'];
export const selectStorageTotal = (state: RootState) => state.config.tariff.quotas['maxStorage'];
  1. In handlers/core.ts, add case:
case 'storage_quota_changed':
  dispatch(storageQuotaChanged(data.quota));
  break;
  1. New app/src/hooks/useStorageStatus.ts:
export const useStorageStatus = () => {
  const used = useAppSelector(selectStorageUsed) ?? 0;
  const total = useAppSelector(selectStorageTotal); // undefined = unlimited
  const canUpgrade = useAppSelector(selectIsFeatureEnabled(CoreFeatures.StorageUpgradable));

  const usagePercentage = total ? (used / total) * 100 : 0;
  const isNearLimit = total ? usagePercentage >= 95 : false;
  const isFull = total ? usagePercentage >= 100 : false;

  return { usagePercentage, isNearLimit, isFull, canUpgrade };
};

Acceptance criteria

  • redux action storageQuotaChanged updates state.config.tariff.usedQuota.maxStorage on dispatch
  • if payload.total is present, state.config.tariff.quotas.maxStorage is updated too
  • a storage_quota_changed WS message dispatches storageQuotaChanged with the correct payload
  • useStorageStatus returns isNearLimit: false and isFull: false when total is undefined (unlimited storage)
  • useStorageStatus returns isFull: true when used >= total
  • useStorageStatus returns isNearLimit: true when used / total >= 0.95
  • unit tests for useStorageStatus cover the unlimited, near-limit and full cases