@@ -9,6 +9,8 @@ import {NgbOffcanvas} from '@ng-bootstrap/ng-bootstrap';
99import { V2SongScoreRankingComponent } from '../v2-song-score-ranking/v2-song-score-ranking.component' ;
1010import { FormArray , FormControl } from '@angular/forms' ;
1111import { combineLatest , debounceTime , distinctUntilChanged , lastValueFrom , map , Observable , startWith } from 'rxjs' ;
12+ import { Collapse } from 'bootstrap' ;
13+ import { ReleaseTagService } from '../util/release-tag.service' ;
1214
1315
1416@Component ( {
@@ -18,34 +20,41 @@ import {combineLatest, debounceTime, distinctUntilChanged, lastValueFrom, map, O
1820} )
1921export class V2SonglistComponent implements OnInit {
2022
21- genres = [ 'POPS_ANIME' , 'NICONICO' , 'TOUHOU' , 'VARIETY' , 'GEKICHUMA' , 'IRODORI' , 'ORIGINAL' ] ;
22- genresMap = new Map ( [
23+ filterCollapsed = true ;
24+ filterCollapse : Collapse ;
25+ songList : ChusanMusic [ ] = [ ] ;
26+ filteredSongList : Observable < ChusanMusic [ ] > ;
27+ displayedColumns : string [ ] = [ 'musicId' , 'name' , 'artistName' ] ;
28+ host = environment . assetsHost ;
29+
30+ genreMap = new Map ( [
2331 [ 'POPS_ANIME' , 'POPS & ANIME' ] ,
2432 [ 'NICONICO' , 'niconico' ] ,
2533 [ 'TOUHOU' , '東方Project' ] ,
2634 [ 'VARIETY' , 'VARIETY' ] ,
27- [ 'GEKICHUMA' , 'ゲキマイ' ] ,
2835 [ 'IRODORI' , 'イロドリミドリ' ] ,
36+ [ 'GEKICHUMA' , 'ゲキマイ' ] ,
2937 [ 'ORIGINAL' , 'ORIGINAL' ]
3038 ] ) ;
31- songList : ChusanMusic [ ] = [ ] ;
32- filteredSongList : Observable < ChusanMusic [ ] > ;
33- displayedColumns : string [ ] = [ 'musicId' , 'name' , 'artistName' ] ;
34- host = environment . assetsHost ;
39+ genres : string [ ] = [ ...this . genreMap . keys ( ) ] ;
40+
3541 currentPage : 1 ;
3642 totalElements = 0 ;
43+ versionControls = new FormArray < FormControl < boolean > > ( [ ] ) ;
3744 genreControls = new FormArray < FormControl < boolean > > ( [ ] ) ;
3845 weControl = new FormControl ( false ) ;
3946 patternControl = new FormControl ( '' ) ;
4047
4148 constructor (
49+ public releaseTagService : ReleaseTagService ,
50+ public router : Router ,
51+ public route : ActivatedRoute ,
4252 private dbService : NgxIndexedDBService ,
4353 private api : ApiService ,
4454 private messageService : MessageService ,
45- public router : Router ,
46- public route : ActivatedRoute ,
4755 private offcanvasService : NgbOffcanvas ,
4856 ) {
57+ this . releaseTagService . releaseTags . forEach ( ( ) => this . versionControls . push ( new FormControl ( false ) ) ) ;
4958 this . genres . forEach ( ( ) => this . genreControls . push ( new FormControl ( false ) ) ) ;
5059 }
5160
@@ -63,27 +72,44 @@ export class V2SonglistComponent implements OnInit {
6372
6473 this . filteredSongList = combineLatest ( [
6574 this . genreControls . valueChanges . pipe ( startWith ( new Array < boolean > ( ) ) ) ,
75+ this . versionControls . valueChanges . pipe ( startWith ( new Array < boolean > ( ) ) ) ,
6676 this . patternControl . valueChanges . pipe ( startWith ( '' ) ) ,
6777 this . weControl . valueChanges . pipe ( startWith ( false ) ) ,
6878 ] ) . pipe (
6979 debounceTime ( 200 ) ,
7080 distinctUntilChanged ( ) ,
71- map ( ( [ genreValues , pattern , weChecked ] ) => {
81+ map ( ( [ genreValues , versionValues , pattern , weChecked ] ) => {
82+ let selectedVersions = this . releaseTagService . releaseTags . filter ( ( _ , index ) => versionValues [ index ] ) ;
83+ if ( selectedVersions . length === 0 && ! weChecked ) {
84+ selectedVersions = this . releaseTagService . releaseTags ;
85+ }
86+
7287 let selectedGenres = this . genres . filter ( ( _ , index ) => genreValues [ index ] ) ;
7388 if ( selectedGenres . length === 0 && ! weChecked ) {
7489 selectedGenres = this . genres ;
7590 }
7691
77- let filtered = this . songList ;
78- if ( selectedGenres . length !== this . genres . length ) {
79- filtered = filtered . filter ( song => selectedGenres . includes ( song . genre ) || ( weChecked && song . levels [ '5' ] . enable ) ) ;
80- }
81- filtered = filtered . filter ( song => this . filterByPattern ( song , pattern ) ) ;
82- return filtered ;
92+ return this . filterSongs ( selectedGenres , selectedVersions , weChecked , pattern ) ;
8393 } )
8494 ) ;
8595 }
8696
97+ filterSongs ( selectedGenres : string [ ] , selectedVersions : string [ ] , weChecked : boolean , pattern : string ) {
98+ let filtered = this . songList ;
99+ if ( weChecked ) {
100+ filtered = filtered . filter ( song => song . levels [ '5' ] . enable ) ;
101+ }
102+ if ( selectedVersions . length !== this . releaseTagService . releaseTags . length ) {
103+ filtered = filtered . filter ( song => selectedVersions . includes ( song . releaseVersion ) ) ;
104+ }
105+ if ( selectedGenres . length !== this . genreMap . size ) {
106+ filtered = filtered . filter ( song => selectedGenres . includes ( song . genre ) ) ;
107+ }
108+ filtered = filtered . filter ( song => this . filterByPattern ( song , pattern ) ) ;
109+ this . totalElements = filtered . length ;
110+ return filtered ;
111+ }
112+
87113 pageChanged ( page : number ) {
88114 this . router . navigate ( [ 'chuni/v2/song' ] , { queryParams : { page} } ) ;
89115 }
@@ -97,6 +123,37 @@ export class V2SonglistComponent implements OnInit {
97123 return sameId || includesName || includesArtist ;
98124 }
99125
126+ resetFilter ( ) {
127+ this . weControl . setValue ( false ) ;
128+ this . genreControls . controls . forEach ( c => c . setValue ( false ) ) ;
129+ this . versionControls . controls . forEach ( c => c . setValue ( false ) ) ;
130+ this . patternControl . setValue ( '' ) ;
131+ }
132+
133+ isDefaultFilter ( ) {
134+ return this . weControl . value === false &&
135+ this . genreControls . controls . every ( c => c . value === false ) &&
136+ this . genreControls . controls . every ( c => c . value === false ) &&
137+ this . patternControl . value === '' ;
138+ }
139+
140+ toggleFilter ( ) {
141+ if ( ! this . filterCollapse ) {
142+ const collapseElement = document . getElementById ( 'filterCollapse' ) ;
143+ if ( collapseElement ) {
144+ this . filterCollapse = new Collapse ( collapseElement , { toggle : false } ) ;
145+ }
146+ }
147+ if ( this . filterCollapsed ) {
148+ this . filterCollapse . show ( ) ;
149+ this . filterCollapsed = false ;
150+ }
151+ else {
152+ this . filterCollapse . hide ( ) ;
153+ this . filterCollapsed = true ;
154+ }
155+ }
156+
100157 showDetail ( music : ChusanMusic ) {
101158 const offcanvasRef = this . offcanvasService . open ( V2SongScoreRankingComponent , {
102159 position : 'end' ,
0 commit comments