refactor: Refactors the code

This commit is contained in:
Ivan
2022-09-06 20:47:42 +03:00
parent 03c771703c
commit df132c36d0
8 changed files with 651 additions and 449 deletions

660
app.js
View File

@@ -9,23 +9,13 @@ const {
Menu,
Tray,
BrowserWindow,
} = require("electron");
const { autoUpdater } = require("electron-updater");
const AutoLaunch = require("auto-launch");
const Positioner = require("electron-traywindow-positioner");
const Store = require("electron-store");
const bonjour = require("bonjour")();
} = require('electron');
const { autoUpdater } = require('electron-updater');
const AutoLaunch = require('auto-launch');
const Positioner = require('electron-traywindow-positioner');
const Store = require('electron-store');
const bonjour = require('bonjour')();
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const registerKeyboardShortcut = () => {
globalShortcut.register("CommandOrControl+Alt+X", () => {
if (window.isVisible()) window.hide();
else showWindow();
});
};
const unregisterKeyboardShortcut = () => {
globalShortcut.unregisterAll();
};
app.allowRendererProcessReuse = true;
@@ -33,16 +23,20 @@ app.allowRendererProcessReuse = true;
if (!app.requestSingleInstanceLock()) {
app.quit();
} else {
app.on("second-instance", () => {
if (window) showWindow();
app.on('second-instance', () => {
if (window) {
showWindow();
}
});
}
// hide dock icon on macOS
if (process.platform === "darwin") app.dock.hide();
if (process.platform === 'darwin') {
app.dock.hide();
}
const store = new Store();
const autoLauncher = new AutoLaunch({ name: "Home Assistant Desktop" });
const autoLauncher = new AutoLaunch({ name: 'Home Assistant Desktop' });
const indexFile = `file://${__dirname}/web/index.html`;
const errorFile = `file://${__dirname}/web/error.html`;
@@ -51,25 +45,43 @@ let autostartEnabled = false;
let forceQuit = false;
let resizeEvent = false;
const useAutoUpdater = () => {
autoUpdater.on("error", (message) => {
console.error("There was a problem updating the application");
function registerKeyboardShortcut() {
globalShortcut.register('CommandOrControl+Alt+X', () => {
if (window.isVisible()) {
window.hide();
} else {
showWindow();
}
});
}
function unregisterKeyboardShortcut() {
globalShortcut.unregisterAll();
}
function useAutoUpdater() {
autoUpdater.on('error', (message) => {
console.error('There was a problem updating the application');
console.error(message);
});
autoUpdater.on("update-downloaded", () => {
autoUpdater.on('update-downloaded', () => {
forceQuit = true;
autoUpdater.quitAndInstall();
});
setInterval(() => {
if (store.get("autoUpdate")) autoUpdater.checkForUpdates();
if (store.get('autoUpdate')) {
autoUpdater.checkForUpdates();
}
}, 1000 * 60 * 60);
if (store.get("autoUpdate")) autoUpdater.checkForUpdates();
};
if (store.get('autoUpdate')) {
autoUpdater.checkForUpdates();
}
}
const checkAutoStart = () => {
function checkAutoStart() {
autoLauncher
.isEnabled()
.then((isEnabled) => {
@@ -78,23 +90,31 @@ const checkAutoStart = () => {
.catch((err) => {
console.error(err);
});
};
}
const startAvailabilityCheck = () => {
setInterval(() => {
function startAvailabilityCheck() {
let interval;
function availabilityCheck() {
const request = net.request(`${currentInstance()}/auth/providers`);
request.on("response", (response) => {
request.on('response', (response) => {
showError(response.statusCode !== 200);
});
request.on("error", (error) => {
request.on('error', (error) => {
clearInterval(interval);
showError(true);
if (store.get("automaticSwitching")) checkForAvailableInstance();
if (store.get('automaticSwitching')) {
checkForAvailableInstance();
}
});
request.end();
}, 3000);
}
interval = setInterval(availabilityCheck, 3000);
};
const changePosition = () => {
function changePosition() {
const trayBounds = tray.getBounds();
const windowBounds = window.getBounds();
const displayWorkArea = screen.getDisplayNearestPoint({
@@ -103,77 +123,62 @@ const changePosition = () => {
}).workArea;
const taskBarPosition = Positioner.getTaskbarPosition(trayBounds);
if (taskBarPosition == "top" || taskBarPosition == "bottom") {
if (taskBarPosition === 'top' || taskBarPosition === 'bottom') {
const alignment = {
x: "center",
y: taskBarPosition == "top" ? "up" : "down",
x: 'center',
y: taskBarPosition === 'top' ? 'up' : 'down',
};
if (
trayBounds.x + (trayBounds.width + windowBounds.width) / 2 <
displayWorkArea.width
)
if (trayBounds.x + (trayBounds.width + windowBounds.width) / 2 < displayWorkArea.width) {
Positioner.position(window, trayBounds, alignment);
else {
const { y } = Positioner.calculate(
window.getBounds(),
trayBounds,
alignment
);
} else {
const { y } = Positioner.calculate(window.getBounds(), trayBounds, alignment);
window.setPosition(
displayWorkArea.width - windowBounds.width + displayWorkArea.x,
y + (taskBarPosition == "bottom" && displayWorkArea.y),
false
y + (taskBarPosition === 'bottom' && displayWorkArea.y),
false,
);
}
} else {
const alignment = { x: taskBarPosition, y: "center" };
if (
trayBounds.y + (trayBounds.height + windowBounds.height) / 2 <
displayWorkArea.height
) {
const { x, y } = Positioner.calculate(
window.getBounds(),
trayBounds,
alignment
);
window.setPosition(
x + (taskBarPosition == "right" && displayWorkArea.x),
y
);
} else {
const { x } = Positioner.calculate(
window.getBounds(),
trayBounds,
alignment
);
window.setPosition(
x,
displayWorkArea.y + displayWorkArea.height - windowBounds.height,
false
);
}
}
};
const alignment = {
x: taskBarPosition,
y: 'center',
};
if (trayBounds.y + (trayBounds.height + windowBounds.height) / 2 < displayWorkArea.height) {
const { x, y } = Positioner.calculate(window.getBounds(), trayBounds, alignment);
window.setPosition(x + (taskBarPosition === 'right' && displayWorkArea.x), y);
} else {
const { x } = Positioner.calculate(window.getBounds(), trayBounds, alignment);
window.setPosition(x, displayWorkArea.y + displayWorkArea.height - windowBounds.height, false);
}
}
}
function checkForAvailableInstance() {
const instances = store.get('allInstances');
const checkForAvailableInstance = () => {
const instances = store.get("allInstances");
if (instances?.length > 1) {
bonjour.find({ type: "home-assistant" }, (instance) => {
if (instances.indexOf(instance.txt.internal_url) !== -1)
bonjour.find({ type: 'home-assistant' }, (instance) => {
if (instance.txt.internal_url && instances.indexOf(instance.txt.internal_url) !== -1) {
return currentInstance(instance.txt.internal_url);
if (instances.indexOf(instance.txt.external_url) !== -1)
}
if (instance.txt.external_url && instances.indexOf(instance.txt.external_url) !== -1) {
return currentInstance(instance.txt.external_url);
}
});
let found;
for (let instance of instances.filter((e) => e.url !== currentInstance())) {
const request = net.request(`${instance}/auth/providers`);
request.on("response", (response) => {
request.on('response', (response) => {
if (response.statusCode === 200) {
found = instance;
}
});
request.on("error", (error) => {});
request.on('error', (_) => {
});
request.end();
if (found) {
@@ -182,29 +187,29 @@ const checkForAvailableInstance = () => {
}
}
}
};
}
const getMenu = () => {
function getMenu() {
let instancesMenu = [
{
label: "Open in Browser",
label: 'Open in Browser',
enabled: currentInstance(),
click: () => {
shell.openExternal(currentInstance());
},
},
{
type: "separator",
type: 'separator',
},
];
const allInstances = store.get("allInstances");
const allInstances = store.get('allInstances');
if (allInstances) {
allInstances.forEach((e) => {
instancesMenu.push({
label: e,
type: "checkbox",
type: 'checkbox',
checked: currentInstance() === e,
click: () => {
currentInstance(e);
@@ -216,137 +221,150 @@ const getMenu = () => {
instancesMenu.push(
{
type: "separator",
type: 'separator',
},
{
label: "Add another Instance...",
label: 'Add another Instance...',
click: () => {
store.delete("currentInstance");
store.delete('currentInstance');
window.loadURL(indexFile);
window.show();
},
},
{
label: "Automatic Switching",
type: "checkbox",
enabled:
store.has("allInstances") && store.get("allInstances").length > 1,
checked: store.get("automaticSwitching"),
label: 'Automatic Switching',
type: 'checkbox',
enabled: store.has('allInstances') && store.get('allInstances').length > 1,
checked: store.get('automaticSwitching'),
click: () => {
store.set("automaticSwitching", !store.get("automaticSwitching"));
store.set('automaticSwitching', !store.get('automaticSwitching'));
},
},
}
);
} else {
instancesMenu.push({ label: "Not Connected...", enabled: false });
instancesMenu.push({ label: 'Not Connected...', enabled: false });
}
return Menu.buildFromTemplate([
{
label: "Show/Hide Window",
visible: process.platform === "linux",
label: 'Show/Hide Window',
visible: process.platform === 'linux',
click: () => {
if (window.isVisible()) window.hide();
else showWindow();
if (window.isVisible()) {
window.hide();
} else {
showWindow();
}
},
},
{
visible: process.platform === "linux",
type: "separator",
visible: process.platform === 'linux',
type: 'separator',
},
...instancesMenu,
{
type: "separator",
type: 'separator',
},
{
label: "Hover to Show",
visible: process.platform !== "linux" && !store.get("detachedMode"),
enabled: !store.get("detachedMode"),
type: "checkbox",
checked: !store.get("disableHover"),
label: 'Hover to Show',
visible: process.platform !== 'linux' && !store.get('detachedMode'),
enabled: !store.get('detachedMode'),
type: 'checkbox',
checked: !store.get('disableHover'),
click: () => {
store.set("disableHover", !store.get("disableHover"));
store.set('disableHover', !store.get('disableHover'));
},
},
{
label: "Stay on Top",
type: "checkbox",
checked: store.get("stayOnTop"),
label: 'Stay on Top',
type: 'checkbox',
checked: store.get('stayOnTop'),
click: () => {
store.set("stayOnTop", !store.get("stayOnTop"));
window.setAlwaysOnTop(store.get("stayOnTop"));
if (window.isAlwaysOnTop()) showWindow();
store.set('stayOnTop', !store.get('stayOnTop'));
window.setAlwaysOnTop(store.get('stayOnTop'));
if (window.isAlwaysOnTop()) {
showWindow();
}
},
},
{
label: "Start at Login",
type: "checkbox",
label: 'Start at Login',
type: 'checkbox',
checked: autostartEnabled,
click: () => {
if (autostartEnabled) autoLauncher.disable();
else autoLauncher.enable();
if (autostartEnabled) {
autoLauncher.disable();
} else {
autoLauncher.enable();
}
checkAutoStart();
},
},
{
label: `Enable Shortcut`,
type: "checkbox",
accelerator: "CommandOrControl+Alt+X",
checked: store.get("shortcutEnabled"),
label: 'Enable Shortcut',
type: 'checkbox',
accelerator: 'CommandOrControl+Alt+X',
checked: store.get('shortcutEnabled'),
click: () => {
store.set("shortcutEnabled", !store.get("shortcutEnabled"));
if (store.get("shortcutEnabled")) registerKeyboardShortcut();
else unregisterKeyboardShortcut();
store.set('shortcutEnabled', !store.get('shortcutEnabled'));
if (store.get('shortcutEnabled')) {
registerKeyboardShortcut();
} else {
unregisterKeyboardShortcut();
}
},
},
{
type: "separator",
type: 'separator',
},
{
label: "Use detached Window",
type: "checkbox",
checked: store.get("detachedMode"),
label: 'Use detached Window',
type: 'checkbox',
checked: store.get('detachedMode'),
click: () => {
store.set("detachedMode", !store.get("detachedMode"));
store.set('detachedMode', !store.get('detachedMode'));
window.hide();
createMainWindow(store.get("detachedMode"));
createMainWindow(store.get('detachedMode'));
},
},
{
label: "Use Fullscreen",
type: "checkbox",
checked: store.get("fullScreen"),
accelerator: "CommandOrControl+Alt+Return",
label: 'Use Fullscreen',
type: 'checkbox',
checked: store.get('fullScreen'),
accelerator: 'CommandOrControl+Alt+Return',
click: () => {
toggleFullScreen();
},
},
{
type: "separator",
type: 'separator',
},
{
label: `v${app.getVersion()}`,
enabled: false,
},
{
label: "Automatic Updates",
type: "checkbox",
checked: store.get("autoUpdate"),
label: 'Automatic Updates',
type: 'checkbox',
checked: store.get('autoUpdate'),
click: () => {
store.set("autoUpdate", !store.get("autoUpdate"));
store.set('autoUpdate', !store.get('autoUpdate'));
},
},
{
label: "Open on github.com",
label: 'Open on github.com',
click: () => {
shell.openExternal("https://github.com/mrvnklm/homeassistant-desktop");
shell.openExternal('https://github.com/iprodanovbg/homeassistant-desktop');
},
},
{
type: "separator",
type: 'separator',
},
{
label: "Reload Window",
label: 'Reload Window',
click: () => {
window.reload();
window.show();
@@ -354,12 +372,12 @@ const getMenu = () => {
},
},
{
label: "Reset Application...",
label: 'Reset Application...',
click: () => {
dialog
.showMessageBox({
message: "Are you sure you want to reset Home Assistant Desktop?",
buttons: ["Reset Everything!", "Reset Windows", "Cancel"],
message: 'Are you sure you want to reset Home Assistant Desktop?',
buttons: ['Reset Everything!', 'Reset Windows', 'Cancel'],
})
.then((res) => {
if (res.response === 0) {
@@ -369,12 +387,13 @@ const getMenu = () => {
app.relaunch();
app.exit();
}
if (res.response === 1) {
store.delete("windowSizeDetached");
store.delete("windowSize");
store.delete("windowPosition");
store.delete("fullScreen");
store.delete("detachedMode");
store.delete('windowSizeDetached');
store.delete('windowSize');
store.delete('windowPosition');
store.delete('fullScreen');
store.delete('detachedMode');
app.relaunch();
app.exit();
}
@@ -382,19 +401,19 @@ const getMenu = () => {
},
},
{
type: "separator",
type: 'separator',
},
{
label: "Quit",
label: 'Quit',
click: () => {
forceQuit = true;
app.quit();
},
},
]);
};
}
const createMainWindow = (show = false) => {
function createMainWindow(show = false) {
window = new BrowserWindow({
width: 420,
height: 420,
@@ -411,87 +430,103 @@ const createMainWindow = (show = false) => {
// window.webContents.openDevTools();
window.loadURL(indexFile);
// open extenal links in default browser
window.webContents.on("new-window", function (e, url) {
e.preventDefault();
require("electron").shell.openExternal(url);
// open external links in default browser
window.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url);
return { action: 'deny' };
});
// hide scrollbar
window.webContents.on("did-finish-load", function () {
window.webContents.insertCSS(
"::-webkit-scrollbar { display: none; } body { -webkit-user-select: none; }"
);
window.webContents.on('did-finish-load', function () {
window.webContents.insertCSS('::-webkit-scrollbar { display: none; } body { -webkit-user-select: none; }');
if (store.get("detachedMode") && process.platform === "darwin") {
window.webContents.insertCSS("body { -webkit-app-region: drag; }");
if (store.get('detachedMode') && process.platform === 'darwin') {
window.webContents.insertCSS('body { -webkit-app-region: drag; }');
}
// let code = `document.addEventListener("mousemove", () => { ipcRenderer.send("mousemove"); });`;
// let code = `document.addEventListener('mousemove', () => { ipcRenderer.send('mousemove'); });`;
// window.webContents.executeJavaScript(code);
});
if (store.get("detachedMode")) {
if (store.has("windowPosition"))
window.setSize(...store.get("windowSizeDetached"));
else store.set("windowPosition", window.getPosition());
if (store.has("windowSizeDetached"))
window.setPosition(...store.get("windowPosition"));
else store.set("windowSizeDetached", window.getSize());
if (store.get('detachedMode')) {
if (store.has('windowPosition')) {
window.setSize(...store.get('windowSizeDetached'));
} else {
if (store.has("windowSize")) window.setSize(...store.get("windowSize"));
else store.set("windowSize", window.getSize());
store.set('windowPosition', window.getPosition());
}
window.on("resize", (e) => {
// ignore resize event when using fullscreen mode
if (window.isFullScreen()) return e;
if (store.has('windowSizeDetached')) {
window.setPosition(...store.get('windowPosition'));
} else {
store.set('windowSizeDetached', window.getSize());
}
} else if (store.has('windowSize')) {
window.setSize(...store.get('windowSize'));
} else {
store.set('windowSize', window.getSize());
}
if (!store.get("disableHover") || resizeEvent) {
store.set("disableHover", true);
window.on('resize', (e) => {
// ignore resize event when using fullscreen mode
if (window.isFullScreen()) {
return e;
}
if (!store.get('disableHover') || resizeEvent) {
store.set('disableHover', true);
resizeEvent = e;
setTimeout(() => {
if (resizeEvent === e) {
store.set("disableHover", false);
store.set('disableHover', false);
resizeEvent = false;
}
}, 600);
}
if (store.get("detachedMode")) {
store.set("windowSizeDetached", window.getSize());
if (store.get('detachedMode')) {
store.set('windowSizeDetached', window.getSize());
} else {
if (process.platform !== "linux") changePosition();
if (process.platform !== 'linux') {
changePosition();
}
store.set("windowSize", window.getSize());
store.set('windowSize', window.getSize());
}
});
window.on("move", () => {
if (store.get("detachedMode")) {
store.set("windowPosition", window.getPosition());
window.on('move', () => {
if (store.get('detachedMode')) {
store.set('windowPosition', window.getPosition());
}
});
window.on("close", (e) => {
window.on('close', (e) => {
if (!forceQuit) {
window.hide();
e.preventDefault();
}
});
window.on("blur", () => {
if (!store.get("detachedMode") && !window.isAlwaysOnTop()) window.hide();
window.on('blur', () => {
if (!store.get('detachedMode') && !window.isAlwaysOnTop()) {
window.hide();
}
});
window.setAlwaysOnTop(!!store.get("stayOnTop"));
if (window.isAlwaysOnTop() || show) showWindow();
window.setAlwaysOnTop(!!store.get('stayOnTop'));
toggleFullScreen(!!store.get("fullScreen"));
};
if (window.isAlwaysOnTop() || show) {
showWindow();
}
toggleFullScreen(!!store.get('fullScreen'));
}
function showWindow() {
if (!store.get('detachedMode')) {
changePosition();
}
const showWindow = () => {
if (!store.get("detachedMode")) changePosition();
if (!window.isVisible()) {
window.setVisibleOnAllWorkspaces(true); // put the window on all screens
window.show();
@@ -500,160 +535,189 @@ const showWindow = () => {
}
};
const createTray = () => {
function createTray() {
tray = new Tray(
["win32", "linux"].includes(process.platform)
? `${__dirname}/assets/IconWin.png`
: `${__dirname}/assets/IconTemplate.png`
['win32', 'linux'].includes(process.platform) ? `${__dirname}/assets/IconWin.png` : `${__dirname}/assets/IconTemplate.png`,
);
tray.on("click", () => {
if (window.isVisible()) window.hide();
else showWindow();
tray.on('click', () => {
if (window.isVisible()) {
window.hide();
} else {
showWindow();
}
});
tray.on("right-click", () => {
if (!store.get("detachedMode")) window.hide();
tray.on('right-click', () => {
if (!store.get('detachedMode')) {
window.hide();
}
tray.popUpContextMenu(getMenu());
});
let timer = undefined;
tray.on("mouse-move", (e) => {
if (
store.get("detachedMode") ||
window.isAlwaysOnTop() ||
store.get("disableHover")
) {
tray.on('mouse-move', () => {
if (store.get('detachedMode') || window.isAlwaysOnTop() || store.get('disableHover')) {
return;
}
if (!window.isVisible()) {
showWindow();
}
if (timer) clearTimeout(timer);
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
let mousePos = screen.getCursorScreenPoint();
let trayBounds = tray.getBounds();
if (
!(
mousePos.x >= trayBounds.x &&
mousePos.x <= trayBounds.x + trayBounds.width
) ||
!(
mousePos.y >= trayBounds.y &&
mousePos.y <= trayBounds.y + trayBounds.height
)
!(mousePos.x >= trayBounds.x && mousePos.x <= trayBounds.x + trayBounds.width) ||
!(mousePos.y >= trayBounds.y && mousePos.y <= trayBounds.y + trayBounds.height)
) {
setWindowFocusTimer();
}
}, 100);
});
};
}
const setWindowFocusTimer = () => {
let timer = setTimeout(() => {
function setWindowFocusTimer() {
setTimeout(() => {
let mousePos = screen.getCursorScreenPoint();
let windowPosition = window.getPosition();
let windowSize = window.getSize();
if (
!resizeEvent &&
(!(
mousePos.x >= windowPosition[0] &&
mousePos.x <= windowPosition[0] + windowSize[0]
) ||
!(
mousePos.y >= windowPosition[1] &&
mousePos.y <= windowPosition[1] + windowSize[1]
))
(
!(mousePos.x >= windowPosition[ 0 ] && mousePos.x <= windowPosition[ 0 ] + windowSize[ 0 ]) ||
!(mousePos.y >= windowPosition[ 1 ] && mousePos.y <= windowPosition[ 1 ] + windowSize[ 1 ])
)
) {
window.hide();
} else {
setWindowFocusTimer();
}
}, 110);
};
}
app.on("ready", async () => {
checkAutoStart();
function toggleFullScreen(mode = !window.isFullScreen()) {
store.set('fullScreen', mode);
window.setFullScreen(mode);
if (mode) {
window.setAlwaysOnTop(true);
} else {
window.setAlwaysOnTop(store.get('stayOnTop'));
}
}
function currentInstance(url = null) {
if (url) {
store.set('currentInstance', store.get('allInstances').indexOf(url));
}
if (store.has('currentInstance')) {
return store.get('allInstances')[ store.get('currentInstance') ];
}
return false;
}
function addInstance(url) {
if (!store.has('allInstances')) {
store.set('allInstances', []);
}
let instances = store.get('allInstances');
if (instances.find((e) => e === url)) {
currentInstance(url);
return;
}
// active hover by default after adding first instance
if (!instances.length) {
store.set('disableHover', false);
}
instances.push(url);
store.set('allInstances', instances);
currentInstance(url);
}
function showError(isError) {
if (!isError && window.webContents.getURL().includes('error.html')) {
window.loadURL(indexFile);
}
if (isError && currentInstance() && !window.webContents.getURL().includes('error.html')) {
window.loadURL(errorFile);
}
}
app.on('ready', async () => {
useAutoUpdater();
checkAutoStart();
createTray();
// workaround for initial window misplacement due to traybounds being incorrect
while (tray.getBounds().x === 0 && process.uptime() <= 1) {
await delay(15);
}
createMainWindow(!store.has("currentInstance"));
createMainWindow(!store.has('currentInstance'));
if (process.platform === 'linux') {
tray.setContextMenu(getMenu());
}
if (process.platform === "linux") tray.setContextMenu(getMenu());
startAvailabilityCheck();
// register shortcut
if (store.get("shortcutEnabled")) registerKeyboardShortcut();
if (store.get('shortcutEnabled')) {
registerKeyboardShortcut();
}
globalShortcut.register("CommandOrControl+Alt+Return", () => {
globalShortcut.register('CommandOrControl+Alt+Return', () => {
toggleFullScreen();
});
// disable hover for first start
if (!store.has("currentInstance")) store.set("disableHover", true);
if (!store.has('currentInstance')) {
store.set('disableHover', true);
}
// enable auto update by default
if (!store.has("autoUpdate")) store.set("autoUpdate", true);
if (!store.has('autoUpdate')) {
store.set('autoUpdate', true);
}
});
app.on("will-quit", () => {
app.on('will-quit', () => {
unregisterKeyboardShortcut();
});
const toggleFullScreen = (mode = !window.isFullScreen()) => {
store.set("fullScreen", mode);
window.setFullScreen(mode);
if (mode) window.setAlwaysOnTop(true);
else window.setAlwaysOnTop(store.get("stayOnTop"));
};
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
const currentInstance = (url = null) => {
ipcMain.on('get-instances', (event) => {
event.reply('get-instances', store.get('allInstances') || []);
});
ipcMain.on('ha-instance', (event, url) => {
if (url) {
store.set("currentInstance", store.get("allInstances").indexOf(url));
}
if (store.has("currentInstance")) {
return store.get("allInstances")[store.get("currentInstance")];
}
return false;
};
const addInstance = (url) => {
if (!store.has("allInstances")) store.set("allInstances", []);
let instances = store.get("allInstances");
if (instances.find((e) => e === url)) {
currentInstance(url);
return;
addInstance(url);
}
// active hover by default after adding first instance
if (!instances.length) store.set("disableHover", false);
instances.push(url);
store.set("allInstances", instances);
currentInstance(url);
};
const showError = (isError) => {
if (!isError && window.webContents.getURL().includes("error.html"))
window.loadURL(indexFile);
if (
isError &&
currentInstance() &&
!window.webContents.getURL().includes("error.html")
)
window.loadURL(errorFile);
};
ipcMain.on("get-instances", (event) => {
event.reply("get-instances", store.get("allInstances") || []);
});
ipcMain.on("ha-instance", (event, url) => {
if (url) addInstance(url);
if (currentInstance()) event.reply("ha-instance", currentInstance());
if (currentInstance()) {
event.reply('ha-instance', currentInstance());
}
});

174
package-lock.json generated
View File

@@ -415,6 +415,11 @@
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"array-flatten": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
"integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ=="
},
"asar": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz",
@@ -510,6 +515,19 @@
"bluebird": "^3.5.5"
}
},
"bonjour": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
"integrity": "sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==",
"requires": {
"array-flatten": "^2.1.0",
"deep-equal": "^1.0.1",
"dns-equal": "^1.0.0",
"dns-txt": "^2.0.2",
"multicast-dns": "^6.0.1",
"multicast-dns-service-types": "^1.1.0"
}
},
"boolean": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
@@ -602,6 +620,11 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
"buffer-indexof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
"integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g=="
},
"builder-util": {
"version": "23.3.3",
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-23.3.3.tgz",
@@ -697,6 +720,15 @@
}
}
},
"call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
}
},
"camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
@@ -954,6 +986,19 @@
"mimic-response": "^1.0.0"
}
},
"deep-equal": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
"integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
"requires": {
"is-arguments": "^1.0.4",
"is-date-object": "^1.0.1",
"is-regex": "^1.0.4",
"object-is": "^1.0.1",
"object-keys": "^1.1.1",
"regexp.prototype.flags": "^1.2.0"
}
},
"deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
@@ -970,8 +1015,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
"integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
"dev": true,
"optional": true,
"requires": {
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
@@ -1083,6 +1126,28 @@
"verror": "^1.10.0"
}
},
"dns-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
"integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg=="
},
"dns-packet": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
"integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
"requires": {
"ip": "^1.1.0",
"safe-buffer": "^5.0.1"
}
},
"dns-txt": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
"integrity": "sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ==",
"requires": {
"buffer-indexof": "^1.0.0"
}
},
"dot-prop": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
@@ -1511,9 +1576,12 @@
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true,
"optional": true
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"functions-have-names": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="
},
"get-caller-file": {
"version": "2.0.5",
@@ -1525,8 +1593,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
"dev": true,
"optional": true,
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
@@ -1657,8 +1723,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"optional": true,
"requires": {
"function-bind": "^1.1.1"
}
@@ -1673,8 +1737,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
"integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
"dev": true,
"optional": true,
"requires": {
"get-intrinsic": "^1.1.1"
}
@@ -1682,9 +1744,15 @@
"has-symbols": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
"dev": true,
"optional": true
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
},
"has-tostringtag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"requires": {
"has-symbols": "^1.0.2"
}
},
"has-yarn": {
"version": "2.1.0",
@@ -1789,6 +1857,20 @@
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
"ip": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
"integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg=="
},
"is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
}
},
"is-ci": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
@@ -1798,6 +1880,14 @@
"ci-info": "^3.2.0"
}
},
"is-date-object": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
"requires": {
"has-tostringtag": "^1.0.0"
}
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@@ -1831,6 +1921,15 @@
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
"dev": true
},
"is-regex": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
}
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
@@ -2073,6 +2172,20 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"multicast-dns": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
"integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
"requires": {
"dns-packet": "^1.3.1",
"thunky": "^1.0.2"
}
},
"multicast-dns-service-types": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
"integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ=="
},
"node-addon-api": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz",
@@ -2097,12 +2210,19 @@
"pify": "^3.0.0"
}
},
"object-is": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
"integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
}
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true,
"optional": true
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
},
"once": {
"version": "1.4.0",
@@ -2282,6 +2402,16 @@
"lazy-val": "^1.0.4"
}
},
"regexp.prototype.flags": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
"integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3",
"functions-have-names": "^1.2.2"
}
},
"registry-auth-token": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz",
@@ -2353,6 +2483,11 @@
"tslib": "^2.1.0"
}
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
@@ -2588,6 +2723,11 @@
}
}
},
"thunky": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="
},
"tmp": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",

View File

@@ -21,6 +21,7 @@
},
"dependencies": {
"auto-launch": "^5.0.5",
"bonjour": "^3.5.0",
"electron-log": "^4.4.8",
"electron-store": "^8.1.0",
"electron-traywindow-positioner": "^1.1.1",

View File

@@ -7,6 +7,7 @@
height: 80px;
margin: 0 auto;
}
.success-checkmark .check-icon {
width: 80px;
height: 80px;
@@ -15,6 +16,7 @@
box-sizing: content-box;
border: 4px solid #4caf50;
}
.success-checkmark .check-icon::before {
top: 3px;
left: -2px;
@@ -22,6 +24,7 @@
transform-origin: 100% 50%;
border-radius: 100px 0 0 100px;
}
.success-checkmark .check-icon::after {
top: 0;
left: 30px;
@@ -30,6 +33,7 @@
border-radius: 0 100px 100px 0;
animation: rotate-circle 4.25s ease-in;
}
.success-checkmark .check-icon::before,
.success-checkmark .check-icon::after {
content: "";
@@ -38,6 +42,7 @@
background: #ffffff;
transform: rotate(-45deg);
}
.success-checkmark .check-icon .icon-line {
height: 5px;
background-color: #4caf50;
@@ -46,6 +51,7 @@
position: absolute;
z-index: 10;
}
.success-checkmark .check-icon .icon-line.line-tip {
top: 46px;
left: 14px;
@@ -53,6 +59,7 @@
transform: rotate(45deg);
animation: icon-line-tip 0.75s;
}
.success-checkmark .check-icon .icon-line.line-long {
top: 38px;
right: 8px;
@@ -60,6 +67,7 @@
transform: rotate(-45deg);
animation: icon-line-long 0.75s;
}
.success-checkmark .check-icon .icon-circle {
top: -4px;
left: -4px;
@@ -71,6 +79,7 @@
box-sizing: content-box;
border: 4px solid rgba(76, 175, 80, 0.5);
}
.success-checkmark .check-icon .icon-fix {
top: 8px;
width: 5px;
@@ -96,6 +105,7 @@
transform: rotate(-405deg);
}
}
@keyframes icon-line-tip {
0% {
width: 0;
@@ -123,6 +133,7 @@
top: 45px;
}
}
@keyframes icon-line-long {
0% {
width: 0;
@@ -136,7 +147,7 @@
}
84% {
width: 55px;
right: 0px;
right: 0;
top: 35px;
}
100% {

View File

@@ -3,27 +3,33 @@ svg {
display: block;
margin: 40px auto 0;
}
.path {
stroke-dasharray: 1000;
stroke-dashoffset: 0;
}
.path.circle {
-webkit-animation: dash 0.9s ease-in-out;
animation: dash 0.9s ease-in-out;
}
.path.line {
stroke-dashoffset: 1000;
-webkit-animation: dash 0.9s 0.35s ease-in-out forwards;
animation: dash 0.9s 0.35s ease-in-out forwards;
}
p {
text-align: center;
margin: 20px 0 60px;
font-size: 1.1em;
}
p.error {
color: #d06079;
}
@-webkit-keyframes dash {
0% {
stroke-dashoffset: 1000;
@@ -32,6 +38,7 @@ p.error {
stroke-dashoffset: 0;
}
}
@keyframes dash {
0% {
stroke-dashoffset: 1000;

View File

@@ -44,8 +44,7 @@ body {
text-overflow: ellipsis;
color: rgb(var(--pure-material-onprimary-rgb, 255, 255, 255));
background-color: rgb(var(--pure-material-primary-rgb, 3, 169, 244));
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),
0 1px 5px 0 rgba(0, 0, 0, 0.12);
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
font-family: var(
--pure-material-font,
"Roboto",
@@ -100,8 +99,7 @@ body {
/* Hover, Focus */
.pure-material-button-contained:hover,
.pure-material-button-contained:focus {
box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),
0 1px 10px 0 rgba(0, 0, 0, 0.12);
box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
}
.pure-material-button-contained:hover::before {
@@ -118,8 +116,7 @@ body {
/* Active */
.pure-material-button-contained:active {
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.pure-material-button-contained:active::after {
@@ -190,7 +187,7 @@ p {
input {
background: none;
font-size: 18px;
padding: 10px 0px 10px 0px;
padding: 10px 0 10px 0;
display: block;
width: 320px;
border: none;
@@ -234,9 +231,9 @@ label {
content: "";
height: 2px;
width: 0;
bottom: 0px;
bottom: 0;
position: absolute;
background: #03a9f4;
transition: 300ms ease all;
left: 0%;
left: 0;
}

View File

@@ -1,65 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<title>Home Assistant</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,user-scalable=no" />
<link href="assets/style.css" rel="stylesheet" />
<link href="assets/error.css" rel="stylesheet" />
</head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,user-scalable=no"/>
<link href="assets/style.css" rel="stylesheet"/>
<link href="assets/error.css" rel="stylesheet"/>
</head>
<body>
<div class="vertical-center">
<body>
<div class="vertical-center">
<div class="content">
<div class="center">
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 130.2 130.2"
>
<circle
class="path circle"
fill="none"
stroke="#D06079"
stroke-width="6"
stroke-miterlimit="10"
cx="65.1"
cy="65.1"
r="62.1"
/>
<line
class="path line"
fill="none"
stroke="#D06079"
stroke-width="6"
stroke-linecap="round"
stroke-miterlimit="10"
x1="34.4"
y1="37.9"
x2="95.8"
y2="92.3"
/>
<line
class="path line"
fill="none"
stroke="#D06079"
stroke-width="6"
stroke-linecap="round"
stroke-miterlimit="10"
x1="95.8"
y1="38"
x2="34.4"
y2="92.2"
/>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 130.2 130.2">
<circle class="path circle" fill="none" stroke="#D06079" stroke-width="6" stroke-miterlimit="10" cx="65.1" cy="65.1" r="62.1"/>
<line class="path line" fill="none" stroke="#D06079" stroke-width="6" stroke-linecap="round" stroke-miterlimit="10" x1="34.4"
y1="37.9" x2="95.8" y2="92.3"/>
<line class="path line" fill="none" stroke="#D06079" stroke-width="6" stroke-linecap="round" stroke-miterlimit="10" x1="95.8"
y1="38" x2="34.4" y2="92.2"/>
</svg>
</div>
<div class="center">
<p class="error">
Home Assistant instance is not available, please check your
connection.
Home Assistant instance is not available, please check your connection.
</p>
</div>
</div>
</div>
</body>
</div>
</body>
</html>

View File

@@ -8,49 +8,60 @@
<link href="assets/style.css" rel="stylesheet" />
<link href="assets/checkmark.css" rel="stylesheet" />
<script>
const { ipcRenderer } = require("electron");
const { ipcRenderer } = require('electron');
const bonjour = require('bonjour')()
function showInstance(url) {
document.getElementById('availableInstancesContainer').style.display = "block"
const button = document.createElement("button")
button.onclick = () => addInstance(url)
button.classList.add("pure-material-button-contained")
button.textContent = url
document.getElementById('availableInstances').append(button)
if (url === '') {
return;
}
document.addEventListener("DOMContentLoaded", function (event) {
document.getElementById('availableInstancesContainer').style.display = 'block';
const button = document.createElement('button');
button.onclick = () => addInstance(url);
button.classList.add('pure-material-button-contained');
button.textContent = url;
document.getElementById('availableInstances').append(button);
}
document.addEventListener('DOMContentLoaded', function () {
setTimeout(() => document.getElementById('url').focus(), 300);
});
ipcRenderer.send("get-instances");
ipcRenderer.on("get-instances", (event, result) => {
let instances = result
ipcRenderer.send('get-instances');
ipcRenderer.on('get-instances', (event, result) => {
let instances = result;
bonjour.find({ type: 'home-assistant' }, instance => {
if (instances.indexOf(instance.txt.internal_url) === -1) showInstance(instance.txt.internal_url)
if (instances.indexOf(instance.txt.external_url) === -1) showInstance(instance.txt.external_url)
bonjour.find({type: 'home-assistant'}, instance => {
if (instance.txt.internal_url && instances.indexOf(instance.txt.internal_url) === -1) {
showInstance(instance.txt.internal_url);
}
if (instance.txt.external_url && instances.indexOf(instance.txt.external_url) === -1) {
showInstance(instance.txt.external_url);
}
})
})
function addInstance(url) {
ipcRenderer.send("ha-instance", url);
ipcRenderer.send('ha-instance', url);
}
ipcRenderer.send("ha-instance");
ipcRenderer.send('ha-instance');
let showCheckmark = false;
ipcRenderer.on("ha-instance", function (event, url) {
ipcRenderer.on('ha-instance', function (event, url) {
if (showCheckmark) {
document
.getElementById("check-wrapper")
.getElementById('check-wrapper')
.addEventListener(
"animationend",
'animationend',
() => (window.location.href = url)
);
} else window.location.href = url;
} else {
window.location.href = url;
}
});
function isValidUrl(string) {
@@ -59,41 +70,46 @@
} catch (_) {
return false;
}
return true;
}
function checkUrl() {
const url = document.getElementById("url").value;
const url = document.getElementById('url').value;
if (!isValidUrl(url)) {
return;
}
fetch(url + "/auth/providers")
fetch(`${url}/auth/providers`)
.then(response => response.text())
.then(data => {
if (!data.includes('homeassistant')) return;
document.getElementById("url").value = url;
document.getElementById("url").disabled = true;
document.getElementById("check-wrapper").style.display = "block";
document.getElementById("url-wrapper").style.display = "none";
if (!data.includes('homeassistant')) {
return;
}
document.getElementById('url').value = url;
document.getElementById('url').disabled = true;
document.getElementById('check-wrapper').style.display = 'block';
document.getElementById('url-wrapper').style.display = 'none';
showCheckmark = true;
ipcRenderer.send("ha-instance", url);
}).catch((err) => { });
ipcRenderer.send('ha-instance', url);
}).catch((_) => {
});
}
function showPlaceholder(status = true) {
if (status) document.getElementById("url").placeholder = 'e.g. http://hassio.local:8123';
else document.getElementById("url").placeholder = '';
if (status) document.getElementById('url').placeholder = 'e.g. http://hassio.local:8123';
else document.getElementById('url').placeholder = '';
}
</script>
</head>
<body>
<div class="container">
<div class="container">
<div class="content">
<div class="center header">
<img src="assets/favicon.png" height="52" /> Home Assistant
<img src="assets/favicon.png" height="52"/> Home Assistant
</div>
<div id="availableInstancesContainer" style="display:none;">
<div class="center">
@@ -121,7 +137,7 @@
onkeyup="checkUrl()" />
<span class="highlight"></span>
<span class="bar"></span>
<label>Home Assistant URL</label>
<label for="url">Home Assistant URL</label>
</div>
</div>
@@ -131,7 +147,7 @@
</p>
</div>
</div>
</div>
</div>
</body>
</html>