Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"presets": ["@babel/preset-react"],
"presets": [["@babel/preset-react", {"runtime": "automatic"}]],
"plugins": []
}
24 changes: 21 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@
"suncalc": "^1.9.0",
"tt-windows-utils": "file:src/modules/tt-windows-utils",
"win32-displayconfig": "file:src/modules/win32-displayconfig",
"windows-ambient-sensor": "file:src/modules/windows-ambient-sensor",
"windows-accent-colors": "^1.0.1",
"windows-hdr": "file:src/modules/windows-hdr",
"wmi-bridge": "file:src/modules/wmi-bridge",
"wmi-client": "^0.5.0"
"wmi-client": "^0.5.0",
"yoctolib-es2017": "^1.11.6320"
},
"build": {
"productName": "Twinkle Tray",
Expand Down Expand Up @@ -80,6 +82,7 @@
"!node_modules/global-mouse-events/node_modules",
"!node_modules/electron-acrylic-window/node_modules",
"!node_modules/tt-windows-utils/node_modules",
"!node_modules/windows-ambient-sensor/node_modules",
"!node_modules/windows-accent-colors/node_modules",
"!node_modules/**/node-gyp/*",
"!node_modules/**/*.ipdb",
Expand All @@ -104,6 +107,7 @@
"!node_modules/native-reg/src/*",
"!node_modules/acrylic/bin/**/*.node",
"!node_modules/tt-windows-utils/bin/**/*.node",
"!node_modules/windows-ambient-sensor/bin/**/*.node",
"!node_modules/win32-displayconfig/bin/**/*.node",
"!node_modules/@paymoapp/active-window/module/*",
"!node_modules/@paymoapp/active-window/src/*",
Expand Down
27 changes: 12 additions & 15 deletions src/components/SettingsWindow.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import MonitorInfo from "./MonitorInfo"
import MonitorFeatures from "./MonitorFeatures"
import { SettingsOption, SettingsChild } from "./SettingsOption";
import SafeRender from "./SafeRender";
import { getMonitorName } from './utilts/monitor.util';
import { LightSensorSettings } from "./light-sensor/LightSensorSettings";

import DefaultIcon from "../assets/tray-icons/dark/[email protected]"
import MDL2Icon from "../assets/tray-icons/dark/[email protected]"
Expand Down Expand Up @@ -116,7 +118,7 @@ export default class SettingsWindow extends PureComponent {
super(props)
this.state = {
rawSettings: {},
activePage: "general",
activePage: "light-sensor",
theme: 'default',
openAtLogin: false,
brightnessAtStartup: true,
Expand Down Expand Up @@ -361,6 +363,11 @@ export default class SettingsWindow extends PureComponent {
label: T.t("SETTINGS_SIDEBAR_HOTKEYS"),
icon: ""
},
{
id: "light-sensor",
label: 'Light Sensor',
icon: ""
},
{
id: "updates",
label: T.t("SETTINGS_SIDEBAR_UPDATES"),
Expand Down Expand Up @@ -1322,10 +1329,6 @@ export default class SettingsWindow extends PureComponent {
</div>
</SettingsPage>





<SettingsPage current={this.state.activePage} id="hotkeys">
<div className="pageSection">
<div className="sectionTitle">{T.t("SETTINGS_HOTKEYS_TITLE")}</div>
Expand Down Expand Up @@ -1410,7 +1413,9 @@ export default class SettingsWindow extends PureComponent {
</div>
</SettingsPage>


<SettingsPage current={this.state.activePage} id="light-sensor">
<LightSensorSettings T={T} renderToggle={this.renderToggle.bind(this)} monitors={this.state.monitors}></LightSensorSettings>
</SettingsPage>

<SettingsPage current={this.state.activePage} id="updates">
<div className="pageSection">
Expand Down Expand Up @@ -1591,14 +1596,6 @@ function getProfileMonitors(monitors, profile, onChange) {
})
}

function getMonitorName(monitor, renames) {
if (Object.keys(renames).indexOf(monitor.id) >= 0 && renames[monitor.id] != "") {
return renames[monitor.id] + ` (${monitor.name})`
} else {
return monitor.name
}
}

function AppProfile(props) {
const { profile, updateValue, onDelete, monitors } = props
if (!profile.monitors) profile.monitors = {};
Expand Down Expand Up @@ -1817,4 +1814,4 @@ function ActionItem(props) {
</div>
</div>
)
}
}
118 changes: 118 additions & 0 deletions src/components/light-sensor/LightSensorSettings.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { SettingsChild, SettingsOption } from "../SettingsOption";
import { getMonitorName } from "../utilts/monitor.util";
import { YoctoSettings } from "./YoctoSettings";

export function LightSensorSettings({ T, renderToggle, monitors }) {

// trigger the monitor state update, as sometimes its not present
useEffect(() => window.reloadReactMonitors(),[])

const minMaxChange = useCallback((monitor, type, value) => {
const currentSettings = window.settings.yoctoMonitorSettings || {};
const monitorSettings = currentSettings[monitor.key] || { minLux: 5, maxLux: 250, enabled: true };

if (type === 'min') {
monitorSettings.minLux = value;
} else if (type === 'max') {
monitorSettings.maxLux = value;
}

const newSettings = {
...currentSettings,
[monitor.key]: monitorSettings
};

window.sendSettings({ yoctoMonitorSettings: newSettings });
}, []);

const toggleMonitorEnabled = useCallback((monitor, enabled) => {
const currentSettings = window.settings.yoctoMonitorSettings || {};
const monitorSettings = currentSettings[monitor.key] || { minLux: 5, maxLux: 250, enabled: true };

monitorSettings.enabled = enabled;

const newSettings = {
...currentSettings,
[monitor.key]: monitorSettings
};

window.sendSettings({ yoctoMonitorSettings: newSettings });
}, []);


const dropdownChanged = useCallback((newUrl) => {
window.sendSettings({ yoctoHubUrl: newUrl });
}, []);
return (
<>
<div className="pageSection">
<div className="sectionTitle">Light Sensor</div>
<p>
Set the brightness based on environment light from a light sensor
</p>
</div>
<div className="pageSection">
<SettingsChild title={'Enable'} input={renderToggle("yoctoEnabled")} />
<SettingsOption title={"Select Sensor Type"} input={
<select value={"yocto"} onChange={dropdownChanged}>
<option value="yocto">Yocto</option>
<option value="windows">Windows</option>
<option value="fake">Fake</option>
</select>
}></SettingsOption>

<YoctoSettings T={T} renderToggle={renderToggle} monitors={monitors}></YoctoSettings>
<SettingsChild>
<p>This maps each monitor's brightness (0%-100%) to ambient light levels in Lux.</p>
<p>For example, setting the range to 5 and 250 means:</p>
<ul>
<li><p>When the sensor reads 5 Lux or less, brightness is set to 0%.</p></li>
<li><p>When the sensor reads 250 Lux or more, brightness is set to 100%.</p></li>
<li><p>Values between 5 and 250 Lux are linearly interpolated.</p></li>
</ul>
</SettingsChild>
{Object.values(monitors ?? {}).map((monitor) => {
const monitorSettings = window.settings.yoctoMonitorSettings?.[monitor.key] || { minLux: 5, maxLux: 250, enabled: false };
return (
<SettingsChild key={monitor.key}>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<input
style={{ marginTop: '17px'}}
type="checkbox"
checked={monitorSettings.enabled}
data-checked={monitorSettings.enabled}
onChange={(e) => toggleMonitorEnabled(monitor, e.target.checked)}
/>
<strong>{getMonitorName(monitor, {})}</strong>
<div>
<label style={{ textTransform: "capitalize", fontSize: 'smaller' }}>0% at</label>
<input
style={{ marginTop: '5px '}}
type="number"
min="0"
max="600"
value={monitorSettings.minLux}
onChange={(e) => minMaxChange(monitor, 'min', Number(e.target.value))}
/>
</div>
<div>
<label style={{ textTransform: "capitalize", fontSize: 'smaller' }}>100% at</label>
<input
style={{ marginTop: '5px '}}
type="number"
min="0"
max="600"
value={monitorSettings.maxLux}
onChange={(e) => minMaxChange(monitor, 'max', Number(e.target.value))}
/>
</div>
<span>Lux</span>
</div>
</SettingsChild>
);
})}
</div>
</>
);
}
118 changes: 118 additions & 0 deletions src/components/light-sensor/YoctoSettings.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { SettingsChild } from "../SettingsOption";
import { getMonitorName } from "../utilts/monitor.util";

export function YoctoSettings({ T, renderToggle, monitors }) {
// trigger the monitor state update, as sometimes its not present

const sensorUrl =
"https://www.yoctopuce.com/EN/products/usb-environmental-sensors/yocto-light-v5";

const [yoctoStatus, setYoctoStatus] = useState({
hubConnected: false,
sensorConnected: false,
illuminance: null,
});

useEffect(() => {
const handleYoctoStatus = (e, status) => {
setYoctoStatus(status);
};

window.ipc.on("yocto-status", handleYoctoStatus);

return () => {
window.ipc.removeListener("yocto-status", handleYoctoStatus);
};
}, []);

const virtualhubUrl =
"https://www.yoctopuce.com/EN/article/for-the-beginners/the-virtualhub-a-multi-purpose-tool";

const message = useMemo(() => {
if (!yoctoStatus.hubConnected) {
return (
<p>
Yocto Virtual Hub not found see{" "}
<a href={virtualhubUrl} target="_blank" rel="noreferrer">
here
</a>
</p>
);
}
if (!yoctoStatus.sensorConnected) {
return (
<p>
Yocto Light Sensor not found{" "}
<span className="icon" style={{ color: "red" }}>
&#xE783;
</span>
</p>
);
}
return <p>Yocto Light Sensor Found</p>;
}, [yoctoStatus.hubConnected, yoctoStatus.sensorConnected]);

const handleUrlChange = useCallback((newUrl) => {
window.sendSettings({ yoctoHubUrl: newUrl });
}, []);
return (
<>
<SettingsChild>
Get environment light from a{" "}
<a href={sensorUrl} target="_blank" rel="noreferrer">
Yocto light sensor
</a>
{message}{" "}
{yoctoStatus.sensorConnected && yoctoStatus.illuminance !== null
? `${yoctoStatus.illuminance} Lux`
: ""}
</SettingsChild>
<SettingsChild>
<p>
To communicate to the sensor, you need to install the "Yocto Virtual
Hub" this allows this program to talk to connected sensors on your pc
</p>
<p>
<strong>Important:</strong> The virtual hub can be configured to auto
start by running it on the command line with '-i'
<br />
See
<i>
"-i : Installation as a service"{" "}
<a
href={
"https://www.yoctopuce.com/EN/products/yocto-light-v5/doc/LIGHTMK5.usermanual.html"
}
target="_blank"
rel="noreferrer"
>
Here
</a>
</i>
</p>

<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<label>VirtualHub URL:</label>
<input
type="text"
value={window.settings.yoctoHubUrl || "http://127.0.0.1:4444"}
onChange={(e) => handleUrlChange(e.target.value)}
style={{ flex: 1, maxWidth: "300px" }}
placeholder="http://127.0.0.1:4444"
/>
{yoctoStatus.hubConnected ? (
<div className="icon">&#xE73E;</div>
) : (
<>
<div className="icon" style={{ color: "red" }}>
&#xE783;
</div>{" "}
<span>Disconnected</span>
</>
)}
</div>
</SettingsChild>
</>
);
}
Loading