Skip to content

Commit 135b5cf

Browse files
committed
add shikimori graphql types for user rates
1 parent 6024ad9 commit 135b5cf

File tree

101 files changed

+1253
-639
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+1253
-639
lines changed

package-lock.json

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

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,11 @@
7171
"@ngrx/store": "^19.0.0",
7272
"date-fns": "^4.1.0",
7373
"deep-object-diff": "^1.1.9",
74+
"fflate": "^0.8.2",
7475
"ionicons": "^8.0.8",
7576
"ngrx-store-localstorage": "19.0.0",
7677
"ngx-scrollbar": "^18.0.0",
7778
"ngx-tippy-wrapper": "^6.3.0",
78-
"ngx-visibility": "2.0.0",
7979
"ngxtension": "^5.1.0",
8080
"rxjs": "~7.8.1",
8181
"tslib": "^2.6.2"
@@ -134,4 +134,4 @@
134134
"typescript": "~5.8.3",
135135
"webpack": "^5.89.0"
136136
}
137-
}
137+
}

src/app/modules/home/components/anime-rate-section/anime-rate-section.component.html

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
<div
2-
class="anime-rate-section__label"
3-
(ngxVisibility)="onSectionVisible($event)"
4-
>
1+
<div class="anime-rate-section__label">
52
<ion-text class="anime-rate-section__text">
63
{{ label() | transloco | uppercase }}
74

8-
@if (isLoaded()) {
5+
@if (!isRatesLoading()) {
96
<span class="anime-rate-section__counter">({{ ratesCount() }})</span>
107
}
118
</ion-text>
@@ -28,6 +25,7 @@
2825
class="anime-rate-section__grid"
2926
[class.ion-hide]="isHidden()"
3027
[userAnimeRates]="rates()"
31-
[isLoading]="!isLoaded()"
32-
(ngxVisibility)="onSectionVisible($event)"
28+
[ratesMetadata]="ratesMetadata()"
29+
[isRatesLoading]="isRatesLoading()"
30+
[isMetaLoading]="isMetaLoading()"
3331
/>

src/app/modules/home/components/anime-rate-section/anime-rate-section.component.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@ import {
77
output,
88
} from '@angular/core';
99
import { IonButton, IonIcon, IonText } from '@ionic/angular/standalone';
10-
import { NgxVisibilityDirective } from 'ngx-visibility';
1110
import { TranslocoPipe } from '@jsverse/transloco';
1211
import { UpperCasePipe } from '@angular/common';
1312

13+
import { AnimeRatesMetadata } from '@app/modules/home/store/anime-rates';
1414
import { CardGridComponent } from '@app/modules/home/components/card-grid';
15-
import { UserAnimeRate } from '@app/shared/types/shikimori/user-anime-rate';
15+
import { UserBriefRateInterface } from '@app/shared/types/shikimori';
1616

1717
@Component({
1818
selector: 'app-anime-rate-section',
1919
imports: [
20-
NgxVisibilityDirective,
2120
TranslocoPipe,
2221
IonIcon,
2322
IonButton,
@@ -32,31 +31,28 @@ import { UserAnimeRate } from '@app/shared/types/shikimori/user-anime-rate';
3231
host: {
3332
'class': 'anime-rate-section',
3433
'[id]': 'status()',
35-
'[class.ion-hide]': 'isSectionHidden(isLoaded(), rates())',
34+
'[class.ion-hide]': 'isSectionHidden(!isRatesLoading(), rates())',
3635
},
3736
})
3837
export class AnimeRateSectionComponent {
3938
label = input.required<string>();
4039
status = input.required<string>();
41-
rates = input.required<UserAnimeRate[]>();
40+
rates = input.required<UserBriefRateInterface[]>();
41+
ratesMetadata = input.required<AnimeRatesMetadata>();
42+
4243
isHidden = input(false);
43-
isLoaded = input(false);
44+
isRatesLoading = input(true);
45+
isMetaLoading = input(true);
4446

4547
visible = output();
4648
toggleHidden = output();
4749

4850
ratesCount = computed(() => this.rates()?.length || 0);
4951

50-
isSectionHidden(isLoaded: boolean, rates: UserAnimeRate[]): boolean {
52+
isSectionHidden(isLoaded: boolean, rates: UserBriefRateInterface[]): boolean {
5153
return isLoaded && !rates?.length;
5254
}
5355

54-
onSectionVisible(isVisible: boolean): void {
55-
if (isVisible) {
56-
this.visible.emit();
57-
}
58-
}
59-
6056
onToggleHidden(): void {
6157
this.toggleHidden.emit();
6258
}

src/app/modules/home/components/card-grid-item/card-grid-item.component.html

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,37 +15,48 @@
1515
/>
1616
</a>
1717

18-
@if (isLoading) {
18+
@if (isLoading() || isMetaLoading()) {
1919
<app-skeleton-block
20-
class="card-grid-item__name card-grid-item__name--skeleton"
21-
[height]="'33px'"
22-
[width]="width()"
20+
class="card-grid-item__name"
21+
height="1.08rem"
22+
width="100%"
23+
borderRadius="0.25rem"
2324
/>
24-
}
2525

26-
<h2
27-
class="card-grid-item__name"
28-
[class.ion-hide]="isLoading"
29-
[ngxTippy]="name()"
30-
[tippyProps]="{
31-
'placement': 'top'
32-
}"
33-
[ngStyle]="{
34-
'max-width': width()
35-
}"
36-
>
37-
{{ name() }}
38-
</h2>
26+
<div class="card-grid-item__other-info card-grid-item__other-info--skeleton">
27+
<app-skeleton-block
28+
height="0.8625rem"
29+
width="3rem"
30+
borderRadius="0.25rem"
31+
/>
3932

40-
<footer
41-
class="card-grid-item__other-info"
42-
[class.ion-hide]="isLoading"
43-
>
44-
@if (kind()) {
45-
<span>{{ 'GLOBAL.SHIKIMORI.ANIME_KINDS.' + (kind() | uppercase) | transloco }}</span>
46-
}
33+
<app-skeleton-block
34+
height="0.8625rem"
35+
width="2.5rem"
36+
borderRadius="0.25rem"
37+
/>
38+
</div>
39+
} @else {
40+
<h2
41+
class="card-grid-item__name"
42+
[ngxTippy]="name()"
43+
[tippyProps]="{
44+
'placement': 'top'
45+
}"
46+
[ngStyle]="{
47+
'max-width': width()
48+
}"
49+
>
50+
{{ name() }}
51+
</h2>
4752

48-
@if (releaseDate()) {
49-
<time [dateTime]="releaseDate()">{{ releaseDate() | date: 'YYYY' }}</time>
50-
}
51-
</footer>
53+
<footer class="card-grid-item__other-info">
54+
@if (kind()) {
55+
<span>{{ 'GLOBAL.SHIKIMORI.ANIME_KINDS.' + (kind() | uppercase) | transloco }}</span>
56+
}
57+
58+
@if (releaseDate()) {
59+
<time [dateTime]="releaseDate()">{{ releaseDate() | date: 'YYYY' }}</time>
60+
}
61+
</footer>
62+
}

src/app/modules/home/components/card-grid-item/card-grid-item.component.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
.card-grid-item {
44
display: flex;
55
flex-direction: column;
6+
// скрываем alt текст для картинок на фоне (т.к. он всё равно заблюрен)
7+
font-size: 0;
68

79
:focus {
810
outline: 0.25rem solid var(--ion-color-primary);
@@ -24,9 +26,14 @@
2426
display: flex;
2527
flex-direction: row;
2628
justify-content: space-between;
29+
30+
&--skeleton {
31+
margin-top: 1px;
32+
}
2733
}
2834

2935
.wrapper {
3036
display: contents;
37+
position: relative;
3138
}
3239
}

src/app/modules/home/components/card-grid-item/card-grid-item.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,7 @@ export class CardGridItemComponent extends AbstractImageCardComponent {
4646

4747
link = input('#');
4848

49+
isMetaLoading = input(true);
50+
4951
mouseOver = false;
5052
}

src/app/modules/home/components/card-grid/card-grid.component.html

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
@if (userAnimeRates()?.length) {
2-
@for (rate of userAnimeRates(); track $index) {
2+
@for (rate of userAnimeRates(); track trackById($index, rate)) {
3+
@let animeId = rate.target_id;
4+
35
<app-card-grid-item
46
class="anime-grid__item"
57
height="100%"
68
width="auto"
7-
[link]="rate.anime | getPlayerLink"
8-
[imageUrl]="rate.anime?.image?.original"
9-
[name]="rate.anime | getAnimeName: currentLang()"
10-
[kind]="rate.anime.kind"
11-
[releaseDate]="rate.anime.released_on || rate.anime.aired_on"
9+
[link]="animeId | getPlayerLink"
10+
[imageUrl]="animeId | getAnimePoster: ratesMetadata()"
11+
[name]="animeId | getAnimeName: currentLang(): ratesMetadata()"
12+
[kind]="animeId | getAnimeKind: ratesMetadata()"
13+
[releaseDate]="animeId | getAnimeReleaseDate: ratesMetadata()"
14+
[isMetaLoading]="isMetaLoading()"
1215
/>
13-
}
14-
15-
@if (isLoading()) {
16-
<ng-container [ngTemplateOutlet]="skeletonTemplate" />
16+
} @empty {
17+
@if (isRatesLoading()) {
18+
<ng-container [ngTemplateOutlet]="skeletonTemplate" />
19+
}
1720
}
1821
} @else {
1922
<ng-container [ngTemplateOutlet]="skeletonTemplate" />
@@ -42,14 +45,14 @@
4245
class="skeleton-item__text"
4346
height="0.8625rem"
4447
width="3rem"
45-
borderRadius="0.25rem"
48+
borderRadius="0.25rem"
4649
/>
4750

4851
<app-skeleton-block
4952
class="skeleton-item__text"
5053
height="0.8625rem"
5154
width="2.5rem"
52-
borderRadius="0.25rem"
55+
borderRadius="0.25rem"
5356
/>
5457
</div>
5558
</div>
Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
ChangeDetectionStrategy,
33
Component,
4-
HostBinding,
54
ViewEncapsulation,
65
inject,
76
input,
@@ -11,12 +10,19 @@ import { RepeatPipe } from 'ngxtension/repeat-pipe';
1110
import { TranslocoService } from '@jsverse/transloco';
1211
import { toSignal } from '@angular/core/rxjs-interop';
1312

13+
import { AnimeRatesMetadata } from '@app/modules/home/store/anime-rates';
1414
import { CardGridItemComponent } from '@app/modules/home/components/card-grid-item/card-grid-item.component';
15-
import { GetAnimeNamePipe } from '@app/shared/pipes/get-anime-name/get-anime-name.pipe';
15+
import {
16+
GetAnimeKindPipe,
17+
GetAnimeNamePipe,
18+
GetAnimePosterPipe,
19+
GetAnimeReleaseDatePipe,
20+
} from '@app/modules/home/pipes';
1621
import { GetPlayerLinkPipe } from '@app/shared/pipes/get-player-link/get-player-link.pipe';
1722
import { SkeletonBlockComponent } from '@app/shared/components/skeleton-block/skeleton-block.component';
18-
import { UserAnimeRate } from '@app/shared/types/shikimori/user-anime-rate';
23+
import { UserBriefRateInterface } from '@app/shared/types/shikimori';
1924
import { provideShikimoriImageLoader } from '@app/shared/providers/shikimori-image-loader.provider';
25+
import { trackById } from '@app/shared/utils/common-ngfor-tracking';
2026

2127
@Component({
2228
selector: 'app-card-grid',
@@ -29,22 +35,26 @@ import { provideShikimoriImageLoader } from '@app/shared/providers/shikimori-ima
2935
GetPlayerLinkPipe,
3036
GetAnimeNamePipe,
3137
RepeatPipe,
38+
GetAnimePosterPipe,
39+
GetAnimeKindPipe,
40+
GetAnimeReleaseDatePipe,
3241
],
3342
providers: [
3443
provideShikimoriImageLoader(96),
3544
],
3645
changeDetection: ChangeDetectionStrategy.OnPush,
3746
encapsulation: ViewEncapsulation.None,
47+
host: { class: 'anime-grid' },
3848
})
3949
export class CardGridComponent {
40-
@HostBinding('class.anime-grid')
41-
private animeGridClass = true;
42-
4350
private readonly _transloco = inject(TranslocoService);
4451

52+
readonly trackById = trackById;
4553
readonly currentLang = toSignal(this._transloco.langChanges$);
4654

47-
userAnimeRates = input<UserAnimeRate[]>();
55+
userAnimeRates = input.required<UserBriefRateInterface[]>();
56+
ratesMetadata = input.required<AnimeRatesMetadata>();
4857

49-
isLoading = input<boolean>();
58+
isRatesLoading = input(true);
59+
isMetaLoading = input(true);
5060
}

src/app/modules/home/home.page.html

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
<ion-content [fullscreen]="true" class="page-content ion-padding">
22
@for (status of animeStatusOrder(); track status) {
3-
@let grid = animeGridMap.get(status);
3+
@let userRatesForStatus = userAnimeRatesWithRecent() | filterRatesByStatus: status;
4+
@let sortedUserRates = status === 'recent'
5+
? (userRatesForStatus | slice: 0: 6 | sortRatesByDateVisited)
6+
: (userRatesForStatus | sortRatesByUserScore: ratesMetadata(): 'original': false);
47

58
<app-anime-rate-section
69
class="home-page__anime-rates"
710
[label]="'HOME_MODULE.HOME_PAGE.GRIDS.' + (status | uppercase)"
811
[status]="status"
9-
[rates]="grid.rates | async"
10-
[isLoaded]="grid.isLoaded | async"
12+
[rates]="sortedUserRates"
13+
[ratesMetadata]="ratesMetadata()"
14+
[isRatesLoading]="isRatesLoading()"
15+
[isMetaLoading]="isMetadataLoading()"
1116
[isHidden]="getHiddenGridStatus(status)"
12-
(visible)="onSectionVisibilityChange(status)"
1317
(toggleHidden)="toggleHiddenGridStatus(status)"
1418
/>
1519
}

0 commit comments

Comments
 (0)