Skip to content

Commit 90c3faa

Browse files
committed
Merge branch 'release/1.3.3'
2 parents d71c235 + e594206 commit 90c3faa

File tree

15 files changed

+202
-31
lines changed

15 files changed

+202
-31
lines changed

CHANGELOG.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
1.3.3 / 2022-11-28
2+
------------------
3+
4+
- Исправление выявленных недочетов
5+
6+
1.3.2 / 2022-11-27
7+
------------------
8+
9+
- Изменения механизма ограничения доступа по паролю:
10+
- появилась возможность выхода из сессии
11+
- в конфиг добавлена настройка таймаута для автозавершения сессии
12+
- Добавлено отображение количества книг в серии в разделе "Авторы"
13+
14+
1.3.1 / 2022-11-25
15+
------------------
16+
17+
- Улучшена кроссплатформенность приложения
18+
19+
1.3.0 / 2022-11-24
20+
------------------
21+
22+
- Добавлен OPDS-сервер для inpx-коллекции
23+
- Произведена небольшая оптимизация поисковой БД
24+
- Добавлен релиз для macos, без тестирования
25+
26+
1.2.4 / 2022-11-14
27+
------------------
28+
29+
- Добавлена возможность посмотреть обложку в увеличении
30+
- Исправление выявленных недочетов
31+
32+
1.2.3 / 2022-11-12
33+
------------------
34+
35+
- Добавлено диалоговое окно "Информация о книге"
36+
- Небольшие изменения интерфейса, добавлена кнопка "Клонировать поиск"
37+
38+
1.1.4 / 2022-11-03
39+
------------------
40+
41+
- Исправлен баг "Не качает книги #1"
42+
43+
1.1.2 / 2022-10-31
44+
------------------
45+
46+
- Добавлены разделы "Серии" и "Книги"
47+
- Расширена форма поиска: добавлен поиск по датам поступления и оценкам
48+

client/components/Api/Api.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ class Api {
239239
return await this.request({action: 'get-author-book-list', authorId});
240240
}
241241
242+
async getAuthorSeriesList(authorId) {
243+
return await this.request({action: 'get-author-series-list', authorId});
244+
}
245+
242246
async getSeriesBookList(series) {
243247
return await this.request({action: 'get-series-book-list', series});
244248
}
@@ -261,6 +265,7 @@ class Api {
261265
262266
async logout() {
263267
await this.request({action: 'logout'});
268+
this.accessGranted = false;
264269
await this.request({action: 'test'});
265270
}
266271
}

client/components/Search/AuthorList/AuthorList.vue

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
</div>
5757

5858
<div class="q-ml-sm text-bold" style="color: #555">
59-
{{ getSeriesBookCount(book) }}
59+
{{ getSeriesBookCount(item, book) }}
6060
</div>
6161
</div>
6262

@@ -188,15 +188,17 @@ class AuthorList extends BaseList {
188188
return `(${result})`;
189189
}
190190
191-
getSeriesBookCount(book) {
191+
getSeriesBookCount(item, book) {
192192
let result = '';
193193
if (!this.showCounts || book.type != 'series')
194194
return result;
195195
196196
let count = book.seriesBooks.length;
197197
result = `${count}`;
198-
if (book.allBooksLoaded) {
199-
result += `/${book.allBooksLoaded.length}`;
198+
if (item.seriesLoaded) {
199+
const rec = item.seriesLoaded[book.series];
200+
const totalCount = (this.showDeleted ? rec.bookCount + rec.bookDelCount : rec.bookCount);
201+
result += `/${totalCount}`;
200202
}
201203
202204
return `(${result})`;
@@ -227,6 +229,19 @@ class AuthorList extends BaseList {
227229
}
228230
}
229231
232+
async getAuthorSeries(item) {
233+
if (item.seriesLoaded)
234+
return;
235+
236+
const series = await this.loadAuthorSeries(item.key);
237+
const loaded = {};
238+
for (const s of series) {
239+
loaded[s.series] = {bookCount: s.bookCount, bookDelCount: s.bookDelCount};
240+
}
241+
242+
item.seriesLoaded = loaded;
243+
}
244+
230245
async getAuthorBooks(item) {
231246
if (item.books) {
232247
if (item.count > this.maxItemCount) {
@@ -328,6 +343,7 @@ class AuthorList extends BaseList {
328343
}
329344
330345
item.booksLoaded = books;
346+
this.getAuthorSeries(item);//no await
331347
this.showMore(item);
332348
333349
await this.$nextTick();
@@ -360,6 +376,7 @@ class AuthorList extends BaseList {
360376
name: rec.author.replace(/,/g, ', '),
361377
count,
362378
booksLoaded: false,
379+
seriesLoaded: false,
363380
books: false,
364381
bookLoading: false,
365382
showMore: false,

client/components/Search/BaseList.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,30 @@ export default class BaseList {
253253
result = await this.api.getAuthorBookList(authorId);
254254
}
255255

256-
return (result.books ? JSON.parse(result.books) : []);
256+
return result.books;
257+
} catch (e) {
258+
this.$root.stdDialog.alert(e.message, 'Ошибка');
259+
}
260+
}
261+
262+
async loadAuthorSeries(authorId) {
263+
try {
264+
let result;
265+
266+
if (this.abCacheEnabled) {
267+
const key = `author-${authorId}-series-${this.list.inpxHash}`;
268+
const data = await authorBooksStorage.getData(key);
269+
if (data) {
270+
result = JSON.parse(data);
271+
} else {
272+
result = await this.api.getAuthorSeriesList(authorId);
273+
await authorBooksStorage.setData(key, JSON.stringify(result));
274+
}
275+
} else {
276+
result = await this.api.getAuthorSeriesList(authorId);
277+
}
278+
279+
return result.series;
257280
} catch (e) {
258281
this.$root.stdDialog.alert(e.message, 'Ошибка');
259282
}
@@ -276,7 +299,7 @@ export default class BaseList {
276299
result = await this.api.getSeriesBookList(series);
277300
}
278301

279-
return (result.books ? JSON.parse(result.books) : []);
302+
return result.books;
280303
} catch (e) {
281304
this.$root.stdDialog.alert(e.message, 'Ошибка');
282305
}

client/components/Search/authorBooksStorage.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ const abStore = localForage.createInstance({
88
name: 'authorBooksStorage'
99
});
1010

11+
const storageVersion = '1';
12+
1113
class AuthorBooksStorage {
1214
constructor() {
1315
}
@@ -17,6 +19,8 @@ class AuthorBooksStorage {
1719
}
1820

1921
async setData(key, data) {
22+
key += storageVersion;
23+
2024
if (typeof data !== 'string')
2125
throw new Error('AuthorBooksStorage: data must be a string');
2226

@@ -25,6 +29,8 @@ class AuthorBooksStorage {
2529
}
2630

2731
async getData(key) {
32+
key += storageVersion;
33+
2834
const item = await abStore.getItem(key);
2935

3036
//обновим addTime
@@ -34,9 +40,9 @@ class AuthorBooksStorage {
3440
return item;
3541
}
3642

37-
async removeData(key) {
38-
await abStore.removeItem(key);
39-
await abStore.removeItem(`addTime-${key}`);
43+
async _removeData(fullKey) {
44+
await abStore.removeItem(fullKey);
45+
await abStore.removeItem(`addTime-${fullKey}`);
4046
}
4147

4248
async cleanStorage() {
@@ -62,7 +68,7 @@ class AuthorBooksStorage {
6268
}
6369

6470
if (size > maxDataSize && toDel) {
65-
await this.removeData(toDel);
71+
await this._removeData(toDel);
6672
} else {
6773
break;
6874
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "inpx-web",
3-
"version": "1.3.2",
3+
"version": "1.3.3",
44
"author": "Book Pauk <bookpauk@gmail.com>",
55
"license": "CC0-1.0",
66
"repository": "bookpauk/inpx-web",

server/controllers/WebSocketController.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ class WebSocketController {
8989
await this.search(req, ws); break;
9090
case 'get-author-book-list':
9191
await this.getAuthorBookList(req, ws); break;
92+
case 'get-author-series-list':
93+
await this.getAuthorSeriesList(req, ws); break;
9294
case 'get-series-book-list':
9395
await this.getSeriesBookList(req, ws); break;
9496
case 'get-genre-tree':
@@ -169,6 +171,12 @@ class WebSocketController {
169171
this.send(result, req, ws);
170172
}
171173

174+
async getAuthorSeriesList(req, ws) {
175+
const result = await this.webWorker.getAuthorSeriesList(req.authorId);
176+
177+
this.send(result, req, ws);
178+
}
179+
172180
async getSeriesBookList(req, ws) {
173181
const result = await this.webWorker.getSeriesBookList(req.series);
174182

server/core/DbSearcher.js

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ class DbSearcher {
599599
throw new Error('DbSearcher closed');
600600

601601
if (!authorId && !author)
602-
return {author: '', books: ''};
602+
return {author: '', books: []};
603603

604604
this.searchFlag++;
605605

@@ -625,14 +625,60 @@ class DbSearcher {
625625
const rows = await this.restoreBooks('author', [authorId]);
626626

627627
let authorName = '';
628-
let books = '';
628+
let books = [];
629629

630630
if (rows.length) {
631631
authorName = rows[0].name;
632632
books = rows[0].books;
633633
}
634634

635-
return {author: authorName, books: (books && books.length ? JSON.stringify(books) : '')};
635+
return {author: authorName, books};
636+
} finally {
637+
this.searchFlag--;
638+
}
639+
}
640+
641+
async getAuthorSeriesList(authorId) {
642+
if (this.closed)
643+
throw new Error('DbSearcher closed');
644+
645+
if (!authorId)
646+
return {author: '', series: []};
647+
648+
this.searchFlag++;
649+
650+
try {
651+
const db = this.db;
652+
653+
//выборка книг автора по authorId
654+
const bookList = await this.getAuthorBookList(authorId);
655+
const books = bookList.books;
656+
const seriesSet = new Set();
657+
for (const book of books) {
658+
if (book.series)
659+
seriesSet.add(book.series.toLowerCase());
660+
}
661+
662+
let series = [];
663+
if (seriesSet.size) {
664+
//выборка серий по названиям
665+
series = await db.select({
666+
table: 'series',
667+
map: `(r) => ({id: r.id, series: r.name, bookCount: r.bookCount, bookDelCount: r.bookDelCount})`,
668+
where: `
669+
const seriesArr = ${db.esc(Array.from(seriesSet))};
670+
const ids = new Set();
671+
for (const value of seriesArr) {
672+
for (const id of @dirtyIndexLR('value', value, value))
673+
ids.add(id);
674+
}
675+
676+
return ids;
677+
`
678+
});
679+
}
680+
681+
return {author: bookList.author, series};
636682
} finally {
637683
this.searchFlag--;
638684
}
@@ -643,7 +689,7 @@ class DbSearcher {
643689
throw new Error('DbSearcher closed');
644690

645691
if (!series)
646-
return {books: ''};
692+
return {books: []};
647693

648694
this.searchFlag++;
649695

@@ -659,7 +705,7 @@ class DbSearcher {
659705
where: `return Array.from(@dirtyIndexLR('value', ${db.esc(series)}, ${db.esc(series)}))`
660706
});
661707

662-
let books;
708+
let books = [];
663709
if (rows.length && rows[0].rawResult.length) {
664710
//выборка книг серии
665711
const bookRows = await this.restoreBooks('series', [rows[0].rawResult[0]])
@@ -668,7 +714,7 @@ class DbSearcher {
668714
books = bookRows[0].books;
669715
}
670716

671-
return {books: (books && books.length ? JSON.stringify(books) : '')};
717+
return {books};
672718
} finally {
673719
this.searchFlag--;
674720
}

server/core/RemoteLib.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ class RemoteLib {
1616
this.config = config;
1717

1818
this.wsc = new WebSocketConnection(config.remoteLib.url, 10, 30, {rejectUnauthorized: false});
19-
if (config.remoteLib.accessPassword)
20-
this.accessToken = utils.getBufHash(config.remoteLib.accessPassword, 'sha256', 'hex');
2119

2220
this.remoteHost = config.remoteLib.url.replace(/^ws:\/\//, 'http://').replace(/^wss:\/\//, 'https://');
2321

@@ -31,7 +29,7 @@ class RemoteLib {
3129
return instance;
3230
}
3331

34-
async wsRequest(query) {
32+
async wsRequest(query, recurse = false) {
3533
if (this.accessToken)
3634
query.accessToken = this.accessToken;
3735

@@ -40,6 +38,11 @@ class RemoteLib {
4038
120
4139
);
4240

41+
if (!recurse && response && response.error == 'need_access_token' && this.config.remoteLib.accessPassword) {
42+
this.accessToken = utils.getBufHash(this.config.remoteLib.accessPassword + response.salt, 'sha256', 'hex');
43+
return await this.wsRequest(query, true);
44+
}
45+
4346
if (response.error)
4447
throw new Error(response.error);
4548

0 commit comments

Comments
 (0)