Add subtitles in frontend
Update backend to match polochon
This commit is contained in:
parent
e85554fbaa
commit
e71c5bfb84
@ -325,12 +325,23 @@ func RefreshMovieSubtitlesHandler(env *web.Env, w http.ResponseWriter, r *http.R
|
||||
return env.RenderError(w, err)
|
||||
}
|
||||
|
||||
err = client.UpdateSubtitles(&papi.Movie{ImdbID: id})
|
||||
movie := &papi.Movie{ImdbID: id}
|
||||
refreshSubs, err := client.UpdateSubtitles(movie)
|
||||
if err != nil {
|
||||
return env.RenderError(w, err)
|
||||
}
|
||||
|
||||
return env.RenderOK(w, "Subtitles refreshed")
|
||||
subs := []subtitles.Subtitle{}
|
||||
for _, lang := range refreshSubs {
|
||||
subtitleURL, _ := client.SubtitleURL(movie, lang)
|
||||
subs = append(subs, subtitles.Subtitle{
|
||||
Language: lang,
|
||||
URL: subtitleURL,
|
||||
VVTFile: fmt.Sprintf("/movies/%s/subtitles/%s", id, lang),
|
||||
})
|
||||
}
|
||||
|
||||
return env.RenderJSON(w, subs)
|
||||
}
|
||||
|
||||
// DownloadVVTSubtitle returns a vvt subtitle for the movie
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/odwrtw/polochon/lib"
|
||||
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/backend"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/subtitles"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/users"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/web"
|
||||
)
|
||||
@ -31,12 +32,7 @@ func (m *Movie) MarshalJSON() ([]byte, error) {
|
||||
type Alias Movie
|
||||
|
||||
var downloadURL string
|
||||
type Subtitle struct {
|
||||
Language string `json:"language"`
|
||||
URL string `json:"url"`
|
||||
VVTFile string `json:"vvt_file"`
|
||||
}
|
||||
var subtitles []Subtitle
|
||||
var subs []subtitles.Subtitle
|
||||
// If the episode is present, fill the downloadURL
|
||||
if m.pMovie != nil {
|
||||
// Get the DownloadURL
|
||||
@ -44,7 +40,7 @@ func (m *Movie) MarshalJSON() ([]byte, error) {
|
||||
// Append the Subtitles
|
||||
for _, l := range m.pMovie.Subtitles {
|
||||
subtitleURL, _ := m.client.SubtitleURL(m.pMovie, l)
|
||||
subtitles = append(subtitles, Subtitle{
|
||||
subs = append(subs, subtitles.Subtitle{
|
||||
Language: l,
|
||||
URL: subtitleURL,
|
||||
VVTFile: fmt.Sprintf("/movies/%s/subtitles/%s", m.ImdbID, l),
|
||||
@ -55,14 +51,14 @@ func (m *Movie) MarshalJSON() ([]byte, error) {
|
||||
// Marshal the movie with its polochon_url
|
||||
movieToMarshal := &struct {
|
||||
*Alias
|
||||
PolochonURL string `json:"polochon_url"`
|
||||
PosterURL string `json:"poster_url"`
|
||||
Subtitles []Subtitle `json:"subtitles"`
|
||||
PolochonURL string `json:"polochon_url"`
|
||||
PosterURL string `json:"poster_url"`
|
||||
Subtitles []subtitles.Subtitle `json:"subtitles"`
|
||||
}{
|
||||
Alias: (*Alias)(m),
|
||||
PolochonURL: downloadURL,
|
||||
PosterURL: m.PosterURL(),
|
||||
Subtitles: subtitles,
|
||||
Subtitles: subs,
|
||||
}
|
||||
|
||||
return json.Marshal(movieToMarshal)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
polochon "github.com/odwrtw/polochon/lib"
|
||||
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/backend"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/subtitles"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/web"
|
||||
)
|
||||
|
||||
@ -24,12 +25,7 @@ func (e *Episode) MarshalJSON() ([]byte, error) {
|
||||
type alias Episode
|
||||
|
||||
var downloadURL string
|
||||
type Subtitle struct {
|
||||
Language string `json:"language"`
|
||||
URL string `json:"url"`
|
||||
VVTFile string `json:"vvt_file"`
|
||||
}
|
||||
var subtitles []Subtitle
|
||||
var subs []subtitles.Subtitle
|
||||
// If the episode is present, fill the downloadURL
|
||||
if e.pShow != nil {
|
||||
pEpisode := e.pShow.GetEpisode(e.Season, e.Episode)
|
||||
@ -45,7 +41,7 @@ func (e *Episode) MarshalJSON() ([]byte, error) {
|
||||
// Append the Subtitles
|
||||
for _, l := range pEpisode.Subtitles {
|
||||
subtitleURL, _ := e.client.SubtitleURL(pEpisode, l)
|
||||
subtitles = append(subtitles, Subtitle{
|
||||
subs = append(subs, subtitles.Subtitle{
|
||||
Language: l,
|
||||
URL: subtitleURL,
|
||||
VVTFile: fmt.Sprintf("/shows/%s/seasons/%d/episodes/%d/subtitles/%s", e.ShowImdbID, e.Season, e.Episode, l),
|
||||
@ -57,12 +53,12 @@ func (e *Episode) MarshalJSON() ([]byte, error) {
|
||||
// Marshal the episode with its polochon_url
|
||||
episodeToMarshal := &struct {
|
||||
*alias
|
||||
PolochonURL string `json:"polochon_url"`
|
||||
Subtitles []Subtitle `json:"subtitles"`
|
||||
PolochonURL string `json:"polochon_url"`
|
||||
Subtitles []subtitles.Subtitle `json:"subtitles"`
|
||||
}{
|
||||
alias: (*alias)(e),
|
||||
PolochonURL: downloadURL,
|
||||
Subtitles: subtitles,
|
||||
Subtitles: subs,
|
||||
}
|
||||
|
||||
return json.Marshal(episodeToMarshal)
|
||||
|
@ -374,16 +374,28 @@ func RefreshEpisodeSubtitlesHandler(env *web.Env, w http.ResponseWriter, r *http
|
||||
return env.RenderError(w, err)
|
||||
}
|
||||
|
||||
err = client.UpdateSubtitles(&papi.Episode{
|
||||
e := &papi.Episode{
|
||||
ShowImdbID: id,
|
||||
Season: season,
|
||||
Episode: episode,
|
||||
})
|
||||
}
|
||||
|
||||
refreshedSubs, err := client.UpdateSubtitles(e)
|
||||
if err != nil {
|
||||
return env.RenderError(w, err)
|
||||
}
|
||||
|
||||
return env.RenderOK(w, "Subtitles refreshed")
|
||||
subs := []subtitles.Subtitle{}
|
||||
for _, lang := range refreshedSubs {
|
||||
subtitleURL, _ := client.SubtitleURL(e, lang)
|
||||
subs = append(subs, subtitles.Subtitle{
|
||||
Language: lang,
|
||||
URL: subtitleURL,
|
||||
VVTFile: fmt.Sprintf("/shows/%s/seasons/%d/episodes/%d/subtitles/%s", e.ShowImdbID, e.Season, e.Episode, lang),
|
||||
})
|
||||
}
|
||||
|
||||
return env.RenderJSON(w, subs)
|
||||
}
|
||||
|
||||
// DownloadVVTSubtitle returns a vvt subtitle for the movie
|
||||
|
8
src/internal/subtitles/subtitles.go
Normal file
8
src/internal/subtitles/subtitles.go
Normal file
@ -0,0 +1,8 @@
|
||||
package subtitles
|
||||
|
||||
// Subtitle represents a Subtitle
|
||||
type Subtitle struct {
|
||||
Language string `json:"language"`
|
||||
URL string `json:"url"`
|
||||
VVTFile string `json:"vvt_file"`
|
||||
}
|
36
src/public/js/actions/subtitles.js
Normal file
36
src/public/js/actions/subtitles.js
Normal file
@ -0,0 +1,36 @@
|
||||
import { configureAxios, request } from '../requests'
|
||||
|
||||
import { addAlertOk } from './alerts'
|
||||
|
||||
export function refreshSubtitles(type, id, season, episode) {
|
||||
switch (type) {
|
||||
case 'movie':
|
||||
var resourceURL = `/movies/${id}`
|
||||
return request(
|
||||
'MOVIE_SUBTITLES_UPDATE',
|
||||
configureAxios().post(`${resourceURL}/subtitles/refresh`),
|
||||
[
|
||||
addAlertOk("Subtitles refreshed"),
|
||||
],
|
||||
{
|
||||
imdb_id: id,
|
||||
},
|
||||
)
|
||||
case 'episode':
|
||||
var resourceURL = `/shows/${id}/seasons/${season}/episodes/${episode}`
|
||||
return request(
|
||||
'EPISODE_SUBTITLES_UPDATE',
|
||||
configureAxios().post(`${resourceURL}/subtitles/refresh`),
|
||||
[
|
||||
addAlertOk("Subtitles refreshed"),
|
||||
],
|
||||
{
|
||||
imdb_id: id,
|
||||
season: season,
|
||||
episode: episode,
|
||||
},
|
||||
)
|
||||
default:
|
||||
console.log("refreshSubtitles - Unknown type " + type)
|
||||
}
|
||||
}
|
97
src/public/js/components/buttons/subtitles.js
Normal file
97
src/public/js/components/buttons/subtitles.js
Normal file
@ -0,0 +1,97 @@
|
||||
import React from 'react'
|
||||
|
||||
import { DropdownButton, MenuItem } from 'react-bootstrap'
|
||||
|
||||
export default class SubtitlesButton extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
handleClick(e, url) {
|
||||
e.preventDefault();
|
||||
if (this.props.fetching) {
|
||||
return
|
||||
}
|
||||
// Refresh the subtitles
|
||||
this.props.refreshSubtitles(this.props.type, this.props.resourceID, this.props.data.season, this.props.data.episode);
|
||||
}
|
||||
render() {
|
||||
// If there is no URL, the resource is not in polochon, we won't be able to download subtitles
|
||||
if (this.props.url === "") {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Build the button
|
||||
const entries = buildMenuItems(this.props.subtitles);
|
||||
let btnSize = "small";
|
||||
if (this.props.xs) {
|
||||
btnSize = "xsmall";
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownButton bsStyle="success" bsSize={btnSize} title="Subtitles" id="download-subtitles-button" dropup>
|
||||
{entries.map(function(e, index) {
|
||||
switch (e.type) {
|
||||
case 'action':
|
||||
return (
|
||||
<MenuItem key={index} onClick={(event) => this.handleClick(event, e.url)}>
|
||||
{this.props.fetchingSubtitles ||
|
||||
<span>
|
||||
<i className="fa fa-refresh">
|
||||
</i> Refresh
|
||||
</span>
|
||||
}
|
||||
{this.props.fetchingSubtitles &&
|
||||
<span>
|
||||
<i className="fa fa-spin fa-refresh">
|
||||
</i> Refreshing
|
||||
</span>
|
||||
}
|
||||
</MenuItem>
|
||||
);
|
||||
case 'divider':
|
||||
return (
|
||||
<MenuItem key={index} divider></MenuItem>
|
||||
);
|
||||
case 'entry':
|
||||
return (
|
||||
<MenuItem key={index} href={e.url}>
|
||||
<i className="fa fa-download"></i> {e.lang}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
}, this)}
|
||||
</DropdownButton>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function buildMenuItems(subtitles) {
|
||||
// Build the array of entries
|
||||
let entries = [];
|
||||
|
||||
// Push the refresh button
|
||||
entries.push({
|
||||
type: "action",
|
||||
value: "Refresh",
|
||||
});
|
||||
|
||||
// If there is no subtitles, stop here
|
||||
if (!subtitles) {
|
||||
return entries;
|
||||
}
|
||||
|
||||
// Push the divider
|
||||
entries.push({ type: "divider" });
|
||||
// Push the subtitles
|
||||
for (let sub of subtitles) {
|
||||
entries.push({
|
||||
type: "entry",
|
||||
// Take only the last part of fr_FR
|
||||
lang: sub.language.split("_")[1],
|
||||
url: sub.url,
|
||||
});
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
@ -2,10 +2,12 @@ import React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { addTorrent } from '../../actions/torrents'
|
||||
import { refreshSubtitles } from '../../actions/subtitles'
|
||||
import { addMovieToWishlist, deleteMovieFromWishlist,
|
||||
getMovieDetails, selectMovie } from '../../actions/movies'
|
||||
|
||||
import DownloadButton from '../buttons/download'
|
||||
import SubtitlesButton from '../buttons/subtitles'
|
||||
import TorrentsButton from './torrents'
|
||||
import ActionsButton from './actions'
|
||||
import ListPosters from '../list/posters'
|
||||
@ -16,7 +18,7 @@ function mapStateToProps(state) {
|
||||
}
|
||||
const mapDispatchToProps = (dipatch) =>
|
||||
bindActionCreators({ selectMovie, getMovieDetails, addTorrent,
|
||||
addMovieToWishlist, deleteMovieFromWishlist }, dipatch)
|
||||
addMovieToWishlist, deleteMovieFromWishlist, refreshSubtitles }, dipatch)
|
||||
|
||||
function MovieButtons(props) {
|
||||
const imdb_link = `http://www.imdb.com/title/${props.movie.imdb_id}`;
|
||||
@ -48,6 +50,15 @@ function MovieButtons(props) {
|
||||
subtitles={props.movie.subtitles}
|
||||
/>
|
||||
|
||||
<SubtitlesButton
|
||||
url={props.movie.polochon_url}
|
||||
subtitles={props.movie.subtitles}
|
||||
refreshSubtitles={props.refreshSubtitles}
|
||||
resourceID={props.movie.imdb_id}
|
||||
data={props.movie}
|
||||
type="movie"
|
||||
/>
|
||||
|
||||
<a type="button" className="btn btn-warning btn-sm" href={imdb_link}>
|
||||
<i className="fa fa-external-link"></i> IMDB
|
||||
</a>
|
||||
@ -96,6 +107,7 @@ class MovieList extends React.Component {
|
||||
addToWishlist={this.props.addMovieToWishlist}
|
||||
deleteFromWishlist={this.props.deleteMovieFromWishlist}
|
||||
lastFetchUrl={this.props.movieStore.lastFetchUrl}
|
||||
refreshSubtitles={this.props.refreshSubtitles}
|
||||
/>
|
||||
</ListDetails>
|
||||
}
|
||||
|
@ -2,11 +2,13 @@ import React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { addTorrent } from '../../actions/torrents'
|
||||
import { refreshSubtitles } from '../../actions/subtitles'
|
||||
import { addShowToWishlist, deleteFromWishlist, getEpisodeDetails,
|
||||
updateEpisodeDetailsStore, updateShowDetails } from '../../actions/shows'
|
||||
|
||||
import Loader from '../loader/loader'
|
||||
import DownloadButton from '../buttons/download'
|
||||
import SubtitlesButton from '../buttons/subtitles'
|
||||
|
||||
import { OverlayTrigger, Tooltip } from 'react-bootstrap'
|
||||
|
||||
@ -18,7 +20,8 @@ function mapStateToProps(state) {
|
||||
}
|
||||
const mapDispatchToProps = (dispatch) =>
|
||||
bindActionCreators({addTorrent, addShowToWishlist, deleteFromWishlist,
|
||||
updateShowDetails, updateEpisodeDetailsStore, getEpisodeDetails }, dispatch)
|
||||
updateShowDetails, updateEpisodeDetailsStore, getEpisodeDetails,
|
||||
refreshSubtitles }, dispatch)
|
||||
|
||||
class ShowDetails extends React.Component {
|
||||
render() {
|
||||
@ -39,6 +42,7 @@ class ShowDetails extends React.Component {
|
||||
addToWishlist={this.props.addShowToWishlist}
|
||||
getEpisodeDetails={this.props.getEpisodeDetails}
|
||||
updateEpisodeDetailsStore={this.props.updateEpisodeDetailsStore}
|
||||
refreshSubtitles={this.props.refreshSubtitles}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@ -113,6 +117,7 @@ function SeasonsList(props){
|
||||
addToWishlist={props.addToWishlist}
|
||||
getEpisodeDetails={props.getEpisodeDetails}
|
||||
updateEpisodeDetailsStore={props.updateEpisodeDetailsStore}
|
||||
refreshSubtitles={props.refreshSubtitles}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
@ -159,6 +164,7 @@ class Season extends React.Component {
|
||||
addToWishlist={this.props.addToWishlist}
|
||||
getEpisodeDetails={this.props.getEpisodeDetails}
|
||||
updateEpisodeDetailsStore={this.props.updateEpisodeDetailsStore}
|
||||
refreshSubtitles={this.props.refreshSubtitles}
|
||||
/>
|
||||
)
|
||||
}, this)}
|
||||
@ -181,8 +187,17 @@ function Episode(props) {
|
||||
{props.data.episode}
|
||||
</th>
|
||||
<td className="col-xs-5">{props.data.title}</td>
|
||||
<td className="col-xs-6">
|
||||
<span className="pull-right">
|
||||
<td className="col-xs-6 list-details-button">
|
||||
<span className="pull-right episode-buttons btn-toolbar">
|
||||
<SubtitlesButton
|
||||
url={props.data.polochon_url}
|
||||
subtitles={props.data.subtitles}
|
||||
refreshSubtitles={props.refreshSubtitles}
|
||||
resourceID={props.data.show_imdb_id}
|
||||
data={props.data}
|
||||
type="episode"
|
||||
xs
|
||||
/>
|
||||
{props.data.torrents && props.data.torrents.map(function(torrent, index) {
|
||||
let key = `${props.data.season}-${props.data.episode}-${torrent.source}-${torrent.quality}`;
|
||||
return (
|
||||
@ -196,7 +211,6 @@ function Episode(props) {
|
||||
<DownloadButton
|
||||
url={props.data.polochon_url}
|
||||
subtitles={props.data.subtitles}
|
||||
customClassName="episode-button"
|
||||
xs
|
||||
/>
|
||||
<GetDetailsButton
|
||||
@ -221,7 +235,7 @@ class Torrent extends React.Component {
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<span className="episode-button">
|
||||
<span>
|
||||
<a type="button"
|
||||
className="btn btn-primary btn-xs"
|
||||
onClick={(e) => this.handleClick(e, this.props.data.url)}
|
||||
@ -306,7 +320,7 @@ class TrackButton extends React.Component {
|
||||
<Tooltip id={tooltipId}>Track show from here</Tooltip>
|
||||
);
|
||||
return (
|
||||
<OverlayTrigger placement="top" overlay={tooltip} className="episode-button">
|
||||
<OverlayTrigger placement="top" overlay={tooltip}>
|
||||
<a type="button" className="btn btn-default btn-xs" onClick={(e) => this.handleClick(e)}>
|
||||
<i className="fa fa-bookmark"></i>
|
||||
</a>
|
||||
@ -326,24 +340,23 @@ class GetDetailsButton extends React.Component {
|
||||
return
|
||||
}
|
||||
this.props.updateEpisodeDetailsStore(this.props.data.show_imdb_id, this.props.data.season, this.props.data.episode);
|
||||
console.log(this.props.data);
|
||||
this.props.getEpisodeDetails(this.props.data.show_imdb_id, this.props.data.season, this.props.data.episode);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<span className="episode-button">
|
||||
<a type="button" className="btn btn-xs btn-info" onClick={(e) => this.handleClick(e)}>
|
||||
{this.props.data.fetching ||
|
||||
<span>
|
||||
<i className="fa fa-refresh"></i> Refresh
|
||||
</span>
|
||||
}
|
||||
{this.props.data.fetching &&
|
||||
<span>
|
||||
<i className="fa fa-spin fa-refresh"></i> Refreshing
|
||||
</span>
|
||||
}
|
||||
</a>
|
||||
</span>
|
||||
<a type="button" className="btn btn-xs btn-info" onClick={(e) => this.handleClick(e)}>
|
||||
{this.props.data.fetching ||
|
||||
<span>
|
||||
<i className="fa fa-refresh"></i> Refresh
|
||||
</span>
|
||||
}
|
||||
{this.props.data.fetching &&
|
||||
<span>
|
||||
<i className="fa fa-spin fa-refresh"></i> Refreshing
|
||||
</span>
|
||||
}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -18,13 +18,13 @@ export default function movieStore(state = defaultState, action) {
|
||||
case 'MOVIE_LIST_FETCH_FULFILLED':
|
||||
let selectedImdbId = "";
|
||||
// Select the first movie
|
||||
if (action.payload.data.length > 0) {
|
||||
if (action.payload.response.data.length > 0) {
|
||||
// Sort by year
|
||||
action.payload.data.sort((a,b) => b.year - a.year);
|
||||
selectedImdbId = action.payload.data[0].imdb_id;
|
||||
action.payload.response.data.sort((a,b) => b.year - a.year);
|
||||
selectedImdbId = action.payload.response.data[0].imdb_id;
|
||||
}
|
||||
return Object.assign({}, state, {
|
||||
movies: action.payload.data,
|
||||
movies: action.payload.response.data,
|
||||
selectedImdbId: selectedImdbId,
|
||||
filter: defaultState.filter,
|
||||
perPage: defaultState.perPage,
|
||||
@ -36,7 +36,7 @@ export default function movieStore(state = defaultState, action) {
|
||||
})
|
||||
case 'MOVIE_GET_DETAILS_FULFILLED':
|
||||
return Object.assign({}, state, {
|
||||
movies: updateMovieDetails(state.movies.slice(), action.payload.data.imdb_id, action.payload.data),
|
||||
movies: updateMovieDetails(state.movies.slice(), action.payload.response.data.imdb_id, action.payload.response.data),
|
||||
fetchingDetails: false,
|
||||
})
|
||||
case 'MOVIE_UPDATE_STORE_WISHLIST':
|
||||
@ -45,12 +45,21 @@ export default function movieStore(state = defaultState, action) {
|
||||
})
|
||||
case 'MOVIE_GET_EXPLORE_OPTIONS_FULFILLED':
|
||||
return Object.assign({}, state, {
|
||||
exploreOptions: action.payload.data,
|
||||
exploreOptions: action.payload.response.data,
|
||||
})
|
||||
case 'UPDATE_LAST_MOVIE_FETCH_URL':
|
||||
return Object.assign({}, state, {
|
||||
lastFetchUrl: action.payload.url,
|
||||
})
|
||||
case 'MOVIE_SUBTITLES_UPDATE_PENDING':
|
||||
return Object.assign({}, state, {
|
||||
movies: updateMovieSubtitles(state.movies.slice(), state.selectedImdbId, true),
|
||||
})
|
||||
case 'MOVIE_SUBTITLES_UPDATE_FULFILLED':
|
||||
console.log("payload :", action.payload);
|
||||
return Object.assign({}, state, {
|
||||
movies: updateMovieSubtitles(state.movies.slice(), state.selectedImdbId, false, action.payload.response.data),
|
||||
})
|
||||
case 'SELECT_MOVIE':
|
||||
// Don't select the movie if we're fetching another movie's details
|
||||
if (state.fetchingDetails) {
|
||||
@ -76,3 +85,12 @@ function updateStoreWishlist(movies, imdbId, wishlisted) {
|
||||
movies[index].wishlisted = wishlisted;
|
||||
return movies
|
||||
}
|
||||
|
||||
function updateMovieSubtitles(movies, imdbId, fetching, data = null) {
|
||||
let index = movies.map((el) => el.imdb_id).indexOf(imdbId);
|
||||
if (data) {
|
||||
movies[index].subtitles = data;
|
||||
}
|
||||
movies[index].fetchingSubtitles = fetching;
|
||||
return movies
|
||||
}
|
||||
|
@ -21,11 +21,12 @@ export default function showStore(state = defaultState, action) {
|
||||
case 'SHOW_LIST_FETCH_FULFILLED':
|
||||
let selectedImdbId = "";
|
||||
// Select the first show
|
||||
if (action.payload.data.length > 0) {
|
||||
selectedImdbId = action.payload.data[0].imdb_id;
|
||||
console.log("Hey", action.payload);
|
||||
if (action.payload.response.data.length > 0) {
|
||||
selectedImdbId = action.payload.response.data[0].imdb_id;
|
||||
}
|
||||
return Object.assign({}, state, {
|
||||
shows: action.payload.data,
|
||||
shows: action.payload.response.data,
|
||||
selectedImdbId: selectedImdbId,
|
||||
filter: defaultState.filter,
|
||||
perPage: defaultState.perPage,
|
||||
@ -37,7 +38,7 @@ export default function showStore(state = defaultState, action) {
|
||||
})
|
||||
case 'SHOW_GET_DETAILS_FULFILLED':
|
||||
return Object.assign({}, state, {
|
||||
shows: updateShowDetails(state.shows.slice(), action.payload.data),
|
||||
shows: updateShowDetails(state.shows.slice(), action.payload.response.data),
|
||||
getDetails: false,
|
||||
})
|
||||
case 'SHOW_FETCH_DETAILS_PENDING':
|
||||
@ -46,7 +47,7 @@ export default function showStore(state = defaultState, action) {
|
||||
})
|
||||
case 'SHOW_FETCH_DETAILS_FULFILLED':
|
||||
return Object.assign({}, state, {
|
||||
show: sortEpisodes(action.payload.data),
|
||||
show: sortEpisodes(action.payload.response.data),
|
||||
loading: false,
|
||||
})
|
||||
case 'EPISODE_GET_DETAILS':
|
||||
@ -55,7 +56,7 @@ export default function showStore(state = defaultState, action) {
|
||||
})
|
||||
case 'EPISODE_GET_DETAILS_FULFILLED':
|
||||
return Object.assign({}, state, {
|
||||
show: updateEpisode(Object.assign({}, state.show), false, action.payload.data),
|
||||
show: updateEpisode(Object.assign({}, state.show), false, action.payload.response.data),
|
||||
})
|
||||
case 'EXPLORE_SHOWS_PENDING':
|
||||
return Object.assign({}, state, {
|
||||
@ -63,12 +64,12 @@ export default function showStore(state = defaultState, action) {
|
||||
})
|
||||
case 'EXPLORE_SHOWS_FULFILLED':
|
||||
return Object.assign({}, state, {
|
||||
shows: action.payload.data,
|
||||
shows: action.payload.response.data,
|
||||
loading: false,
|
||||
})
|
||||
case 'SHOW_GET_EXPLORE_OPTIONS_FULFILLED':
|
||||
return Object.assign({}, state, {
|
||||
exploreOptions: action.payload.data,
|
||||
exploreOptions: action.payload.response.data,
|
||||
})
|
||||
case 'SHOW_UPDATE_STORE_WISHLIST':
|
||||
return Object.assign({}, state, {
|
||||
@ -79,6 +80,15 @@ export default function showStore(state = defaultState, action) {
|
||||
return Object.assign({}, state, {
|
||||
lastShowsFetchUrl: action.payload.url,
|
||||
})
|
||||
case 'EPISODE_SUBTITLES_UPDATE_PENDING':
|
||||
return Object.assign({}, state, {
|
||||
show: updateEpisodeSubtitles(Object.assign({}, state.show), action.payload.main.season, action.payload.main.episode, true),
|
||||
})
|
||||
case 'EPISODE_SUBTITLES_UPDATE_FULFILLED':
|
||||
console.log("payload :", action.payload);
|
||||
return Object.assign({}, state, {
|
||||
show: updateEpisodeSubtitles(Object.assign({}, state.show), action.payload.main.season, action.payload.main.episode, false, action.payload.response.data),
|
||||
})
|
||||
case 'SELECT_SHOW':
|
||||
// Don't select the show if we're fetching another show's details
|
||||
if (state.fetchingDetails) {
|
||||
@ -113,6 +123,17 @@ function updateEpisode(show, fetching, data = null) {
|
||||
return show
|
||||
}
|
||||
|
||||
function updateEpisodeSubtitles(show, season, episode, fetching, data = null) {
|
||||
let seasonIndex = show.seasons.map((el) => el.season).indexOf(season.toString());
|
||||
let episodeIndex = show.seasons[seasonIndex].episodes.map((el) => el.episode).indexOf(episode);
|
||||
|
||||
if (data) {
|
||||
show.seasons[seasonIndex].episodes[episodeIndex].subtitles = data;
|
||||
}
|
||||
show.seasons[seasonIndex].episodes[episodeIndex].fetchingSubtitles = fetching;
|
||||
return show
|
||||
}
|
||||
|
||||
function sortEpisodes(show) {
|
||||
let episodes = show.episodes;
|
||||
delete show["episodes"];
|
||||
|
@ -12,7 +12,7 @@ export default function torrentStore(state = defaultState, action) {
|
||||
case 'TORRENTS_FETCH_FULFILLED':
|
||||
return state.merge(fromJS({
|
||||
fetching: false,
|
||||
torrents: action.payload.data,
|
||||
torrents: action.payload.response.data,
|
||||
}));
|
||||
default:
|
||||
return state
|
||||
|
@ -17,18 +17,18 @@ export default function userStore(state = defaultState, action) {
|
||||
userLoading: true,
|
||||
})
|
||||
case 'USER_LOGIN_FULFILLED':
|
||||
if (action.payload.status === "error") {
|
||||
if (action.payload.response.status === "error") {
|
||||
return logoutUser(state)
|
||||
}
|
||||
return updateFromToken(state, action.payload.data.token)
|
||||
return updateFromToken(state, action.payload.response.data.token)
|
||||
case 'USER_SET_TOKEN':
|
||||
return updateFromToken(state, action.payload.token)
|
||||
case 'USER_LOGOUT':
|
||||
return logoutUser(state)
|
||||
case 'GET_USER_FULFILLED':
|
||||
return Object.assign({}, state, {
|
||||
polochonToken: action.payload.data.token,
|
||||
polochonUrl: action.payload.data.url,
|
||||
polochonToken: action.payload.response.data.token,
|
||||
polochonUrl: action.payload.response.data.url,
|
||||
})
|
||||
default:
|
||||
return state;
|
||||
|
@ -16,7 +16,7 @@ export function configureAxios(headers = {}) {
|
||||
|
||||
// This function takes en event prefix to dispatch evens during the life of the
|
||||
// request, it also take a promise (axios request)
|
||||
export function request(eventPrefix, promise, callbackEvents = null) {
|
||||
export function request(eventPrefix, promise, callbackEvents = null, mainPayload = null) {
|
||||
// Events
|
||||
const pending = `${eventPrefix}_PENDING`;
|
||||
const fulfilled = `${eventPrefix}_FULFILLED`;
|
||||
@ -24,6 +24,9 @@ export function request(eventPrefix, promise, callbackEvents = null) {
|
||||
return function(dispatch) {
|
||||
dispatch({
|
||||
type: pending,
|
||||
payload: {
|
||||
main: mainPayload,
|
||||
}
|
||||
})
|
||||
promise
|
||||
.then(response => {
|
||||
@ -33,12 +36,16 @@ export function request(eventPrefix, promise, callbackEvents = null) {
|
||||
type: 'ADD_ALERT_ERROR',
|
||||
payload: {
|
||||
message: response.data.message,
|
||||
main: mainPayload,
|
||||
}
|
||||
})
|
||||
}
|
||||
dispatch({
|
||||
type: fulfilled,
|
||||
payload: response.data,
|
||||
payload: {
|
||||
response: response.data,
|
||||
main: mainPayload,
|
||||
},
|
||||
})
|
||||
if (callbackEvents) {
|
||||
for (let event of callbackEvents) {
|
||||
@ -57,6 +64,7 @@ export function request(eventPrefix, promise, callbackEvents = null) {
|
||||
type: 'ADD_ALERT_ERROR',
|
||||
payload: {
|
||||
message: error.response.data,
|
||||
main: mainPayload,
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -46,8 +46,11 @@ body {
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.episode-button {
|
||||
padding-right: 5px;
|
||||
.episode-buttons {
|
||||
display: flex;
|
||||
span {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar {
|
||||
|
Loading…
x
Reference in New Issue
Block a user