import React from 'react'; import { ipcRenderer } from 'electron'; import { Tab, TabList, TabPanel, Tabs } from 'react-tabs'; import Creatable from 'react-select/creatable'; import Select from 'react-select'; export class ViewStateSettings extends React.Component { constructor(props) { super(props); this.stateManager = this.props.config.state; const options = this.stateManager.savedStates.map(state => { return { value: state.name, label: state.name }; }); const optionsWithNull = this.getOptionsWithNull(options); console.log(this.stateManager) this.state = { selection: null, options: options, isLoading: false, optionsWithNull: optionsWithNull, selectionStart: optionsWithNull.find(o => o.value === this.stateManager.stateOnStart), selectionResume: optionsWithNull.find(o => o.value === this.stateManager.stateOnResume), selectionSuspend: optionsWithNull.find(o => o.value === this.stateManager.stateOnSuspend), selectionAc: optionsWithNull.find(o => o.value === this.stateManager.stateOnAc), selectionBatt: optionsWithNull.find(o => o.value === this.stateManager.stateOnBattery), selectionShutdown: optionsWithNull.find(o => o.value === this.stateManager.stateOnShutdown), selectionLockscreen: optionsWithNull.find(o => o.value === this.stateManager.stateOnLockScreen), selectionUnlockscreen: optionsWithNull.find(o => o.value === this.stateManager.stateOnUnlockScreen), selectionUserDidBecomeActive: optionsWithNull.find(o => o.value === this.stateManager.stateOnUserDidBecomeActive), selectionUserDidResignActive: optionsWithNull.find(o => o.value === this.stateManager.stateOnUserDidResignActive), } } getOptionsWithNull(options) { return [{ value: null, label: '--- Default: do nothing ---' }].concat(options); } getPropertiesToKeyValues(object) { return Object.entries(object).map(([key, value]) => { return <div key={key} className='state-device-body-properties'> <div>{key.toUpperCase()}</div> <div>{JSON.stringify(value)}</div> </div> }); } getDeviceStateFor(device, state) { return (<div key={device.productId} className='state-device'> <div className='state-device-title'>{device.name}</div> <div className='state-device-body'>{this.getPropertiesToKeyValues(state)}</div> </div>); } selectionChange(item, actionObject) { if(actionObject.action === 'clear') { if(window.confirm('Do you really want to remove state "'+this.state.selection.label+'"?')) { const toDeleteItem = this.state.selection.value; ipcRenderer.send('state-settings-remove', toDeleteItem); const newOptions = this.state.options.filter(o => o.value !== toDeleteItem); this.setState({ selection: null, options: newOptions }); } } else { this.setState({ selection: item }); } } handleCreate(itemName) { this.setState({ isLoading: true }); const additionalState = ipcRenderer.sendSync('state-settings-add', itemName); this.stateManager.savedStates.push(additionalState); const devicesWithUndefinedState = additionalState.states.filter(stateObj => !stateObj.state.mode).map(stateObj => { const device = this.stateManager.devices.find(d => d.productId === stateObj.deviceId); return device.name; }); if(devicesWithUndefinedState.length > 0) { let message = 'The state "'+itemName+'" has been created but the following devices have an undefined state:'; message += '\n\n'; devicesWithUndefinedState.forEach(deviceName => message += 'ยท '+deviceName+'\n'); message += '\n'; message += 'Please set the mentioned devices to a defined state by using the Razer macOS menu at the top right and try again.'; window.alert(message); } const newOptions = this.stateManager.savedStates.map(state => { return { value: state.name, label: state.name }; }); this.setState({ isLoading:false, selection: newOptions.find(o => o.value === itemName), options: newOptions, optionsWithNull: this.getOptionsWithNull(newOptions) }); } handleClick() { ipcRenderer.send('state-settings-activate', this.state.selection.value); } renderState() { const stateToRender = this.stateManager.savedStates.find(s => this.state.selection != null && s.name == this.state.selection.value); if(!stateToRender) { return null; } return stateToRender.states.map(stateObj => { const device = this.stateManager.devices.find(device => device.productId == stateObj.deviceId); return this.getDeviceStateFor(device, stateObj.state); }); } selectionChangeStart(item) { this.setState({ selectionStart: item }); ipcRenderer.send('state-settings-start', item.value); } selectionChangeSuspend(item) { this.setState({ selectionSuspend: item }); ipcRenderer.send('state-settings-suspend', item.value); } selectionChangeResume(item) { this.setState({ selectionResume: item }); ipcRenderer.send('state-settings-resume', item.value); } selectionChangeAc(item) { this.setState({ selectionAc: item }); ipcRenderer.send('state-settings-ac', item.value); } selectionChangeBattery(item) { this.setState({ selectionBatt: item }); ipcRenderer.send('state-settings-battery', item.value); } selectionChangeShutdown(item) { this.setState({ selectionShutdown: item }); ipcRenderer.send('state-settings-shutdown', item.value); } selectionChangeLockscreen(item) { this.setState({ selectionLockscreen: item }); ipcRenderer.send('state-settings-lockscreen', item.value); } selectionChangeUnlockscreen(item) { this.setState({ selectionUnlockscreen: item }); ipcRenderer.send('state-settings-unlockscreen', item.value); } selectionChangeUserDidBecomeActive(item) { this.setState({ selectionUserDidBecomeActive: item }); ipcRenderer.send('state-settings-userdidbecomeactive', item.value); } selectionChangeUserDidResignActive(item) { this.setState({ selectionUserDidResignActive: item }); ipcRenderer.send('state-settings-userdidresignactive', item.value); } render() { const customStyles = { option: (provided, state) => ({ ...provided, borderBottom: '1px solid grey', color: state.isSelected ? '#47e10c' : 'grey', padding: '5px 10px', border: '1px solid #47e10c', borderTop: 'none', backgroundColor: state.isSelected ? 'green' : '#000', ':last-child': { borderBottomLeftRadius: '10px', borderBottomRightRadius: '10px', }, ':hover': { backgroundColor: state.isSelected ? 'green' : '#002b17', } }), control: (provided, state) => ({ ...provided, backgroundColor: 'black', border: '1px solid #47e10c', borderRadius: '15px', borderBottomLeftRadius: state.menuIsOpen ? '0' : '15px', borderBottomRightRadius: state.menuIsOpen ? '0' : '15px', color: '#47e10c', minHeight: 0, boxShadow: 'none', transition: 'none', ":hover": { borderColor: "inherit", }, }), menu: (provided, state) => ({ ...provided, backgroundColor: 'transparent', margin: 0, zIndex: 100, padding: 0, }), menuList: (provided, state) => ({ ...provided, backgroundColor: 'transparent', margin: 0, padding: 0, }), dropdownIndicator: (provided, state) => ({ ...provided, color: '#47e10c', padding: '0px 8px' }), indicatorSeparator: (provided, state) => ({ ...provided, backgroundColor: '#47e10c', }), singleValue: (provided, state) => ({ ...provided, color: '#47e10c', }), input: (provided, state) => ({ ...provided, color: '#47e10c', }), }; return ( <Tabs> <TabList> <Tab>States</Tab> <Tab>Settings</Tab> <Tab>Current devices state (debug)</Tab> </TabList> <TabPanel> <div> <div> <p> State manager allows you to create unique states for all your devices. <br />Either choose an existing state to activate or create a new one by: </p> <ol> <li>Set each device in the state you want it to be with the help of the menu</li> <li>Focus the dropdown and give your state a name, like "Party" or "Work".</li> <li>Press enter or click on the "Create" dropdown item</li> </ol> <p> States defined here can be previewed, activated and used in the "Settings" tab for system / application events. </p> </div> <div className={'control'}> <Creatable isLoading={this.state.isLoading} isClearable={true} value={this.state.selection} options={this.state.options} onCreateOption={(item) => this.handleCreate(item)} onChange={(item, action) => this.selectionChange(item, action)} styles={customStyles} /> </div> <div className={'control'}> <button disabled={this.state.selection == null} onClick={() => this.handleClick()}>{this.state.selection == null ? 'Activate - Please select a state first' : 'Activate'}</button> </div> <div className={'state-devices'}> {this.renderState()} </div> </div> </TabPanel> <TabPanel> <div> <p>Select a state to be activate on application and system events</p> </div> <div className={'state-selectors'}> <p>This state will be activated whenever Razer macOS starts or refreshes its devices.</p> <div className={'state-selector'}> <div>On application start</div> <div><Select value={this.state.selectionStart} options={this.state.optionsWithNull} onChange={(item) => this.selectionChangeStart(item)} styles={customStyles} /></div> </div> <p>This state will be activated when the system goes to sleep ('suspend' event).</p> <div className={'state-selector'}> <div>On system idle/sleep</div> <div><Select value={this.state.selectionSuspend} options={this.state.optionsWithNull} onChange={(item) => this.selectionChangeSuspend(item)} styles={customStyles} /></div> </div> <p>This state will be activated when the system wakes up ('resume' event).</p> <div className={'state-selector'}> <div>On system wake up</div> <div><Select value={this.state.selectionResume} options={this.state.optionsWithNull} onChange={(item) => this.selectionChangeResume(item)} styles={customStyles} /></div> </div> <p>This state will be activated when the system is plugged in ('on-ac' event).</p> <div className={'state-selector'}> <div>On system plugged in</div> <div><Select value={this.state.selectionAc} options={this.state.optionsWithNull} onChange={(item) => this.selectionChangeAc(item)} styles={customStyles} /></div> </div> <p>This state will be activated when the system is on battery ('on-battery' event).</p> <div className={'state-selector'}> <div>On system on battery</div> <div><Select value={this.state.selectionBatt} options={this.state.optionsWithNull} onChange={(item) => this.selectionChangeBattery(item)} styles={customStyles} /></div> </div> <p>This state will be activated when the system is about to shutdown ('shutdown' event).</p> <div className={'state-selector'}> <div>On system shutdown</div> <div><Select value={this.state.selectionShutdown} options={this.state.optionsWithNull} onChange={(item) => this.selectionChangeShutdown(item)} styles={customStyles} /></div> </div> <p>This state will be activated when the system is about to lock the screen ('lock-screen' event).</p> <div className={'state-selector'}> <div>On system lock screen</div> <div><Select value={this.state.selectionLockscreen} options={this.state.optionsWithNull} onChange={(item) => this.selectionChangeLockscreen(item)} styles={customStyles} /></div> </div> <p>This state will be activated when the system is about to unlock the screen ('unlock-screen' event).</p> <div className={'state-selector'}> <div>On system unlock screen</div> <div><Select value={this.state.selectionUnlockscreen} options={this.state.optionsWithNull} onChange={(item) => this.selectionChangeUnlockscreen(item)} styles={customStyles} /></div> </div> <p>This state will be activated when the user on the system is about to become active ('user-did-become-active' event).</p> <div className={'state-selector'}> <div>On system user become active</div> <div><Select value={this.state.selectionUserDidBecomeActive} options={this.state.optionsWithNull} onChange={(item) => this.selectionChangeUserDidBecomeActive(item)} styles={customStyles} /></div> </div> <p>This state will be activated when the user on the system is about to resign active ('user-did-resign-active' event).</p> <div className={'state-selector'}> <div>On system user resign active</div> <div><Select value={this.state.selectionUserDidResignActive} options={this.state.optionsWithNull} onChange={(item) => this.selectionChangeUserDidResignActive(item)} styles={customStyles} /></div> </div> </div> </TabPanel> <TabPanel> <div className={'state-devices'}> {this.stateManager.devices.map(device => this.getDeviceStateFor(device, device.state))} </div> </TabPanel> </Tabs> ); } }