frontend/smart-hut/src/store.js

138 lines
4.1 KiB
JavaScript

import { createStore } from "redux";
import { RemoteService } from "./remote";
import { createDispatchHook } from "react-redux";
import actions from "./storeActions";
const initialToken = localStorage.getItem("token");
const initialState = {
login: {
loggedIn: false,
token: initialToken ? initialToken : null,
},
userInfo: null,
/** @type {[integer]Room} */
rooms: {},
/** @type {[integer]Device} */
devices: {},
};
function reducer(previousState, action) {
let newState = Object.assign({}, previousState);
const createOrUpdateRoom = (room) => {
if (!(room.id in newState.rooms)) {
newState.rooms[room.id] = room;
newState.rooms[room.id].devices = new Set();
} else {
newState.rooms[room.id].name = room.name;
newState.rooms[room.id].image = room.image;
newState.rooms[room.id].icon = room.icon;
}
};
switch (action.type) {
case "LOGIN_UPDATE":
newState.login = action.login;
delete newState.errors.login;
break;
case "USER_INFO_UPDATE":
newState.user = action.user;
delete newState.errors.userInfo;
break;
case "ROOMS_UPDATE":
for (const room of action.rooms) {
createOrUpdateRoom(room);
}
delete newState.errors.rooms;
break;
case "DEVICES_UPDATE":
// if room is given, delete all devices in that room
// and remove any join between that room and deleted
// devices
if (action.roomId) {
const room = newState.rooms[action.roomId];
for (const deviceId of room.devices) {
delete newState.devices[deviceId];
}
room.devices = [];
} else if (action.partial) {
// if the update is partial and caused by an operation on an input
// device (like /switch/operate), iteratively remove deleted
// devices and their join with their corresponding room.
for (const device of action.devices) {
const room = newState.rooms[newState.devices[device.id].roomId];
room.devices.delete(device.id);
delete newState.devices[device.id];
}
} else {
// otherwise, just delete all devices and all joins
// between rooms and devices
newState.devices = {};
for (const room of newState.rooms) {
room.devices = [];
}
}
for (const device of action.devices) {
newState.devices[device.id] = device;
if (device.roomId in newState.rooms) {
newState.rooms[device.roomId].devices.add(device.id);
} else {
console.warn(
"Cannot join device",
device,
`in room ${device.roomId} since that
room has not been fetched`
);
}
}
delete newState.errors.devices;
break;
case "ROOM_SAVE":
createOrUpdateRoom(action.room);
break;
case "ROOM_DELETE":
if (!(actions.roomId in newState.rooms)) {
console.warn(`Room to delete ${actions.roomId} does not exist`);
break;
}
// This update does not ensure the consistent update of switchId/dimmerId properties
// on output devices connected to an input device in this room. Please manually request
// all devices again if consistent update is desired
for (const id of newState.rooms[action.roomId].devices) {
delete newState.devices[id];
}
delete newState.rooms[action.roomId];
break;
case "DEVICE_DELETE":
if (!(actions.deviceId in newState.devices)) {
console.warn(`Device to delete ${actions.deviceId} does not exist`);
break;
}
newState.rooms[newState.devices[actions.deviceId].roomId].devices.delete(
actions.deviceId
);
delete newState.devices[actions.deviceId];
break;
case "LOGOUT":
newState.login = { token: null, loggedIn: false };
newState.rooms = [];
newState.devices = [];
delete newState.errors.login;
break;
default:
console.warn(`Action type ${action.type} unknown`, action);
}
return newState;
}
const smartHutStore = createStore(reducer, initialState);
export default smartHutStore;