Skip to content

Commit

Permalink
feat: draggable channels in favorites list
Browse files Browse the repository at this point in the history
  • Loading branch information
4gray committed Feb 28, 2023
1 parent de17686 commit ba41c8d
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,28 +98,28 @@
</div>
</ng-template>
<mat-nav-list
cdkDropList
*ngIf="favorites$ | async as favorites"
(cdkDropListDropped)="drop($event, favorites)"
id="favorites-list"
>
<ng-container *ngIf="favorites.length > 0; else noFavorites">
<ng-container *ngFor="let channel of favorites; index as i">
<app-channel-list-item
[name]="
i +
1 +
'. ' +
(channel?.name || 'CHANNELS.UNNAMED_CHANNEL'
| translate)
"
[logo]="channel?.tvg?.logo"
(clicked)="selectChannel(channel)"
[selected]="selected?.id === channel.id"
[showFavoriteButton]="true"
(favoriteToggled)="
toggleFavoriteChannel(channel, $event)
"
></app-channel-list-item>
</ng-container>
<app-channel-list-item
*ngFor="let channel of favorites; index as i"
[name]="
i +
1 +
'. ' +
(channel?.name || 'CHANNELS.UNNAMED_CHANNEL'
| translate)
"
[isDraggable]="true"
[logo]="channel?.tvg?.logo"
(clicked)="selectChannel(channel)"
[selected]="selected?.id === channel.id"
[showFavoriteButton]="true"
(favoriteToggled)="toggleFavoriteChannel(channel, $event)"
></app-channel-list-item>
</ng-container>
<ng-template #noFavorites>
<mat-list-item
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import {
Component,
ElementRef,
Expand All @@ -11,7 +12,6 @@ import { TranslateService } from '@ngx-translate/core';
import * as _ from 'lodash';
import { map, skipWhile } from 'rxjs';
import { Channel } from '../../../../../shared/channel.interface';
import { PlaylistsService } from '../../../services/playlists.service';
import * as PlaylistActions from '../../../state/actions';
import {
selectActivePlaylistId,
Expand Down Expand Up @@ -73,15 +73,16 @@ export class ChannelListContainerComponent {
favorites$ = this.store
.select(selectFavorites)
.pipe(
map((favorites) =>
this.channelList.filter((channel) =>
favorites.includes(channel.id)
map((favoriteChannelIds) =>
favoriteChannelIds.map((favoriteChannelId) =>
this.channelList.find(
(channel) => channel.id === favoriteChannelId
)
)
)
);

constructor(
private playlistService: PlaylistsService,
private readonly store: Store,
private snackBar: MatSnackBar,
private translateService: TranslateService
Expand Down Expand Up @@ -119,4 +120,14 @@ export class ChannelListContainerComponent {
trackByFn(index: number, channel: Channel): string {
return channel.id;
}

drop(event: CdkDragDrop<Channel[]>, favorites: Channel[]) {
moveItemInArray(favorites, event.previousIndex, event.currentIndex);
console.log(favorites);
this.store.dispatch(
PlaylistActions.setFavorites({
channelIds: favorites.map((item) => item.id),
})
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@
}
}
}

.drag-icon {
cursor: move;
margin-left: -20px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,20 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
selector: 'app-channel-list-item',
styleUrls: ['./channel-list-item.component.scss'],
template: `<mat-list-item
cdkDrag
[cdkDragDisabled]="!isDraggable"
cdkDragPreviewContainer="parent"
[class.active]="selected"
(click)="clicked.emit()"
data-test-id="channel-item"
>
<mat-icon
*ngIf="isDraggable"
mat-list-icon
cdkDragHandle
class="drag-icon"
>drag_indicator</mat-icon
>
<div class="channel-logo" *ngIf="logo">
<img [src]="logo" width="48" onerror="this.style.display='none'" />
</div>
Expand All @@ -27,6 +37,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
></mat-list-item>`,
})
export class ChannelListItemComponent {
@Input() isDraggable = false;
@Input() logo!: string;
@Input() name = '';
@Input() showFavoriteButton = false;
Expand Down
11 changes: 11 additions & 0 deletions src/app/services/playlists.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,15 @@ export class PlaylistsService {
})
);
}

setFavorites(playlistId: string, favorites: string[]) {
return this.getPlaylistById(playlistId).pipe(
switchMap((playlist) =>
this.dbService.update(DbStores.Playlists, {
...playlist,
favorites,
})
)
);
}
}
1 change: 1 addition & 0 deletions src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { MomentDatePipe } from './pipes/moment-date.pipe';
}),
],
exports: [
DragDropModule,
FilterPipe,
FormsModule,
HeaderComponent,
Expand Down
5 changes: 5 additions & 0 deletions src/app/state/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ export const updateFavorites = createAction(
props<{ channel: Channel }>()
);

export const setFavorites = createAction(
`${STORE_KEY} Set favorites`,
props<{ channelIds: string[] }>()
);

export const setActiveChannel = createAction(
`${STORE_KEY} Set active channel`,
props<{ channel: Channel }>()
Expand Down
18 changes: 18 additions & 0 deletions src/app/state/effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@ export class PlaylistEffects {
{ dispatch: false }
);

setFavorites$ = createEffect(
() => {
return this.actions$.pipe(
ofType(PlaylistActions.setFavorites),
combineLatestWith(this.store.select(selectActivePlaylistId)),
switchMap(([action, playlistId]) =>
this.playlistsService.setFavorites(
playlistId,
action.channelIds
)
)
);
},
{
dispatch: false,
}
);

setActiveChannel$ = createEffect(() => {
return this.actions$.pipe(
ofType(PlaylistActions.setActiveChannel),
Expand Down
16 changes: 16 additions & 0 deletions src/app/state/reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,22 @@ export const playlistReducer = createReducer(
},
};
}),
on(PlaylistActions.setFavorites, (state, action): PlaylistState => {
const { channelIds } = action;
return {
...state,
playlists: {
...state.playlists,
entities: {
...state.playlists.entities,
[state.playlists.selectedId]: {
...state.playlists.entities[state.playlists.selectedId],
favorites: channelIds,
},
},
},
};
}),
on(PlaylistActions.loadPlaylistsSuccess, (state, action): PlaylistState => {
return {
...state,
Expand Down

1 comment on commit ba41c8d

@vercel
Copy link

@vercel vercel bot commented on ba41c8d Feb 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

iptvnator – ./

iptvnator.vercel.app
iptvnator-git-electron-4gray.vercel.app
iptvnator-4gray.vercel.app

Please sign in to comment.