diff --git a/resources/index.css b/resources/index.css
new file mode 100644
index 0000000..3cbb146
--- /dev/null
+++ b/resources/index.css
@@ -0,0 +1,146 @@
+body {
+ display: flex;
+ flex-direction: row;
+}
+
+#service-selector {
+ flex-grow: 1;
+ display: block;
+ margin: 0;
+ padding: 0;
+}
+
+*:focus {
+ outline-color: rgb(118, 93, 176);
+}
+
+#navigation button {
+ display: block;
+ width: 100%;
+ padding: 16px;
+ margin: 0;
+ height: 72px;
+
+ color: #fff;
+ border: 0;
+ background: transparent;
+
+ cursor: pointer;
+}
+
+#navigation button img {
+ width: 32px;
+}
+
+#navigation button i {
+ font-size: 32px;
+}
+
+#service-selector li {
+ position: relative;
+}
+
+#service-selector li.active button {
+ position: relative;
+ background-color: #fff2;
+}
+
+#service-selector li.active button::before {
+ content: "";
+ display: block;
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 100%;
+ border-left: 4px solid #ffffff2e;
+}
+
+#service-selector li.loaded::after {
+ content: "";
+ position: absolute;
+ top: 50%;
+ right: 2px;
+ transform: translateY(-50%);
+ width: 4px;
+ height: 4px;
+
+ background-color: #fff;
+ border-radius: 100%;
+}
+
+#navigation button:hover {
+ background-color: #fff3;
+}
+
+#history {
+ padding: 8px;
+}
+
+#history button {
+ display: inline;
+ width: 24px;
+ height: 24px;
+ padding: initial;
+ font-size: 12px;
+
+ background: #fff1;
+ border: 1px solid #fff4;
+ border-radius: 72px;
+
+ color: #fff;
+ cursor: pointer;
+}
+
+#history button i {
+ font-size: inherit;
+}
+
+#history button.disabled {
+ color: #888;
+ border: transparent;
+ background: transparent;
+ cursor: initial;
+}
+
+#history button:focus,
+#history button:hover {
+ outline: none;
+ border-color: #fff9;
+}
+
+#history button:hover:not(.disabled) {
+ outline: none;
+ background-color: #fff2;
+}
+
+#history button:active:not(.disabled) {
+ background-color: #fff4;
+}
+
+#navigation #add-button:not(:hover) {
+ opacity: 0.75;
+}
+
+#services {
+ position: relative;
+ flex-grow: 1;
+}
+
+#services > *:not(.loader) {
+ height: 100%;
+}
+
+#services > :not(.active):not(.loader) {
+ display: none;
+}
+
+#services > .loader {
+ width: 64px;
+ height: 64px;
+
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ z-index: -1;
+}
\ No newline at end of file
diff --git a/resources/index.html b/resources/index.html
index ad4fe07..c5d3d06 100644
--- a/resources/index.html
+++ b/resources/index.html
@@ -1,144 +1,14 @@
+
Tabs
-
-
+
@@ -331,6 +201,10 @@
} else {
nav.insertBefore(li, nextNavButton);
}
+
+ if (service.autoLoad) {
+ loadService(index, service);
+ }
}
document.addEventListener('DOMContentLoaded', () => {
@@ -347,34 +221,7 @@
function setActiveService(serviceId) {
let currentService = services[serviceId];
process.nextTick(() => {
- // Load service if not loaded yet
- if (!currentService.view) {
- currentService.view = document.createElement('webview');
- currentService.view.setAttribute('src', currentService.url);
- currentService.view.setAttribute('partition', 'persist:service_' + currentService.partition);
- currentService.view.setAttribute('autosize', "true");
-
- document.querySelector('#services').appendChild(currentService.view);
- currentService.view.addEventListener('dom-ready', event => {
- currentService.viewReady = true;
- updateNavigation();
- });
- currentService.view.addEventListener('page-favicon-updated', event => {
- console.debug('Loaded favicons for', currentService.name, event.favicons);
- if (event.favicons.length > 0) {
- ipcRenderer.send('setServiceFavicon', serviceId, event.favicons[0]);
- if (currentService.useFavicon) {
- const img = document.createElement('img');
- img.src = event.favicons[0];
- img.alt = currentService.name;
- img.onload = () => {
- currentService.li.button.innerHTML = '';
- currentService.li.button.appendChild(img);
- };
- }
- }
- });
- }
+ loadService(serviceId, currentService);
// Hide previous service
if (services[selectedService] && services[selectedService].view) {
@@ -392,6 +239,39 @@
});
}
+ function loadService(serviceId, service) {
+ // Load service if not loaded yet
+ if (!service.view) {
+ service.view = document.createElement('webview');
+ service.view.setAttribute('src', service.url);
+ service.view.setAttribute('partition', 'persist:service_' + service.partition);
+ service.view.setAttribute('autosize', "true");
+
+ document.querySelector('#services').appendChild(service.view);
+ service.view.addEventListener('dom-ready', () => {
+ service.viewReady = true;
+ updateNavigation();
+ });
+ service.view.addEventListener('page-favicon-updated', event => {
+ console.debug('Loaded favicons for', service.name, event.favicons);
+ if (event.favicons.length > 0) {
+ ipcRenderer.send('setServiceFavicon', serviceId, event.favicons[0]);
+ if (service.useFavicon) {
+ const img = document.createElement('img');
+ img.src = event.favicons[0];
+ img.alt = service.name;
+ img.onload = () => {
+ service.li.button.innerHTML = '';
+ service.li.button.appendChild(img);
+ };
+ }
+ }
+ });
+
+ service.li.classList.add('loaded');
+ }
+ }
+
function updateNavigation() {
console.debug('Updating navigation');
// Update active list element
diff --git a/resources/service-settings.html b/resources/service-settings.html
index ed2d04b..447a447 100644
--- a/resources/service-settings.html
+++ b/resources/service-settings.html
@@ -134,6 +134,11 @@
+
+
+
+
+
Service icon
@@ -216,27 +221,6 @@
});
});
- function loadServiceValues() {
- if (!service || !isImageCheckbox) {
- return;
- }
-
- document.getElementById('name').value = service.name;
- document.getElementById('url').value = service.url;
- document.getElementById('use-favicon').checked = service.useFavicon;
- isImageCheckbox.checked = service.isImage;
- if (service.isImage) {
- iconUrlField.value = service.icon;
- } else {
- builtInIconSearchField.value = service.icon;
- updateIconSearchResults();
- const icon = Array.from(iconSelect.querySelectorAll('label')).find(i => i.dataset.icon === service.icon);
- if (icon) {
- selectIcon(icon);
- }
- }
- }
-
function updateIconSearchResults() {
const searchStr = builtInIconSearchField.value;
iconSelect.childNodes.forEach(c => {
@@ -298,6 +282,50 @@
}
}
+ function loadServiceValues() {
+ if (!service || !isImageCheckbox) {
+ return;
+ }
+
+ document.getElementById('name').value = service.name;
+ document.getElementById('url').value = service.url;
+ document.getElementById('use-favicon').checked = service.useFavicon;
+ document.getElementById('auto-load').checked = service.autoLoad;
+ isImageCheckbox.checked = service.isImage;
+ if (service.isImage) {
+ iconUrlField.value = service.icon;
+ } else {
+ builtInIconSearchField.value = service.icon;
+ updateIconSearchResults();
+ const icon = Array.from(iconSelect.querySelectorAll('label')).find(i => i.dataset.icon === service.icon);
+ if (icon) {
+ selectIcon(icon);
+ }
+ }
+ }
+
+ function save() {
+ const formData = new FormData(document.querySelector('form'));
+ service.name = formData.get('name');
+ if (typeof service.partition !== 'string' || service.partition.length === 0) {
+ service.partition = service.name.replace(/ /g, '-');
+ service.partition = service.partition.replace(/[^a-zA-Z-_]/g, '');
+ }
+ service.url = formData.get('url');
+ service.isImage = formData.get('isImage') === 'on';
+ service.icon = formData.get('icon');
+ service.useFavicon = formData.get('useFavicon') === 'on';
+ service.autoLoad = formData.get('autoLoad') === 'on';
+
+
+ if (!isValid()) {
+ return;
+ }
+
+ ipcRenderer.send('saveService', serviceId, service);
+ remote.getCurrentWindow().close();
+ }
+
function isValid() {
if (typeof service.name !== 'string' || service.name.length === 0) {
console.log('Invalid name');
@@ -317,27 +345,6 @@
}
return true;
}
-
- function save() {
- const formData = new FormData(document.querySelector('form'));
- service.name = formData.get('name');
- if (typeof service.partition !== 'string' || service.partition.length === 0) {
- service.partition = service.name.replace(/ /g, '-');
- service.partition = service.partition.replace(/[^a-zA-Z-_]/g, '');
- }
- service.url = formData.get('url');
- service.isImage = formData.get('isImage') === 'on';
- service.icon = formData.get('icon');
- service.useFavicon = formData.get('useFavicon') === 'on';
-
-
- if (!isValid()) {
- return;
- }
-
- ipcRenderer.send('saveService', serviceId, service);
- remote.getCurrentWindow().close();
- }
\ No newline at end of file
diff --git a/src/Service.js b/src/Service.js
index d198c55..bf7bd0d 100644
--- a/src/Service.js
+++ b/src/Service.js
@@ -33,6 +33,7 @@ Service.requiredProperties = {
'isImage': null,
'url': null,
'useFavicon': true,
+ 'autoLoad': false,
};
export default Service;
\ No newline at end of file