fontastic 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/claude-code-review.yml +0 -6
- package/.github/workflows/release-please.yml +25 -0
- package/.github/workflows/release.yml +5 -109
- package/.release-please-manifest.json +3 -0
- package/CHANGELOG.md +39 -0
- package/README.md +6 -0
- package/app/Application.js +4 -4
- package/app/Application.ts +13 -13
- package/app/config/database.js +1 -1
- package/app/config/database.ts +1 -1
- package/app/config/mimes.js +23 -23
- package/app/config/mimes.ts +35 -29
- package/app/core/ConfigManager.js +27 -0
- package/app/core/ConfigManager.ts +28 -0
- package/app/core/FontFinder.js +66 -15
- package/app/core/FontFinder.ts +81 -22
- package/app/core/FontManager.js +20 -18
- package/app/core/FontManager.ts +21 -19
- package/app/core/FontObject.js +44 -24
- package/app/core/FontObject.ts +47 -27
- package/app/core/MessageHandler.js +70 -19
- package/app/core/MessageHandler.ts +82 -21
- package/app/core/SystemManager.js +5 -1
- package/app/core/SystemManager.ts +5 -1
- package/app/database/entity/Collection.schema.js +20 -18
- package/app/database/entity/Collection.schema.ts +22 -21
- package/app/database/repository/Collection.repository.js +17 -18
- package/app/database/repository/Collection.repository.ts +27 -18
- package/app/database/repository/Store.repository.js +13 -18
- package/app/database/repository/Store.repository.ts +13 -21
- package/app/enums/ChannelType.js +18 -0
- package/app/enums/ChannelType.ts +24 -0
- package/app/main.js +98 -10
- package/app/main.ts +126 -19
- package/app/package.json +1 -1
- package/app/types/NativeThemeState.js +3 -0
- package/app/types/NativeThemeState.ts +4 -0
- package/app/types/ScanProgress.js +3 -0
- package/app/types/ScanProgress.ts +6 -0
- package/app/types/SystemPreferencesState.js +3 -0
- package/app/types/SystemPreferencesState.ts +4 -0
- package/app/types/index.js +3 -0
- package/app/types/index.ts +3 -0
- package/package.json +2 -2
- package/release-please-config.json +20 -0
- package/scripts/patch-electron-plist.js +41 -0
- package/src/app/core/services/database/database.service.ts +6 -0
- package/src/app/core/services/message/message.service.ts +33 -1
- package/src/app/core/services/presentation/presentation.service.ts +100 -1
- package/src/app/layout/footer/footer.component.html +13 -2
- package/src/app/layout/footer/footer.component.ts +18 -2
- package/src/app/layout/header/header.component.html +0 -10
- package/src/app/layout/header/header.component.ts +4 -23
- package/src/app/layout/navigation/navigation.component.html +66 -16
- package/src/app/layout/navigation/navigation.component.ts +65 -12
- package/src/app/settings/ai-keys/ai-keys.component.ts +13 -18
- package/src/app/settings/danger-zone/danger-zone.component.html +8 -0
- package/src/app/settings/danger-zone/danger-zone.component.ts +12 -0
- package/src/app/settings/news-api/news-api.component.ts +6 -8
- package/src/app/settings/theme/theme.component.html +15 -2
- package/src/app/settings/theme/theme.component.ts +4 -0
- package/src/app/shared/components/datagrid/datagrid.component.html +8 -17
- package/src/app/shared/components/datagrid/datagrid.component.ts +6 -10
- package/src/app/shared/components/glyphs/glyphs.component.html +5 -15
- package/src/app/shared/components/glyphs/glyphs.component.ts +3 -0
- package/src/app/shared/components/preview/preview.component.html +1 -1
- package/src/app/shared/components/preview/preview.component.ts +3 -8
- package/src/app/shared/components/prompt-dialog/prompt-dialog.component.html +2 -2
- package/src/app/shared/components/prompt-dialog/prompt-dialog.component.ts +2 -1
- package/src/app/shared/components/rule-builder/rule-builder.component.html +18 -6
- package/src/app/shared/components/rule-builder/rule-builder.component.ts +34 -2
- package/src/app/shared/components/search/search.component.html +9 -36
- package/src/app/shared/components/search/search.component.ts +2 -1
- package/src/app/shared/components/waterfall/waterfall.component.html +1 -3
- package/src/app/shared/components/waterfall/waterfall.component.ts +2 -1
- package/src/app/shared/directives/disabled-opacity/disabled-opacity.directive.ts +18 -0
- package/src/app/shared/directives/hover-highlight/hover-highlight.directive.ts +38 -0
- package/src/app/shared/directives/index.ts +5 -0
- package/src/app/shared/directives/modal-backdrop/modal-backdrop.directive.ts +18 -0
- package/src/app/shared/directives/scroll-reset/scroll-reset.directive.ts +15 -0
- package/src/app/shared/directives/stop-propagation/stop-propagation.directive.ts +12 -0
- package/src/assets/icons/favicon.256x256.png +0 -0
- package/src/assets/icons/favicon.512x512.png +0 -0
- package/src/assets/icons/favicon.icns +0 -0
- package/src/assets/icons/favicon.ico +0 -0
- package/src/assets/icons/favicon.png +0 -0
- package/src/favicon.ico +0 -0
package/app/core/FontFinder.js
CHANGED
|
@@ -13,58 +13,109 @@ const FontObject_1 = require("./FontObject");
|
|
|
13
13
|
const fs = require("fs/promises");
|
|
14
14
|
const path = require("path");
|
|
15
15
|
const mimes_1 = require("../config/mimes");
|
|
16
|
-
const prettyBytes = require(
|
|
17
|
-
const mime = require(
|
|
16
|
+
const prettyBytes = require('pretty-bytes');
|
|
17
|
+
const mime = require('mime');
|
|
18
|
+
const SCAN_CONCURRENCY = 10;
|
|
18
19
|
class FontFinder {
|
|
19
|
-
constructor(connectionManager) {
|
|
20
|
+
constructor(connectionManager, onProgress) {
|
|
20
21
|
this.errors = [];
|
|
21
22
|
this.counter = 0;
|
|
23
|
+
this.onProgress = null;
|
|
22
24
|
this.connectionManager = connectionManager;
|
|
25
|
+
this.onProgress = onProgress !== null && onProgress !== void 0 ? onProgress : null;
|
|
23
26
|
}
|
|
24
|
-
|
|
27
|
+
getFontMimeType(filePath) {
|
|
25
28
|
const fileType = mime.getType(filePath);
|
|
26
|
-
return fileType && mimes_1.mimeTypes.includes(fileType);
|
|
29
|
+
return fileType && mimes_1.mimeTypes.includes(fileType) ? fileType : null;
|
|
27
30
|
}
|
|
28
31
|
scanFiles(files, options) {
|
|
29
32
|
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
this.errors = [];
|
|
34
|
+
this.counter = 0;
|
|
35
|
+
const fontFiles = [];
|
|
30
36
|
for (const fp of files) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
const fileType = this.getFontMimeType(fp);
|
|
38
|
+
if (fileType) {
|
|
39
|
+
fontFiles.push({ fp, fileType });
|
|
34
40
|
}
|
|
35
41
|
}
|
|
42
|
+
yield this.processInBatches(fontFiles, options);
|
|
36
43
|
});
|
|
37
44
|
}
|
|
38
45
|
scanFolder(dir, options) {
|
|
39
46
|
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
this.errors = [];
|
|
48
|
+
this.counter = 0;
|
|
49
|
+
const fontFiles = yield this.collectFontFiles(dir);
|
|
50
|
+
yield this.processInBatches(fontFiles, options);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
collectFontFiles(dir) {
|
|
54
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
const results = [];
|
|
40
56
|
const entries = yield fs.readdir(dir, { withFileTypes: true });
|
|
57
|
+
const subdirPromises = [];
|
|
41
58
|
for (const entry of entries) {
|
|
42
59
|
const fp = path.join(dir, entry.name);
|
|
43
60
|
if (entry.isDirectory()) {
|
|
44
|
-
|
|
61
|
+
subdirPromises.push(this.collectFontFiles(fp));
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const fileType = this.getFontMimeType(fp);
|
|
65
|
+
if (fileType) {
|
|
66
|
+
results.push({ fp, fileType });
|
|
67
|
+
}
|
|
45
68
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
69
|
+
}
|
|
70
|
+
if (subdirPromises.length > 0) {
|
|
71
|
+
const subdirResults = yield Promise.all(subdirPromises);
|
|
72
|
+
for (const subResults of subdirResults) {
|
|
73
|
+
results.push(...subResults);
|
|
49
74
|
}
|
|
50
75
|
}
|
|
76
|
+
return results;
|
|
51
77
|
});
|
|
52
78
|
}
|
|
53
|
-
|
|
79
|
+
processInBatches(fontFiles, options) {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
const total = fontFiles.length;
|
|
82
|
+
for (let i = 0; i < fontFiles.length; i += SCAN_CONCURRENCY) {
|
|
83
|
+
const batch = fontFiles.slice(i, i + SCAN_CONCURRENCY);
|
|
84
|
+
yield Promise.all(batch.map(({ fp, fileType }) => this.processFont(fp, fileType, options)));
|
|
85
|
+
if (this.onProgress) {
|
|
86
|
+
const lastFile = batch[batch.length - 1];
|
|
87
|
+
this.onProgress({
|
|
88
|
+
processed: Math.min(i + SCAN_CONCURRENCY, total),
|
|
89
|
+
total,
|
|
90
|
+
currentFile: path.basename(lastFile.fp),
|
|
91
|
+
errors: this.errors.length,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
processFont(fp, fileType, options) {
|
|
54
98
|
return __awaiter(this, void 0, void 0, function* () {
|
|
55
99
|
const font = new FontObject_1.default(fp);
|
|
56
100
|
if (font.hasError()) {
|
|
57
101
|
this.errors.push(font.getError());
|
|
58
102
|
return;
|
|
59
103
|
}
|
|
60
|
-
|
|
104
|
+
let stat;
|
|
105
|
+
try {
|
|
106
|
+
stat = yield fs.stat(fp);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
this.errors.push({ file: fp, message: err.message });
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
61
112
|
const data = Object.assign(Object.assign({ file_path: fp, file_name: path.basename(fp), file_size: stat.size, file_size_pretty: prettyBytes(stat.size), file_type: fileType, installable: mimes_1.installable.includes(fileType) }, options), font.getNamesTable());
|
|
62
113
|
try {
|
|
63
114
|
yield this.connectionManager.getStoreRepository().create(data);
|
|
64
115
|
this.counter++;
|
|
65
116
|
}
|
|
66
117
|
catch (err) {
|
|
67
|
-
this.errors.push(err.message);
|
|
118
|
+
this.errors.push({ file: fp, message: err.message });
|
|
68
119
|
}
|
|
69
120
|
});
|
|
70
121
|
}
|
package/app/core/FontFinder.ts
CHANGED
|
@@ -1,50 +1,103 @@
|
|
|
1
|
-
import ConnectionManager from
|
|
2
|
-
import FontObject from
|
|
3
|
-
import * as fs from
|
|
4
|
-
import * as path from
|
|
5
|
-
import { mimeTypes, installable } from
|
|
1
|
+
import ConnectionManager from './ConnectionManager';
|
|
2
|
+
import FontObject from './FontObject';
|
|
3
|
+
import * as fs from 'fs/promises';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { mimeTypes, installable } from '../config/mimes';
|
|
6
|
+
import type { ScanProgress } from '../types';
|
|
6
7
|
|
|
7
|
-
const prettyBytes = require(
|
|
8
|
-
const mime = require(
|
|
8
|
+
const prettyBytes = require('pretty-bytes');
|
|
9
|
+
const mime = require('mime');
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
const SCAN_CONCURRENCY = 10;
|
|
12
|
+
|
|
13
|
+
export type ProgressCallback = (progress: ScanProgress) => void;
|
|
11
14
|
|
|
15
|
+
export default class FontFinder {
|
|
12
16
|
connectionManager: ConnectionManager;
|
|
13
17
|
errors: any[] = [];
|
|
14
18
|
counter: number = 0;
|
|
19
|
+
private onProgress: ProgressCallback | null = null;
|
|
15
20
|
|
|
16
|
-
constructor(connectionManager: ConnectionManager) {
|
|
21
|
+
constructor(connectionManager: ConnectionManager, onProgress?: ProgressCallback) {
|
|
17
22
|
this.connectionManager = connectionManager;
|
|
23
|
+
this.onProgress = onProgress ?? null;
|
|
18
24
|
}
|
|
19
25
|
|
|
20
|
-
private
|
|
26
|
+
private getFontMimeType(filePath: string): string | null {
|
|
21
27
|
const fileType = mime.getType(filePath);
|
|
22
|
-
return fileType && mimeTypes.includes(fileType);
|
|
28
|
+
return fileType && mimeTypes.includes(fileType) ? fileType : null;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
async scanFiles(files: string[], options: any) {
|
|
32
|
+
this.errors = [];
|
|
33
|
+
this.counter = 0;
|
|
34
|
+
|
|
35
|
+
const fontFiles: { fp: string; fileType: string }[] = [];
|
|
26
36
|
for (const fp of files) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
const fileType = this.getFontMimeType(fp);
|
|
38
|
+
if (fileType) {
|
|
39
|
+
fontFiles.push({ fp, fileType });
|
|
30
40
|
}
|
|
31
41
|
}
|
|
42
|
+
|
|
43
|
+
await this.processInBatches(fontFiles, options);
|
|
32
44
|
}
|
|
33
45
|
|
|
34
46
|
async scanFolder(dir: string, options: any) {
|
|
47
|
+
this.errors = [];
|
|
48
|
+
this.counter = 0;
|
|
49
|
+
|
|
50
|
+
const fontFiles = await this.collectFontFiles(dir);
|
|
51
|
+
await this.processInBatches(fontFiles, options);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private async collectFontFiles(dir: string): Promise<{ fp: string; fileType: string }[]> {
|
|
55
|
+
const results: { fp: string; fileType: string }[] = [];
|
|
35
56
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
57
|
+
|
|
58
|
+
const subdirPromises: Promise<{ fp: string; fileType: string }[]>[] = [];
|
|
59
|
+
|
|
36
60
|
for (const entry of entries) {
|
|
37
61
|
const fp = path.join(dir, entry.name);
|
|
38
62
|
if (entry.isDirectory()) {
|
|
39
|
-
|
|
40
|
-
} else
|
|
41
|
-
const
|
|
42
|
-
|
|
63
|
+
subdirPromises.push(this.collectFontFiles(fp));
|
|
64
|
+
} else {
|
|
65
|
+
const fileType = this.getFontMimeType(fp);
|
|
66
|
+
if (fileType) {
|
|
67
|
+
results.push({ fp, fileType });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (subdirPromises.length > 0) {
|
|
73
|
+
const subdirResults = await Promise.all(subdirPromises);
|
|
74
|
+
for (const subResults of subdirResults) {
|
|
75
|
+
results.push(...subResults);
|
|
43
76
|
}
|
|
44
77
|
}
|
|
78
|
+
|
|
79
|
+
return results;
|
|
45
80
|
}
|
|
46
81
|
|
|
47
|
-
private async
|
|
82
|
+
private async processInBatches(fontFiles: { fp: string; fileType: string }[], options: any) {
|
|
83
|
+
const total = fontFiles.length;
|
|
84
|
+
for (let i = 0; i < fontFiles.length; i += SCAN_CONCURRENCY) {
|
|
85
|
+
const batch = fontFiles.slice(i, i + SCAN_CONCURRENCY);
|
|
86
|
+
await Promise.all(batch.map(({ fp, fileType }) => this.processFont(fp, fileType, options)));
|
|
87
|
+
|
|
88
|
+
if (this.onProgress) {
|
|
89
|
+
const lastFile = batch[batch.length - 1];
|
|
90
|
+
this.onProgress({
|
|
91
|
+
processed: Math.min(i + SCAN_CONCURRENCY, total),
|
|
92
|
+
total,
|
|
93
|
+
currentFile: path.basename(lastFile.fp),
|
|
94
|
+
errors: this.errors.length,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private async processFont(fp: string, fileType: string, options: any) {
|
|
48
101
|
const font = new FontObject(fp);
|
|
49
102
|
|
|
50
103
|
if (font.hasError()) {
|
|
@@ -52,7 +105,13 @@ export default class FontFinder {
|
|
|
52
105
|
return;
|
|
53
106
|
}
|
|
54
107
|
|
|
55
|
-
|
|
108
|
+
let stat;
|
|
109
|
+
try {
|
|
110
|
+
stat = await fs.stat(fp);
|
|
111
|
+
} catch (err: any) {
|
|
112
|
+
this.errors.push({ file: fp, message: err.message });
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
56
115
|
|
|
57
116
|
const data = {
|
|
58
117
|
file_path: fp,
|
|
@@ -68,8 +127,8 @@ export default class FontFinder {
|
|
|
68
127
|
try {
|
|
69
128
|
await this.connectionManager.getStoreRepository().create(data);
|
|
70
129
|
this.counter++;
|
|
71
|
-
} catch (err) {
|
|
72
|
-
this.errors.push(err.message);
|
|
130
|
+
} catch (err: any) {
|
|
131
|
+
this.errors.push({ file: fp, message: err.message });
|
|
73
132
|
}
|
|
74
133
|
}
|
|
75
134
|
}
|
package/app/core/FontManager.js
CHANGED
|
@@ -18,13 +18,25 @@ const path = require("path");
|
|
|
18
18
|
const fetch = require('node-fetch');
|
|
19
19
|
class FontManager {
|
|
20
20
|
constructor(systemManager, configManager, connectionManager) {
|
|
21
|
+
this.catalog = new FontCatalog_1.default();
|
|
21
22
|
this.systemManager = systemManager;
|
|
22
23
|
this.configManager = configManager;
|
|
23
24
|
this.connectionManager = connectionManager;
|
|
24
25
|
}
|
|
25
26
|
fetchLatestNews(args) {
|
|
26
27
|
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
-
|
|
28
|
+
// Retrieve API key securely from main process storage
|
|
29
|
+
let apiKey = args.apiKey;
|
|
30
|
+
if (!apiKey) {
|
|
31
|
+
const secureKey = this.configManager.getSecure('secure.news.apiKey');
|
|
32
|
+
if (secureKey) {
|
|
33
|
+
apiKey = secureKey;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (!apiKey)
|
|
37
|
+
return { articles: [] };
|
|
38
|
+
const endpoint = `https://newsapi.org/v2/top-headlines?country=${args.country || 'us'}&apiKey=${apiKey}`;
|
|
39
|
+
const response = yield fetch(endpoint);
|
|
28
40
|
const data = yield response.json();
|
|
29
41
|
if (data === null || data === void 0 ? void 0 : data.articles) {
|
|
30
42
|
this.configManager.set(StorageType_1.StorageType.News, Object.assign(Object.assign({}, this.configManager.get(StorageType_1.StorageType.News)), { articles: data.articles, ts: Date.now() }));
|
|
@@ -55,37 +67,27 @@ class FontManager {
|
|
|
55
67
|
copyFiles(files, collectionId) {
|
|
56
68
|
return __awaiter(this, void 0, void 0, function* () {
|
|
57
69
|
const dest = this.getDestinationFolder(collectionId);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
yield catalog.copyFiles(files, dest);
|
|
61
|
-
const catalogFiles = files.map((file) => path.join(dest, path.basename(file)));
|
|
62
|
-
console.log('[FontManager.copyFiles] catalogFiles:', catalogFiles);
|
|
63
|
-
return catalogFiles;
|
|
70
|
+
yield this.catalog.copyFiles(files, dest);
|
|
71
|
+
return files.map((file) => path.join(dest, path.basename(file)));
|
|
64
72
|
});
|
|
65
73
|
}
|
|
66
74
|
copyFolder(src, collectionId) {
|
|
67
75
|
return __awaiter(this, void 0, void 0, function* () {
|
|
68
76
|
const dest = this.getDestinationFolder(collectionId);
|
|
69
|
-
|
|
70
|
-
const catalog = new FontCatalog_1.default();
|
|
71
|
-
yield catalog.copyFolder(src, dest);
|
|
77
|
+
yield this.catalog.copyFolder(src, dest);
|
|
72
78
|
return dest;
|
|
73
79
|
});
|
|
74
80
|
}
|
|
75
|
-
scanFiles(files, options) {
|
|
81
|
+
scanFiles(files, options, onProgress) {
|
|
76
82
|
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
-
|
|
78
|
-
const finder = new FontFinder_1.default(this.connectionManager);
|
|
83
|
+
const finder = new FontFinder_1.default(this.connectionManager, onProgress);
|
|
79
84
|
yield finder.scanFiles(files, options);
|
|
80
|
-
console.log('[FontManager.scanFiles] done, processed:', finder.counter, 'errors:', finder.errors);
|
|
81
85
|
});
|
|
82
86
|
}
|
|
83
|
-
scanFolder(dir, options) {
|
|
87
|
+
scanFolder(dir, options, onProgress) {
|
|
84
88
|
return __awaiter(this, void 0, void 0, function* () {
|
|
85
|
-
|
|
86
|
-
const finder = new FontFinder_1.default(this.connectionManager);
|
|
89
|
+
const finder = new FontFinder_1.default(this.connectionManager, onProgress);
|
|
87
90
|
yield finder.scanFolder(dir, options);
|
|
88
|
-
console.log('[FontManager.scanFolder] done, processed:', finder.counter, 'errors:', finder.errors);
|
|
89
91
|
});
|
|
90
92
|
}
|
|
91
93
|
showMessageBox(options) {
|
package/app/core/FontManager.ts
CHANGED
|
@@ -5,7 +5,7 @@ import ConfigManager from './ConfigManager';
|
|
|
5
5
|
import ConnectionManager from './ConnectionManager';
|
|
6
6
|
|
|
7
7
|
import FontCatalog from './FontCatalog';
|
|
8
|
-
import FontFinder from './FontFinder';
|
|
8
|
+
import FontFinder, { ProgressCallback } from './FontFinder';
|
|
9
9
|
import { execute } from '../helpers/command';
|
|
10
10
|
|
|
11
11
|
import { StorageType } from '../enums/StorageType';
|
|
@@ -18,6 +18,7 @@ export default class FontManager {
|
|
|
18
18
|
systemManager: SystemManager;
|
|
19
19
|
configManager: ConfigManager;
|
|
20
20
|
connectionManager: ConnectionManager;
|
|
21
|
+
private catalog = new FontCatalog();
|
|
21
22
|
|
|
22
23
|
constructor(systemManager: SystemManager, configManager: ConfigManager, connectionManager: ConnectionManager) {
|
|
23
24
|
this.systemManager = systemManager;
|
|
@@ -26,7 +27,18 @@ export default class FontManager {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
async fetchLatestNews(args: any) {
|
|
29
|
-
|
|
30
|
+
// Retrieve API key securely from main process storage
|
|
31
|
+
let apiKey = args.apiKey;
|
|
32
|
+
if (!apiKey) {
|
|
33
|
+
const secureKey = this.configManager.getSecure('secure.news.apiKey');
|
|
34
|
+
if (secureKey) {
|
|
35
|
+
apiKey = secureKey;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (!apiKey) return { articles: [] };
|
|
39
|
+
|
|
40
|
+
const endpoint = `https://newsapi.org/v2/top-headlines?country=${args.country || 'us'}&apiKey=${apiKey}`;
|
|
41
|
+
const response = await fetch(endpoint);
|
|
30
42
|
const data = await response.json();
|
|
31
43
|
if (data?.articles) {
|
|
32
44
|
this.configManager.set(StorageType.News, {
|
|
@@ -58,34 +70,24 @@ export default class FontManager {
|
|
|
58
70
|
|
|
59
71
|
async copyFiles(files: string[], collectionId: number): Promise<string[]> {
|
|
60
72
|
const dest = this.getDestinationFolder(collectionId);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
await catalog.copyFiles(files, dest);
|
|
64
|
-
const catalogFiles = files.map((file) => path.join(dest, path.basename(file)));
|
|
65
|
-
console.log('[FontManager.copyFiles] catalogFiles:', catalogFiles);
|
|
66
|
-
return catalogFiles;
|
|
73
|
+
await this.catalog.copyFiles(files, dest);
|
|
74
|
+
return files.map((file) => path.join(dest, path.basename(file)));
|
|
67
75
|
}
|
|
68
76
|
|
|
69
77
|
async copyFolder(src: string, collectionId: number): Promise<string> {
|
|
70
78
|
const dest = this.getDestinationFolder(collectionId);
|
|
71
|
-
|
|
72
|
-
const catalog = new FontCatalog();
|
|
73
|
-
await catalog.copyFolder(src, dest);
|
|
79
|
+
await this.catalog.copyFolder(src, dest);
|
|
74
80
|
return dest;
|
|
75
81
|
}
|
|
76
82
|
|
|
77
|
-
async scanFiles(files: string[], options: any) {
|
|
78
|
-
|
|
79
|
-
const finder = new FontFinder(this.connectionManager);
|
|
83
|
+
async scanFiles(files: string[], options: any, onProgress?: ProgressCallback) {
|
|
84
|
+
const finder = new FontFinder(this.connectionManager, onProgress);
|
|
80
85
|
await finder.scanFiles(files, options);
|
|
81
|
-
console.log('[FontManager.scanFiles] done, processed:', finder.counter, 'errors:', finder.errors);
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
async scanFolder(dir: string, options: any) {
|
|
85
|
-
|
|
86
|
-
const finder = new FontFinder(this.connectionManager);
|
|
88
|
+
async scanFolder(dir: string, options: any, onProgress?: ProgressCallback) {
|
|
89
|
+
const finder = new FontFinder(this.connectionManager, onProgress);
|
|
87
90
|
await finder.scanFolder(dir, options);
|
|
88
|
-
console.log('[FontManager.scanFolder] done, processed:', finder.counter, 'errors:', finder.errors);
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
showMessageBox(options: any) {
|
package/app/core/FontObject.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const fontkit = require(
|
|
3
|
+
const fontkit = require('fontkit');
|
|
4
|
+
const MAX_CACHE_SIZE = 50;
|
|
5
|
+
const fontCache = new Map();
|
|
4
6
|
class FontObject {
|
|
5
7
|
constructor(fp) {
|
|
6
8
|
try {
|
|
@@ -10,6 +12,20 @@ class FontObject {
|
|
|
10
12
|
this.setError(fp, err.message);
|
|
11
13
|
}
|
|
12
14
|
}
|
|
15
|
+
static fromCache(fp) {
|
|
16
|
+
const cached = fontCache.get(fp);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
const obj = new FontObject(fp);
|
|
20
|
+
if (!obj.hasError()) {
|
|
21
|
+
if (fontCache.size >= MAX_CACHE_SIZE) {
|
|
22
|
+
const firstKey = fontCache.keys().next().value;
|
|
23
|
+
fontCache.delete(firstKey);
|
|
24
|
+
}
|
|
25
|
+
fontCache.set(fp, obj);
|
|
26
|
+
}
|
|
27
|
+
return obj;
|
|
28
|
+
}
|
|
13
29
|
setFont(font) {
|
|
14
30
|
this.font = font;
|
|
15
31
|
}
|
|
@@ -23,31 +39,35 @@ class FontObject {
|
|
|
23
39
|
return this.error;
|
|
24
40
|
}
|
|
25
41
|
hasError() {
|
|
26
|
-
return this.error
|
|
42
|
+
return !!this.error;
|
|
27
43
|
}
|
|
28
44
|
getNamesTable() {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
|
|
46
|
+
if (this.namesTable)
|
|
47
|
+
return this.namesTable;
|
|
48
|
+
const names = (_b = (_a = this.font) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.records;
|
|
49
|
+
this.namesTable = {
|
|
50
|
+
compatible_full_name: (_d = (_c = names === null || names === void 0 ? void 0 : names.compatibleFullName) === null || _c === void 0 ? void 0 : _c.en) !== null && _d !== void 0 ? _d : '',
|
|
51
|
+
copyright: (_f = (_e = names === null || names === void 0 ? void 0 : names.copyright) === null || _e === void 0 ? void 0 : _e.en) !== null && _f !== void 0 ? _f : '',
|
|
52
|
+
description: (_h = (_g = names === null || names === void 0 ? void 0 : names.description) === null || _g === void 0 ? void 0 : _g.en) !== null && _h !== void 0 ? _h : '',
|
|
53
|
+
designer: (_k = (_j = names === null || names === void 0 ? void 0 : names.designer) === null || _j === void 0 ? void 0 : _j.en) !== null && _k !== void 0 ? _k : '',
|
|
54
|
+
designer_url: (_m = (_l = names === null || names === void 0 ? void 0 : names.designerURL) === null || _l === void 0 ? void 0 : _l.en) !== null && _m !== void 0 ? _m : '',
|
|
55
|
+
font_family: (_p = (_o = names === null || names === void 0 ? void 0 : names.fontFamily) === null || _o === void 0 ? void 0 : _o.en) !== null && _p !== void 0 ? _p : '',
|
|
56
|
+
font_subfamily: (_r = (_q = names === null || names === void 0 ? void 0 : names.fontSubfamily) === null || _q === void 0 ? void 0 : _q.en) !== null && _r !== void 0 ? _r : '',
|
|
57
|
+
full_name: (_t = (_s = names === null || names === void 0 ? void 0 : names.fullName) === null || _s === void 0 ? void 0 : _s.en) !== null && _t !== void 0 ? _t : '',
|
|
58
|
+
license: (_v = (_u = names === null || names === void 0 ? void 0 : names.license) === null || _u === void 0 ? void 0 : _u.en) !== null && _v !== void 0 ? _v : '',
|
|
59
|
+
license_url: (_x = (_w = names === null || names === void 0 ? void 0 : names.licenseURL) === null || _w === void 0 ? void 0 : _w.en) !== null && _x !== void 0 ? _x : '',
|
|
60
|
+
manufacturer: (_z = (_y = names === null || names === void 0 ? void 0 : names.manufacturer) === null || _y === void 0 ? void 0 : _y.en) !== null && _z !== void 0 ? _z : '',
|
|
61
|
+
manufacturer_url: (_1 = (_0 = names === null || names === void 0 ? void 0 : names.manufacturerURL) === null || _0 === void 0 ? void 0 : _0.en) !== null && _1 !== void 0 ? _1 : '',
|
|
62
|
+
post_script_name: (_3 = (_2 = names === null || names === void 0 ? void 0 : names.postScriptName) === null || _2 === void 0 ? void 0 : _2.en) !== null && _3 !== void 0 ? _3 : '',
|
|
63
|
+
preferred_family: (_5 = (_4 = names === null || names === void 0 ? void 0 : names.preferredFamily) === null || _4 === void 0 ? void 0 : _4.en) !== null && _5 !== void 0 ? _5 : '',
|
|
64
|
+
preferred_sub_family: (_7 = (_6 = names === null || names === void 0 ? void 0 : names.preferredSubfamily) === null || _6 === void 0 ? void 0 : _6.en) !== null && _7 !== void 0 ? _7 : '',
|
|
65
|
+
sample_text: (_9 = (_8 = names === null || names === void 0 ? void 0 : names.sampleText) === null || _8 === void 0 ? void 0 : _8.en) !== null && _9 !== void 0 ? _9 : '',
|
|
66
|
+
trademark: (_11 = (_10 = names === null || names === void 0 ? void 0 : names.trademark) === null || _10 === void 0 ? void 0 : _10.en) !== null && _11 !== void 0 ? _11 : '',
|
|
67
|
+
unique_id: (_13 = (_12 = names === null || names === void 0 ? void 0 : names.uniqueSubfamily) === null || _12 === void 0 ? void 0 : _12.en) !== null && _13 !== void 0 ? _13 : '',
|
|
68
|
+
version: (_15 = (_14 = names === null || names === void 0 ? void 0 : names.version) === null || _14 === void 0 ? void 0 : _14.en) !== null && _15 !== void 0 ? _15 : '',
|
|
69
|
+
};
|
|
70
|
+
return this.namesTable;
|
|
51
71
|
}
|
|
52
72
|
}
|
|
53
73
|
exports.default = FontObject;
|
package/app/core/FontObject.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
const fontkit = require(
|
|
1
|
+
const fontkit = require('fontkit');
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const MAX_CACHE_SIZE = 50;
|
|
4
|
+
const fontCache = new Map<string, FontObject>();
|
|
4
5
|
|
|
6
|
+
export default class FontObject {
|
|
5
7
|
font: any;
|
|
6
8
|
error: any;
|
|
9
|
+
private namesTable: any;
|
|
7
10
|
|
|
8
11
|
constructor(fp: string) {
|
|
9
12
|
try {
|
|
@@ -13,6 +16,20 @@ export default class FontObject {
|
|
|
13
16
|
}
|
|
14
17
|
}
|
|
15
18
|
|
|
19
|
+
static fromCache(fp: string): FontObject {
|
|
20
|
+
const cached = fontCache.get(fp);
|
|
21
|
+
if (cached) return cached;
|
|
22
|
+
const obj = new FontObject(fp);
|
|
23
|
+
if (!obj.hasError()) {
|
|
24
|
+
if (fontCache.size >= MAX_CACHE_SIZE) {
|
|
25
|
+
const firstKey = fontCache.keys().next().value;
|
|
26
|
+
fontCache.delete(firstKey);
|
|
27
|
+
}
|
|
28
|
+
fontCache.set(fp, obj);
|
|
29
|
+
}
|
|
30
|
+
return obj;
|
|
31
|
+
}
|
|
32
|
+
|
|
16
33
|
setFont(font: any) {
|
|
17
34
|
this.font = font;
|
|
18
35
|
}
|
|
@@ -30,33 +47,36 @@ export default class FontObject {
|
|
|
30
47
|
}
|
|
31
48
|
|
|
32
49
|
hasError() {
|
|
33
|
-
return this.error
|
|
50
|
+
return !!this.error;
|
|
34
51
|
}
|
|
35
52
|
|
|
36
53
|
getNamesTable() {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
if (this.namesTable) return this.namesTable;
|
|
55
|
+
|
|
56
|
+
const names = this.font?.name?.records;
|
|
57
|
+
|
|
58
|
+
this.namesTable = {
|
|
59
|
+
compatible_full_name: names?.compatibleFullName?.en ?? '',
|
|
60
|
+
copyright: names?.copyright?.en ?? '',
|
|
61
|
+
description: names?.description?.en ?? '',
|
|
62
|
+
designer: names?.designer?.en ?? '',
|
|
63
|
+
designer_url: names?.designerURL?.en ?? '',
|
|
64
|
+
font_family: names?.fontFamily?.en ?? '',
|
|
65
|
+
font_subfamily: names?.fontSubfamily?.en ?? '',
|
|
66
|
+
full_name: names?.fullName?.en ?? '',
|
|
67
|
+
license: names?.license?.en ?? '',
|
|
68
|
+
license_url: names?.licenseURL?.en ?? '',
|
|
69
|
+
manufacturer: names?.manufacturer?.en ?? '',
|
|
70
|
+
manufacturer_url: names?.manufacturerURL?.en ?? '',
|
|
71
|
+
post_script_name: names?.postScriptName?.en ?? '',
|
|
72
|
+
preferred_family: names?.preferredFamily?.en ?? '',
|
|
73
|
+
preferred_sub_family: names?.preferredSubfamily?.en ?? '',
|
|
74
|
+
sample_text: names?.sampleText?.en ?? '',
|
|
75
|
+
trademark: names?.trademark?.en ?? '',
|
|
76
|
+
unique_id: names?.uniqueSubfamily?.en ?? '',
|
|
77
|
+
version: names?.version?.en ?? '',
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return this.namesTable;
|
|
61
81
|
}
|
|
62
82
|
}
|