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
|
@@ -26,9 +26,7 @@
|
|
|
26
26
|
<button
|
|
27
27
|
class="px-2 py-0.5 rounded cursor-pointer text-[10px] transition-colors"
|
|
28
28
|
[style.color]="'var(--text-secondary)'"
|
|
29
|
-
[
|
|
30
|
-
(mouseenter)="$any($event.currentTarget).style.backgroundColor = 'var(--hover-bg)'"
|
|
31
|
-
(mouseleave)="$any($event.currentTarget).style.backgroundColor = 'transparent'"
|
|
29
|
+
[appHoverHighlight]="false"
|
|
32
30
|
(click)="onReset()"
|
|
33
31
|
>
|
|
34
32
|
Clear
|
|
@@ -64,15 +62,7 @@
|
|
|
64
62
|
<label
|
|
65
63
|
class="flex items-center gap-2 px-2 py-1 rounded cursor-pointer text-[11px] transition-colors"
|
|
66
64
|
[style.color]="'var(--text-secondary)'"
|
|
67
|
-
[
|
|
68
|
-
(mouseenter)="
|
|
69
|
-
$any($event.currentTarget).style.backgroundColor = isSearchFieldSelected(sf.value)
|
|
70
|
-
? 'var(--selected-bg)'
|
|
71
|
-
: 'var(--hover-bg)'
|
|
72
|
-
"
|
|
73
|
-
(mouseleave)="
|
|
74
|
-
$any($event.currentTarget).style.backgroundColor = isSearchFieldSelected(sf.value) ? 'var(--selected-bg)' : 'transparent'
|
|
75
|
-
"
|
|
65
|
+
[appHoverHighlight]="isSearchFieldSelected(sf.value)"
|
|
76
66
|
>
|
|
77
67
|
<input
|
|
78
68
|
type="checkbox"
|
|
@@ -96,15 +86,7 @@
|
|
|
96
86
|
<label
|
|
97
87
|
class="flex items-center gap-2 px-2 py-1 rounded cursor-pointer text-[11px] transition-colors"
|
|
98
88
|
[style.color]="'var(--text-secondary)'"
|
|
99
|
-
[
|
|
100
|
-
(mouseenter)="
|
|
101
|
-
$any($event.currentTarget).style.backgroundColor = isFileTypeSelected(ft.value)
|
|
102
|
-
? 'var(--selected-bg)'
|
|
103
|
-
: 'var(--hover-bg)'
|
|
104
|
-
"
|
|
105
|
-
(mouseleave)="
|
|
106
|
-
$any($event.currentTarget).style.backgroundColor = isFileTypeSelected(ft.value) ? 'var(--selected-bg)' : 'transparent'
|
|
107
|
-
"
|
|
89
|
+
[appHoverHighlight]="isFileTypeSelected(ft.value)"
|
|
108
90
|
>
|
|
109
91
|
<input
|
|
110
92
|
type="checkbox"
|
|
@@ -125,9 +107,7 @@
|
|
|
125
107
|
<label
|
|
126
108
|
class="flex items-center gap-2 px-2 py-1 rounded cursor-pointer text-[11px] transition-colors"
|
|
127
109
|
[style.color]="'var(--text-secondary)'"
|
|
128
|
-
[
|
|
129
|
-
(mouseenter)="$any($event.currentTarget).style.backgroundColor = favoritesOnly ? 'var(--selected-bg)' : 'var(--hover-bg)'"
|
|
130
|
-
(mouseleave)="$any($event.currentTarget).style.backgroundColor = favoritesOnly ? 'var(--selected-bg)' : 'transparent'"
|
|
110
|
+
[appHoverHighlight]="favoritesOnly"
|
|
131
111
|
>
|
|
132
112
|
<input type="checkbox" class="accent-current" [(ngModel)]="favoritesOnly" />
|
|
133
113
|
Favorites Only
|
|
@@ -135,9 +115,7 @@
|
|
|
135
115
|
<label
|
|
136
116
|
class="flex items-center gap-2 px-2 py-1 rounded cursor-pointer text-[11px] transition-colors"
|
|
137
117
|
[style.color]="'var(--text-secondary)'"
|
|
138
|
-
[
|
|
139
|
-
(mouseenter)="$any($event.currentTarget).style.backgroundColor = systemOnly ? 'var(--selected-bg)' : 'var(--hover-bg)'"
|
|
140
|
-
(mouseleave)="$any($event.currentTarget).style.backgroundColor = systemOnly ? 'var(--selected-bg)' : 'transparent'"
|
|
118
|
+
[appHoverHighlight]="systemOnly"
|
|
141
119
|
>
|
|
142
120
|
<input type="checkbox" class="accent-current" [(ngModel)]="systemOnly" />
|
|
143
121
|
System Fonts Only
|
|
@@ -145,9 +123,7 @@
|
|
|
145
123
|
<label
|
|
146
124
|
class="flex items-center gap-2 px-2 py-1 rounded cursor-pointer text-[11px] transition-colors"
|
|
147
125
|
[style.color]="'var(--text-secondary)'"
|
|
148
|
-
[
|
|
149
|
-
(mouseenter)="$any($event.currentTarget).style.backgroundColor = installedOnly ? 'var(--selected-bg)' : 'var(--hover-bg)'"
|
|
150
|
-
(mouseleave)="$any($event.currentTarget).style.backgroundColor = installedOnly ? 'var(--selected-bg)' : 'transparent'"
|
|
126
|
+
[appHoverHighlight]="installedOnly"
|
|
151
127
|
>
|
|
152
128
|
<input type="checkbox" class="accent-current" [(ngModel)]="installedOnly" />
|
|
153
129
|
Installed Only
|
|
@@ -292,11 +268,10 @@
|
|
|
292
268
|
<div class="flex gap-2 pt-5">
|
|
293
269
|
<button
|
|
294
270
|
class="flex-1 px-3 py-1.5 rounded text-[11px] font-medium cursor-pointer transition-colors"
|
|
295
|
-
[style.background-color]="'var(--selected-bg)'"
|
|
296
271
|
[style.color]="'var(--text-primary)'"
|
|
297
272
|
[style.border]="'1px solid var(--border-default)'"
|
|
298
|
-
|
|
299
|
-
|
|
273
|
+
[appHoverHighlight]="false"
|
|
274
|
+
normalBg="var(--selected-bg)"
|
|
300
275
|
(click)="onSearch()"
|
|
301
276
|
>
|
|
302
277
|
<span class="flex items-center justify-center gap-1">
|
|
@@ -316,9 +291,7 @@
|
|
|
316
291
|
class="px-3 py-1.5 rounded text-[11px] cursor-pointer transition-colors"
|
|
317
292
|
[style.color]="'var(--text-muted)'"
|
|
318
293
|
[style.border]="'1px solid var(--border-subtle)'"
|
|
319
|
-
[
|
|
320
|
-
(mouseenter)="$any($event.currentTarget).style.backgroundColor = 'var(--hover-bg)'"
|
|
321
|
-
(mouseleave)="$any($event.currentTarget).style.backgroundColor = 'transparent'"
|
|
294
|
+
[appHoverHighlight]="false"
|
|
322
295
|
(click)="onReset()"
|
|
323
296
|
>
|
|
324
297
|
Reset
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Component, inject, signal } from '@angular/core';
|
|
2
2
|
import { FormsModule } from '@angular/forms';
|
|
3
3
|
import { DatabaseService, PresentationService } from '../../../core/services';
|
|
4
|
+
import { HoverHighlightDirective } from '../../directives/hover-highlight/hover-highlight.directive';
|
|
4
5
|
import type { Collection } from '@main/database/entity/Collection.schema';
|
|
5
6
|
|
|
6
7
|
const FILE_TYPES = [
|
|
@@ -45,7 +46,7 @@ const SORT_OPTIONS = [
|
|
|
45
46
|
@Component({
|
|
46
47
|
selector: 'app-search',
|
|
47
48
|
standalone: true,
|
|
48
|
-
imports: [FormsModule],
|
|
49
|
+
imports: [FormsModule, HoverHighlightDirective],
|
|
49
50
|
templateUrl: './search.component.html',
|
|
50
51
|
})
|
|
51
52
|
export class SearchComponent {
|
|
@@ -67,9 +67,7 @@
|
|
|
67
67
|
class="px-2 py-0.5 rounded cursor-pointer text-[10px] transition-colors"
|
|
68
68
|
[style.color]="'var(--text-secondary)'"
|
|
69
69
|
[style.border]="'1px solid var(--border-default)'"
|
|
70
|
-
[
|
|
71
|
-
(mouseenter)="$any($event.currentTarget).style.backgroundColor = 'var(--hover-bg)'"
|
|
72
|
-
(mouseleave)="$any($event.currentTarget).style.backgroundColor = 'transparent'"
|
|
70
|
+
[appHoverHighlight]="false"
|
|
73
71
|
(click)="resetScale()"
|
|
74
72
|
title="Reset scale"
|
|
75
73
|
>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Component, inject, computed, signal } from '@angular/core';
|
|
2
2
|
import { FormsModule } from '@angular/forms';
|
|
3
3
|
import { DatabaseService, PresentationService } from '../../../core/services';
|
|
4
|
+
import { HoverHighlightDirective } from '../../directives/hover-highlight/hover-highlight.directive';
|
|
4
5
|
import { fontTypeScale } from '@main/config/system';
|
|
5
6
|
|
|
6
7
|
interface ScaleItem {
|
|
@@ -14,7 +15,7 @@ interface ScaleItem {
|
|
|
14
15
|
@Component({
|
|
15
16
|
selector: 'app-waterfall',
|
|
16
17
|
standalone: true,
|
|
17
|
-
imports: [FormsModule],
|
|
18
|
+
imports: [FormsModule, HoverHighlightDirective],
|
|
18
19
|
templateUrl: './waterfall.component.html',
|
|
19
20
|
})
|
|
20
21
|
export class WaterfallComponent {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Directive, ElementRef, Input, OnChanges, inject } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Directive({
|
|
4
|
+
selector: '[appDisabledOpacity]',
|
|
5
|
+
standalone: true,
|
|
6
|
+
})
|
|
7
|
+
export class DisabledOpacityDirective implements OnChanges {
|
|
8
|
+
@Input('appDisabledOpacity') isDisabled = false;
|
|
9
|
+
@Input() opacityValue = '0.3';
|
|
10
|
+
|
|
11
|
+
private el = inject(ElementRef);
|
|
12
|
+
|
|
13
|
+
ngOnChanges() {
|
|
14
|
+
const el = this.el.nativeElement;
|
|
15
|
+
el.disabled = this.isDisabled;
|
|
16
|
+
el.style.opacity = this.isDisabled ? this.opacityValue : '';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Directive, ElementRef, HostListener, Input, OnChanges, inject } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Directive({
|
|
4
|
+
selector: '[appHoverHighlight]',
|
|
5
|
+
standalone: true,
|
|
6
|
+
})
|
|
7
|
+
export class HoverHighlightDirective implements OnChanges {
|
|
8
|
+
@Input('appHoverHighlight') selected = false;
|
|
9
|
+
@Input() hoverBg = 'var(--hover-bg)';
|
|
10
|
+
@Input() selectedBg = 'var(--selected-bg)';
|
|
11
|
+
@Input() normalBg = 'transparent';
|
|
12
|
+
@Input() selectedColor = '';
|
|
13
|
+
@Input() normalColor = '';
|
|
14
|
+
|
|
15
|
+
private el = inject(ElementRef);
|
|
16
|
+
|
|
17
|
+
ngOnChanges() {
|
|
18
|
+
this.applyStyles();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@HostListener('mouseenter')
|
|
22
|
+
onMouseEnter() {
|
|
23
|
+
this.el.nativeElement.style.backgroundColor = this.selected ? this.selectedBg : this.hoverBg;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@HostListener('mouseleave')
|
|
27
|
+
onMouseLeave() {
|
|
28
|
+
this.applyStyles();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private applyStyles() {
|
|
32
|
+
const el = this.el.nativeElement;
|
|
33
|
+
el.style.backgroundColor = this.selected ? this.selectedBg : this.normalBg;
|
|
34
|
+
if (this.selectedColor || this.normalColor) {
|
|
35
|
+
el.style.color = this.selected ? this.selectedColor : this.normalColor;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
export * from './autofocus/autofocus.directive';
|
|
2
|
+
export * from './disabled-opacity/disabled-opacity.directive';
|
|
3
|
+
export * from './hover-highlight/hover-highlight.directive';
|
|
4
|
+
export * from './modal-backdrop/modal-backdrop.directive';
|
|
5
|
+
export * from './scroll-reset/scroll-reset.directive';
|
|
6
|
+
export * from './stop-propagation/stop-propagation.directive';
|
|
2
7
|
export * from './webview/webview.directive';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Directive, ElementRef, HostListener, Output, EventEmitter, inject } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Directive({
|
|
4
|
+
selector: '[appModalBackdrop]',
|
|
5
|
+
standalone: true,
|
|
6
|
+
})
|
|
7
|
+
export class ModalBackdropDirective {
|
|
8
|
+
@Output() backdropClick = new EventEmitter<void>();
|
|
9
|
+
|
|
10
|
+
private el = inject(ElementRef);
|
|
11
|
+
|
|
12
|
+
@HostListener('click', ['$event'])
|
|
13
|
+
onClick(event: MouseEvent) {
|
|
14
|
+
if (event.target === this.el.nativeElement) {
|
|
15
|
+
this.backdropClick.emit();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Directive, ElementRef, Input, OnChanges, inject } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Directive({
|
|
4
|
+
selector: '[appScrollReset]',
|
|
5
|
+
standalone: true,
|
|
6
|
+
})
|
|
7
|
+
export class ScrollResetDirective implements OnChanges {
|
|
8
|
+
@Input('appScrollReset') trigger: unknown;
|
|
9
|
+
|
|
10
|
+
private el = inject(ElementRef);
|
|
11
|
+
|
|
12
|
+
ngOnChanges() {
|
|
13
|
+
this.el.nativeElement.scrollTo(0, 0);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Directive, HostListener } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Directive({
|
|
4
|
+
selector: '[appStopPropagation]',
|
|
5
|
+
standalone: true,
|
|
6
|
+
})
|
|
7
|
+
export class StopPropagationDirective {
|
|
8
|
+
@HostListener('click', ['$event'])
|
|
9
|
+
onClick(event: Event) {
|
|
10
|
+
event.stopPropagation();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/favicon.ico
CHANGED
|
Binary file
|