Commit d7f073d5 authored by akiraohgaki's avatar akiraohgaki

Merge branch 'develop'

parents 998a9805 d4a06249
Pipeline #307 passed with stage
in 5 minutes and 20 seconds
...@@ -13,17 +13,16 @@ const isDebugMode = process.argv.includes('--debug'); ...@@ -13,17 +13,16 @@ const isDebugMode = process.argv.includes('--debug');
const previewpicDirectory = `${app.getPath('userData')}/previewpic`; const previewpicDirectory = `${app.getPath('userData')}/previewpic`;
const windowIcon = `${__dirname}/images/app-icons/ocs-store.png`; const windowIcon = `${__dirname}/images/app-icons/ocs-store.png`;
const indexFileUrl = `file://${__dirname}/index.html`; const indexFileUrl = `file://${__dirname}/index.html`;
const storeAppConfigStorage = 'application'; const appConfigStoreStorage = 'application';
let topWindow = null; let mainWindow = null;
let ocsManager = null; let ocsManager = null;
let ocsManagerUrl = ''; let ocsManagerUrl = '';
async function startOcsManager() { async function startOcsManager() {
return new Promise((resolve) => { return new Promise((resolve) => {
const resolveUrl = (data) => { const resolveOcsManagerUrl = (data) => {
const matches = data.toString() const matches = data.toString().match(/Websocket server started at: "(wss?:\/\/.+)"/);
.match(/Websocket server started at: "(wss?:\/\/.+)"/);
if (matches) { if (matches) {
ocsManagerUrl = matches[1]; ocsManagerUrl = matches[1];
resolve(true); resolve(true);
...@@ -35,14 +34,14 @@ async function startOcsManager() { ...@@ -35,14 +34,14 @@ async function startOcsManager() {
ocsManager.stdout.on('data', (data) => { ocsManager.stdout.on('data', (data) => {
console.log(`[${ocsManagerConfig.bin}] ${data}`); console.log(`[${ocsManagerConfig.bin}] ${data}`);
if (!ocsManagerUrl) { if (!ocsManagerUrl) {
resolveUrl(data); resolveOcsManagerUrl(data);
} }
}); });
ocsManager.stderr.on('data', (data) => { ocsManager.stderr.on('data', (data) => {
console.error(`[${ocsManagerConfig.bin}] ${data}`); console.error(`[${ocsManagerConfig.bin}] ${data}`);
if (!ocsManagerUrl) { if (!ocsManagerUrl) {
resolveUrl(data); resolveOcsManagerUrl(data);
} }
}); });
...@@ -66,13 +65,13 @@ function stopOcsManager() { ...@@ -66,13 +65,13 @@ function stopOcsManager() {
function createWindow() { function createWindow() {
const appConfigStore = new ElectronStore({ const appConfigStore = new ElectronStore({
name: storeAppConfigStorage, name: appConfigStoreStorage,
defaults: appConfig.defaults defaults: appConfig.defaults
}); });
const windowBounds = appConfigStore.get('windowBounds'); const windowBounds = appConfigStore.get('windowBounds');
topWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
title: appPackage.productName, title: appPackage.productName,
icon: windowIcon, icon: windowIcon,
x: windowBounds.x, x: windowBounds.x,
...@@ -85,22 +84,22 @@ function createWindow() { ...@@ -85,22 +84,22 @@ function createWindow() {
}); });
if (!isDebugMode) { if (!isDebugMode) {
topWindow.setMenu(null); mainWindow.setMenu(null);
} }
topWindow.loadURL(indexFileUrl); mainWindow.loadURL(indexFileUrl);
topWindow.on('close', () => { mainWindow.on('close', () => {
const appConfigStore = new ElectronStore({name: storeAppConfigStorage}); const appConfigStore = new ElectronStore({name: appConfigStoreStorage});
appConfigStore.set('windowBounds', topWindow.getBounds()); appConfigStore.set('windowBounds', mainWindow.getBounds());
}); });
topWindow.on('closed', () => { mainWindow.on('closed', () => {
topWindow = null; mainWindow = null;
}); });
if (isDebugMode) { if (isDebugMode) {
topWindow.webContents.openDevTools(); mainWindow.webContents.openDevTools();
} }
} }
...@@ -131,9 +130,9 @@ function btoa(string) { ...@@ -131,9 +130,9 @@ function btoa(string) {
return buffer.toString('base64'); return buffer.toString('base64');
} }
/*function atob(string) { //function atob(string) {
return Buffer.from(string, 'base64').toString('binary'); // return Buffer.from(string, 'base64').toString('binary');
}*/ //}
function previewpicFilename(itemKey) { function previewpicFilename(itemKey) {
// "itemKey" will be URL to product file // "itemKey" will be URL to product file
...@@ -145,11 +144,9 @@ function downloadPreviewpic(itemKey, url) { ...@@ -145,11 +144,9 @@ function downloadPreviewpic(itemKey, url) {
fs.mkdirSync(previewpicDirectory); fs.mkdirSync(previewpicDirectory);
} }
const path = `${previewpicDirectory}/${previewpicFilename(itemKey)}`; const path = `${previewpicDirectory}/${previewpicFilename(itemKey)}`;
request.get(url) request.get(url).on('error', (error) => {
.on('error', (error) => { console.error(error);
console.error(error); }).pipe(fs.createWriteStream(path));
})
.pipe(fs.createWriteStream(path));
} }
function removePreviewpic(itemKey) { function removePreviewpic(itemKey) {
...@@ -179,7 +176,7 @@ app.on('window-all-closed', () => { ...@@ -179,7 +176,7 @@ app.on('window-all-closed', () => {
}); });
app.on('activate', () => { app.on('activate', () => {
if (topWindow === null) { if (mainWindow === null) {
createWindow(); createWindow();
} }
}); });
...@@ -213,25 +210,25 @@ ipcMain.on('ocs-manager', (event, key) => { ...@@ -213,25 +210,25 @@ ipcMain.on('ocs-manager', (event, key) => {
}); });
ipcMain.on('store', (event, key, value) => { ipcMain.on('store', (event, key, value) => {
const appConfigStore = new ElectronStore({name: storeAppConfigStorage}); const appConfigStore = new ElectronStore({name: appConfigStoreStorage});
if (key && value) { if (key && value) {
appConfigStore.set(key, value); appConfigStore.set(key, value);
} }
event.returnValue = key ? appConfigStore.get(key) : appConfigStore.store; event.returnValue = key ? appConfigStore.get(key) : appConfigStore.store;
}); });
ipcMain.on('previewpic', (event, action, itemKey, url) => { ipcMain.on('previewpic', (event, kind, itemKey, url) => {
if (action === 'directory') { if (kind === 'directory') {
event.returnValue = previewpicDirectory; event.returnValue = previewpicDirectory;
} }
else if (action === 'path' && itemKey) { else if (kind === 'path' && itemKey) {
event.returnValue = `${previewpicDirectory}/${previewpicFilename(itemKey)}`; event.returnValue = `${previewpicDirectory}/${previewpicFilename(itemKey)}`;
} }
else if (action === 'download' && itemKey && url) { else if (kind === 'download' && itemKey && url) {
downloadPreviewpic(itemKey, url); downloadPreviewpic(itemKey, url);
event.returnValue = undefined; event.returnValue = undefined;
} }
else if (action === 'remove' && itemKey) { else if (kind === 'remove' && itemKey) {
removePreviewpic(itemKey); removePreviewpic(itemKey);
event.returnValue = undefined; event.returnValue = undefined;
} }
......
...@@ -31,11 +31,12 @@ export default class AboutdialogComponent extends BaseComponent { ...@@ -31,11 +31,12 @@ export default class AboutdialogComponent extends BaseComponent {
render() { render() {
return this.html` return this.html`
<style>${this.sharedStyle}</style>
<style> <style>
${this.sharedStyle}
@import url(images/icon.css); @import url(images/icon.css);
</style>
<style>
div[slot="content"] { div[slot="content"] {
padding: 1em; padding: 1em;
text-align: center; text-align: center;
...@@ -54,7 +55,7 @@ export default class AboutdialogComponent extends BaseComponent { ...@@ -54,7 +55,7 @@ export default class AboutdialogComponent extends BaseComponent {
} }
</style> </style>
<app-dialog data-width="500px" data-footer-status="inactive"> <app-dialog data-width="500px" data-footer-state="inactive">
<h3 slot="header">About This App</h3> <h3 slot="header">About This App</h3>
<div slot="content"> <div slot="content">
<figure class="icon-ocs-store"></figure> <figure class="icon-ocs-store"></figure>
......
...@@ -22,7 +22,9 @@ export default class CollectiondialogComponent extends BaseComponent { ...@@ -22,7 +22,9 @@ export default class CollectiondialogComponent extends BaseComponent {
render() { render() {
return ` return `
<style>${this.sharedStyle}</style> <style>
${this.sharedStyle}
</style>
<style> <style>
app-page[slot="content"] { app-page[slot="content"] {
...@@ -37,7 +39,7 @@ export default class CollectiondialogComponent extends BaseComponent { ...@@ -37,7 +39,7 @@ export default class CollectiondialogComponent extends BaseComponent {
} }
</style> </style>
<app-dialog data-width="80%" data-height="80%" data-footer-status="inactive"> <app-dialog data-width="80%" data-height="80%" data-footer-state="inactive">
<h3 slot="header">My Collection</h3> <h3 slot="header">My Collection</h3>
<app-page id="collection" slot="content"> <app-page id="collection" slot="content">
<app-collectionsidebar slot="sidebar"></app-collectionsidebar> <app-collectionsidebar slot="sidebar"></app-collectionsidebar>
......
...@@ -23,11 +23,12 @@ export default class CollectiondownloadComponent extends BaseComponent { ...@@ -23,11 +23,12 @@ export default class CollectiondownloadComponent extends BaseComponent {
render() { render() {
return ` return `
<style>${this.sharedStyle}</style>
<style> <style>
${this.sharedStyle}
@import url(styles/material-icons.css); @import url(styles/material-icons.css);
</style>
<style>
:host { :host {
display: flex; display: flex;
flex-flow: column nowrap; flex-flow: column nowrap;
...@@ -92,7 +93,7 @@ export default class CollectiondownloadComponent extends BaseComponent { ...@@ -92,7 +93,7 @@ export default class CollectiondownloadComponent extends BaseComponent {
nav[data-action] button:hover { nav[data-action] button:hover {
border-color: rgba(0,0,0,0.3); border-color: rgba(0,0,0,0.3);
} }
nav[data-action] button[data-status="inactive"] { nav[data-action] button[data-state="inactive"] {
display: none; display: none;
} }
</style> </style>
...@@ -128,8 +129,7 @@ export default class CollectiondownloadComponent extends BaseComponent { ...@@ -128,8 +129,7 @@ export default class CollectiondownloadComponent extends BaseComponent {
} }
} }
else { else {
this.contentRoot.querySelector('ul[data-container]') this.contentRoot.querySelector('ul[data-container]').insertAdjacentHTML('afterbegin', this._listItemHtml(state));
.insertAdjacentHTML('afterbegin', this._listItemHtml(state));
} }
} }
...@@ -137,11 +137,10 @@ export default class CollectiondownloadComponent extends BaseComponent { ...@@ -137,11 +137,10 @@ export default class CollectiondownloadComponent extends BaseComponent {
const listItem = this.contentRoot.querySelector(`li[data-url="${state.url}"]`); const listItem = this.contentRoot.querySelector(`li[data-url="${state.url}"]`);
if (listItem) { if (listItem) {
listItem.querySelector('progress[data-progress]').value = '' + state.bytesReceived/state.bytesTotal; listItem.querySelector('progress[data-progress]').value = '' + state.bytesReceived/state.bytesTotal;
const message = 'Downloading... ' listItem.querySelector('p[data-message]').textContent = 'Downloading... '
+ Chilit.Utility.convertByteToHumanReadable(state.bytesReceived) + Chilit.Utility.convertByteToHumanReadable(state.bytesReceived)
+ ' / ' + ' / '
+ Chilit.Utility.convertByteToHumanReadable(state.bytesTotal); + Chilit.Utility.convertByteToHumanReadable(state.bytesTotal);
listItem.querySelector('p[data-message]').textContent = message;
} }
} }
......
...@@ -20,7 +20,9 @@ export default class CollectioninstalledComponent extends BaseComponent { ...@@ -20,7 +20,9 @@ export default class CollectioninstalledComponent extends BaseComponent {
render() { render() {
return ` return `
<style>${this.sharedStyle}</style> <style>
${this.sharedStyle}
</style>
<style> <style>
:host { :host {
...@@ -79,7 +81,7 @@ export default class CollectioninstalledComponent extends BaseComponent { ...@@ -79,7 +81,7 @@ export default class CollectioninstalledComponent extends BaseComponent {
nav[data-action] button:hover { nav[data-action] button:hover {
border-color: rgba(0,0,0,0.3); border-color: rgba(0,0,0,0.3);
} }
nav[data-action] button[data-status="inactive"] { nav[data-action] button[data-state="inactive"] {
display: none; display: none;
} }
</style> </style>
...@@ -88,11 +90,11 @@ export default class CollectioninstalledComponent extends BaseComponent { ...@@ -88,11 +90,11 @@ export default class CollectioninstalledComponent extends BaseComponent {
`; `;
} }
_listItemsHtml(state) { _listItemSetHtml(state) {
const listItems = []; let listItemSet = '';
if (state.count) { if (state.count) {
const applyButtonStatus = state.isApplicableType ? 'active' : 'inactive'; const applyButtonState = state.isApplicableType ? 'active' : 'inactive';
const openButtonText = (state.installType === 'bin') ? 'Run' : 'Open'; const openButtonText = (state.installType === 'bin') ? 'Run' : 'Open';
const destination = state.installTypes[state.installType].destination; const destination = state.installTypes[state.installType].destination;
...@@ -101,7 +103,7 @@ export default class CollectioninstalledComponent extends BaseComponent { ...@@ -101,7 +103,7 @@ export default class CollectioninstalledComponent extends BaseComponent {
for (const file of value.files) { for (const file of value.files) {
const filePath = `${destination}/${file}`; const filePath = `${destination}/${file}`;
const fileUrl = `file://${filePath}`; const fileUrl = `file://${filePath}`;
listItems.push(` listItemSet += `
<li> <li>
<figure data-previewpic style="background-image: url('${previewpicUrl}');"></figure> <figure data-previewpic style="background-image: url('${previewpicUrl}');"></figure>
<div data-main> <div data-main>
...@@ -111,42 +113,41 @@ export default class CollectioninstalledComponent extends BaseComponent { ...@@ -111,42 +113,41 @@ export default class CollectioninstalledComponent extends BaseComponent {
<button data-action="ocsManager_openUrl" data-url="${fileUrl}">${openButtonText}</button> <button data-action="ocsManager_openUrl" data-url="${fileUrl}">${openButtonText}</button>
<button data-action="ocsManager_applyTheme" <button data-action="ocsManager_applyTheme"
data-path="${filePath}" data-install-type="${state.installType}" data-path="${filePath}" data-install-type="${state.installType}"
data-status="${applyButtonStatus}">Apply</button> data-state="${applyButtonState}">Apply</button>
<button data-action="ocsManager_uninstall" data-item-key="${key}">Delete</button> <button data-action="ocsManager_uninstall" data-item-key="${key}">Delete</button>
</nav> </nav>
</li> </li>
`); `;
} }
} }
} }
return listItems.join(''); return listItemSet;
} }
_handleClick(event) { _handleClick(event) {
if (event.target.closest('button[data-action]')) { if (event.target.closest('button[data-action]')) {
const button = event.target.closest('button[data-action]'); const target = event.target.closest('button[data-action]');
switch (button.getAttribute('data-action')) { switch (target.getAttribute('data-action')) {
case 'ocsManager_openUrl': case 'ocsManager_openUrl':
this.dispatch('ocsManager_openUrl', {url: button.getAttribute('data-url')}); this.dispatch('ocsManager_openUrl', {url: target.getAttribute('data-url')});
break; break;
case 'ocsManager_applyTheme': case 'ocsManager_applyTheme':
this.dispatch('ocsManager_applyTheme', { this.dispatch('ocsManager_applyTheme', {
path: button.getAttribute('data-path'), path: target.getAttribute('data-path'),
installType: button.getAttribute('data-install-type') installType: target.getAttribute('data-install-type')
}); });
break; break;
case 'ocsManager_uninstall': case 'ocsManager_uninstall':
this.dispatch('ocsManager_uninstall', {itemKey: button.getAttribute('data-item-key')}); this.dispatch('ocsManager_uninstall', {itemKey: target.getAttribute('data-item-key')});
button.closest('li').remove(); target.closest('li').remove();
break; break;
} }
} }
} }
_viewHandler_ocsManager_installedItemsByType(state) { _viewHandler_ocsManager_installedItemsByType(state) {
this.contentRoot.querySelector('ul[data-container]') this.contentRoot.querySelector('ul[data-container]').innerHTML = this._listItemSetHtml(state);
.innerHTML = this._listItemsHtml(state);
} }
} }
...@@ -26,7 +26,9 @@ export default class CollectionsidebarComponent extends BaseComponent { ...@@ -26,7 +26,9 @@ export default class CollectionsidebarComponent extends BaseComponent {
render() { render() {
return ` return `
<style>${this.sharedStyle}</style> <style>
${this.sharedStyle}
</style>
<style> <style>
:host { :host {
...@@ -46,7 +48,7 @@ export default class CollectionsidebarComponent extends BaseComponent { ...@@ -46,7 +48,7 @@ export default class CollectionsidebarComponent extends BaseComponent {
nav[data-sidebar] h4 { nav[data-sidebar] h4 {
padding: 0.5em 1em; padding: 0.5em 1em;
} }
nav[data-sidebar] ul[data-menu="activity"] { nav[data-sidebar] ul[data-menu="task"] {
border-bottom: 1px solid var(--color-border); border-bottom: 1px solid var(--color-border);
} }
nav[data-sidebar] ul li a { nav[data-sidebar] ul li a {
...@@ -61,7 +63,7 @@ export default class CollectionsidebarComponent extends BaseComponent { ...@@ -61,7 +63,7 @@ export default class CollectionsidebarComponent extends BaseComponent {
nav[data-sidebar] ul li a[data-selected] { nav[data-sidebar] ul li a[data-selected] {
background-color: var(--color-active); background-color: var(--color-active);
} }
nav[data-sidebar] ul li a[data-status="inactive"] { nav[data-sidebar] ul li a[data-state="inactive"] {
display: none; display: none;
} }
nav[data-sidebar] ul li a span[data-name] { nav[data-sidebar] ul li a span[data-name] {
...@@ -99,44 +101,44 @@ export default class CollectionsidebarComponent extends BaseComponent { ...@@ -99,44 +101,44 @@ export default class CollectionsidebarComponent extends BaseComponent {
</style> </style>
<nav data-sidebar> <nav data-sidebar>
<ul data-menu="activity"> <ul data-menu="task">
<li> <li>
<a href="#" data-action="update" data-status="inactive"> <a href="#" data-action="update" data-state="inactive">
<span data-name>Update</span> <span data-name>Update</span>
<span data-count="0">0</span> <span data-count="0">0</span>
</a> </a>
</li> </li>
<li> <li>
<a href="#" data-action="download" data-status="active"> <a href="#" data-action="download" data-state="active">
<span data-name>Download</span> <span data-name>Download</span>
<span data-count="0">0</span> <span data-count="0">0</span>
</a> </a>
</li> </li>
</ul> </ul>
<h4>Installed</h4> <h4>Installed</h4>
<ul data-menu="category"></ul> <ul data-menu="categories"></ul>
</nav> </nav>
`; `;
} }
_categoryMenuItemsHtml(state) { _categoriesMenuItemSetHtml(state) {
const menuItems = []; let listItemSet = '';
if (state.count) { if (state.count) {
const categorizedInstalledItems = {}; const categorizedItems = {};
for (const [key, value] of Object.entries(state.installedItems)) { for (const [key, value] of Object.entries(state.installedItems)) {
if (!categorizedInstalledItems[value.install_type]) { if (!categorizedItems[value.install_type]) {
categorizedInstalledItems[value.install_type] = {}; categorizedItems[value.install_type] = {};
} }
categorizedInstalledItems[value.install_type][key] = value; categorizedItems[value.install_type][key] = value;
} }
const categories = []; const categories = [];
for (const installType of Object.keys(categorizedInstalledItems)) { for (const installType of Object.keys(categorizedItems)) {
categories.push({ categories.push({
installType: installType, installType: installType,
name: state.installTypes[installType].name, name: state.installTypes[installType].name,
count: Object.keys(categorizedInstalledItems[installType]).length count: Object.keys(categorizedItems[installType]).length
}); });
} }
categories.sort((a, b) => { categories.sort((a, b) => {
...@@ -152,35 +154,33 @@ export default class CollectionsidebarComponent extends BaseComponent { ...@@ -152,35 +154,33 @@ export default class CollectionsidebarComponent extends BaseComponent {
}); });
for (const category of categories) { for (const category of categories) {
menuItems.push(` listItemSet += `
<li> <li>
<a href="#" data-action="installed" data-install-type="${category.installType}"> <a href="#" data-action="installed" data-install-type="${category.installType}">
<span data-name>${category.name}</span> <span data-name>${category.name}</span>
<span data-count="${category.count}">${category.count}</span> <span data-count="${category.count}">${category.count}</span>
</a> </a>
</li> </li>
`); `;
} }
} }
return menuItems.join(''); return listItemSet;
} }
_handleClick(event) { _handleClick(event) {
if (event.target.closest('a[data-action]')) { if (event.target.closest('a[data-action]')) {
event.preventDefault(); event.preventDefault();
const targetMenuItem = event.target.closest('a[data-action]'); const target = event.target.closest('a[data-action]');
for (const menuItem of this.contentRoot.querySelectorAll('a[data-action]')) { if (this.contentRoot.querySelector('a[data-action][data-selected]')) {
menuItem.removeAttribute('data-selected'); this.contentRoot.querySelector('a[data-action][data-selected]').removeAttribute('data-selected');
} }
targetMenuItem.setAttribute('data-selected', 'data-selected'); target.setAttribute('data-selected', 'data-selected');
switch (targetMenuItem.getAttribute('data-action')) { switch (target.getAttribute('data-action')) {
case 'installed': case 'installed':
this.dispatch('ocsManager_installedItemsByType', { this.dispatch('ocsManager_installedItemsByType', {installType: target.getAttribute('data-install-type')});
installType: targetMenuItem.getAttribute('data-install-type')
});
this.dispatch('collectionsidebar_select', {select: 'installed'}); this.dispatch('collectionsidebar_select', {select: 'installed'});
break; break;
case 'update': case 'update':
...@@ -194,15 +194,14 @@ export default class CollectionsidebarComponent extends BaseComponent { ...@@ -194,15 +194,14 @@ export default class CollectionsidebarComponent extends BaseComponent {
} }
_viewHandler_ocsManager_installedItems(state) { _viewHandler_ocsManager_installedItems(state) {
const categoryMenu = this.contentRoot.querySelector('nav ul[data-menu="category"]'); const categoriesMenu = this.contentRoot.querySelector('ul[data-menu="categories"]');
const selectedMenuItem = categoryMenu.querySelector('a[data-selected]'); const selectedMenuItem = categoriesMenu.querySelector('a[data-selected]');
const installType = selectedMenuItem ? selectedMenuItem.getAttribute('data-install-type') : ''; const installType = selectedMenuItem ? selectedMenuItem.getAttribute('data-install-type') : '';
categoryMenu.innerHTML = this._categoryMenuItemsHtml(state); categoriesMenu.innerHTML = this._categoriesMenuItemSetHtml(state);
const menuItem = installType ? categoryMenu.querySelector(`a[data-install-type="${installType}"]`) : null;
const menuItem = installType ? categoriesMenu.querySelector(`a[data-install-type="${installType}"]`) : null;
if (menuItem) { if (menuItem) {
menuItem.click(); menuItem.click();
} }
...@@ -210,7 +209,7 @@ export default class CollectionsidebarComponent extends BaseComponent { ...@@ -210,7 +209,7 @@ export default class CollectionsidebarComponent extends BaseComponent {
_viewHandler_ocsManager_updateAvailableItems(state) { _viewHandler_ocsManager_updateAvailableItems(state) {
const