1
0
mirror of https://github.com/devfake/flox.git synced 2024-11-14 22:22:39 +01:00

Implement watchlist feature (#84)

* implement watchlist feature

* update production files

* fix migration error

* change current route to now-playing
This commit is contained in:
Viktor Geringer 2017-07-31 09:21:44 +02:00 committed by GitHub
parent 6ee5bfefcf
commit 1a224a50ed
37 changed files with 433 additions and 89 deletions

View File

@ -44,6 +44,15 @@
return $this->itemService->create(Input::get('item'));
}
public function watchlist()
{
$item = $this->add();
$item->update(['watchlist' => true]);
return $item;
}
public function remove($itemId)
{
return $this->itemService->remove($itemId);

View File

@ -57,6 +57,7 @@
'date' => $settings->show_date,
'spoiler' => $settings->episode_spoiler_protection,
'version' => $this->version,
'watchlist' => $settings->show_watchlist_everywhere,
];
}
@ -79,6 +80,7 @@
'show_genre' => Input::get('genre'),
'show_date' => Input::get('date'),
'episode_spoiler_protection' => Input::get('spoiler'),
'show_watchlist_everywhere' => Input::get('watchlist'),
]);
}
}

View File

@ -29,9 +29,9 @@
return $this->tmdb->trending();
}
public function current()
public function nowPlaying()
{
return $this->tmdb->current();
return $this->tmdb->nowPlaying();
}
public function upcoming()

View File

@ -31,6 +31,7 @@
'backdrop',
'youtube_key',
'slug',
'watchlist',
];
/**

View File

@ -3,11 +3,11 @@
namespace App\Services\Models;
use App\Item as Model;
use App\Item;
use App\Services\IMDB;
use App\Services\Storage;
use App\Services\TMDB;
use GuzzleHttp\Client;
use App\Setting;
use Symfony\Component\HttpFoundation\Response;
class ItemService {
@ -18,14 +18,16 @@
private $alternativeTitleService;
private $episodeService;
private $imdb;
private $setting;
/**
* @param Model $model
* @param TMDB $tmdb
* @param Storage $storage
* @param Model $model
* @param TMDB $tmdb
* @param Storage $storage
* @param AlternativeTitleService $alternativeTitleService
* @param EpisodeService $episodeService
* @param IMDB $imdb
* @param EpisodeService $episodeService
* @param IMDB $imdb
* @param Setting $setting
*/
public function __construct(
Model $model,
@ -33,7 +35,8 @@
Storage $storage,
AlternativeTitleService $alternativeTitleService,
EpisodeService $episodeService,
IMDB $imdb
IMDB $imdb,
Setting $setting
){
$this->model = $model;
$this->tmdb = $tmdb;
@ -41,6 +44,7 @@
$this->alternativeTitleService = $alternativeTitleService;
$this->episodeService = $episodeService;
$this->imdb = $imdb;
$this->setting = $setting;
}
/**
@ -170,7 +174,7 @@
return $this->imdb->parseRating($imdbId);
}
return null;
return null;
}
// Otherwise we already have the rating saved.
@ -210,7 +214,7 @@
/**
* @param $data
* @param $mediaType
* @return Item
* @return Model
*/
public function createEmpty($data, $mediaType)
{
@ -259,19 +263,23 @@
*/
public function getWithPagination($type, $orderBy)
{
$orderType = $orderBy == 'rating' ? 'asc' : 'desc';
$items = $this->model->orderBy($orderBy, 'asc')->with('latestEpisode')->withCount('episodesWithSrc');
$items = $this->model->orderBy($orderBy, $orderType)->with('latestEpisode')->withCount('episodesWithSrc');
if($type == 'watchlist') {
$items->where('watchlist', true);
} elseif( ! $this->setting->first()->show_watchlist_everywhere) {
$items->where('watchlist', false);
}
if($type == 'tv' || $type == 'movie') {
$items = $items->where('media_type', $type);
$items->where('media_type', $type);
}
return $items->simplePaginate(config('app.LOADING_ITEMS'));
}
/**
* Update rating for a movie.
* Update rating.
*
* @param $itemId
* @param $rating
@ -292,6 +300,7 @@
$item->update([
'rating' => $rating,
'watchlist' => false,
]);
}

View File

@ -121,7 +121,7 @@
*
* @return array
*/
public function current()
public function nowPlaying()
{
$cache = Cache::remember('current', $this->untilEndOfDay(), function() {
$region = getRegion($this->translation);

View File

@ -16,5 +16,6 @@
'show_genre',
'episode_spoiler_protection',
'last_fetch_to_file_parser',
'show_watchlist_everywhere',
];
}

View File

@ -0,0 +1,17 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddWatchlistFieldToItemsTabe extends Migration
{
public function up()
{
Schema::table('items', function (Blueprint $table) {
$table->boolean('watchlist')->default(false);
});
}
public function down() {}
}

View File

@ -0,0 +1,17 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddShowWatchlistEverywhereField extends Migration
{
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->boolean('show_watchlist_everywhere')->default(0);
});
}
public function down() {}
}

View File

@ -14,7 +14,7 @@
Route::get('/suggestions/{tmdbID}/{mediaType}', 'TMDBController@suggestions');
Route::get('/trending', 'TMDBController@trending');
Route::get('/upcoming', 'TMDBController@upcoming');
Route::get('/current', 'TMDBController@current');
Route::get('/now-playing', 'TMDBController@nowPlaying');
Route::patch('/refresh-all', 'ItemController@refreshAll');
Route::get('/settings', 'SettingController@settings');
@ -25,6 +25,7 @@
Route::patch('/settings', 'SettingController@updateSettings');
Route::post('/add', 'ItemController@add');
Route::post('/watchlist', 'ItemController@watchlist');
Route::patch('/update-alternative-titles/{tmdbId?}', 'ItemController@updateAlternativeTitles');
Route::patch('/update-genre', 'ItemController@updateGenre');
Route::patch('/toggle-episode/{id}', 'ItemController@toggleEpisode');

View File

@ -28,6 +28,7 @@
'genre' => 1,
'date' => 0,
'spoiler' => 0,
'watchlist' => 1,
]);
$setting2 = Setting::first();
@ -35,8 +36,10 @@
$this->assertEquals(0, $setting1->show_genre);
$this->assertEquals(1, $setting1->show_date);
$this->assertEquals(1, $setting1->episode_spoiler_protection);
$this->assertEquals(0, $setting1->show_watchlist_everywhere);
$this->assertEquals(1, $setting2->show_genre);
$this->assertEquals(0, $setting2->show_date);
$this->assertEquals(0, $setting2->episode_spoiler_protection);
$this->assertEquals(1, $setting2->show_watchlist_everywhere );
}
}

View File

@ -67,9 +67,9 @@
case 'home':
return this.setPageTitle();
case 'tv':
return this.setPageTitle(this.lang('tv'));
case 'movie':
return this.setPageTitle(this.lang('movies'));
case 'watchlist':
return this.setPageTitle(this.lang(name));
}
},

View File

@ -2,10 +2,12 @@
<transition mode="out-in" name="fade">
<div class="item-wrap">
<div class="item-image-wrap no-select">
<rating :item="localItem" :set-item="setItem"></rating>
<rating :rated="rated" :item="localItem" :set-item="setItem"></rating>
<router-link v-if="localItem.tmdb_id" :to="suggestionsUri(localItem)" class="recommend-item">{{ lang('suggestions') }}</router-link>
<span v-if="auth && localItem.rating == null" class="add-to-watchlist" @click="addToWatchlist()">{{ lang('add to watchlist') }}</span>
<span v-if="localItem.watchlist" class="is-on-watchlist"><i class="icon-watchlist"></i></span>
<span v-if="auth && localItem.rating == null && ! rated" class="add-to-watchlist" @click="addToWatchlist(localItem)">{{ lang('add to watchlist') }}</span>
<span v-if="auth && localItem.watchlist && ! rated" class="remove-from-watchlist" @click="removeItem()">{{ lang('remove from watchlist') }}</span>
<span v-if="auth && ! localItem.tmdb_id" class="edit-item" @click="editItem()">Edit</span>
<router-link :to="{ name: `subpage-${localItem.media_type}`, params: { tmdbId: localItem.tmdb_id, slug: localItem.slug }}">
@ -48,7 +50,8 @@
localItem: this.item,
latestEpisode: this.item.latest_episode,
prevRating: null,
auth: config.auth
auth: config.auth,
rated: false
}
},
@ -73,7 +76,7 @@
const path = this.$route.path;
const released = new Date(this.localItem.released * 1000);
if(path === '/upcoming' || path === '/current') {
if(path === '/upcoming' || path === '/now-playing') {
return this.formatLocaleDate(released);
}
@ -82,15 +85,24 @@
},
methods: {
...mapMutations([ 'OPEN_MODAL' ]),
...mapMutations([ 'OPEN_MODAL', 'SET_RATED' ]),
...mapActions([ 'fetchEpisodes' ]),
setItem(item) {
this.localItem = item;
},
addToWatchlist() {
removeItem() {
this.rated = true;
http.delete(`${config.api}/remove/${this.localItem.id}`).then(response => {
this.rated = false;
this.localItem.rating = null;
this.localItem.watchlist = null;
}, error => {
alert(error);
this.rated = false;
});
},
editItem() {

View File

@ -3,10 +3,10 @@
<div class="wrap-content">
<div class="navigation-tab no-select">
<span :class="{active: activeTab == 'misc'}" @click="changeActiveTab('misc')">{{ lang('tab misc') }}</span>
<span :class="{active: activeTab == 'user'}" @click="changeActiveTab('user')">{{ lang('tab user') }}</span>
<span :class="{active: activeTab == 'options'}" @click="changeActiveTab('options')">{{ lang('tab options') }}</span>
<span :class="{active: activeTab == 'backup'}" @click="changeActiveTab('backup')">{{ lang('tab backup') }}</span>
<span :class="{active: activeTab == 'misc'}" @click="changeActiveTab('misc')">{{ lang('tab misc') }}</span>
</div>
<span class="loader fullsize-loader" v-if="loading"><i></i></span>
@ -42,7 +42,7 @@
data() {
return {
activeTab: 'user'
activeTab: 'misc'
}
},

View File

@ -7,6 +7,7 @@
<span class="update-check" v-if="isUpdate">
<a href="https://github.com/devfake/flox/releases" target="_blank" class="new-update">{{ lang('new update') }}</a>
</span>
<span class="update-check">{{ lang('feedback') }} <a href="https://github.com/devfake/flox/issues" target="_blank">GitHub</a></span>
</div>
<div class="misc-btn-wrap">

View File

@ -1,15 +1,18 @@
<template>
<div class="settings-box no-select" v-if=" ! loading">
<div class="checkbox">
<div class="setting-box">
<input type="checkbox" value="genre" v-model="genre" id="genre" @change="updateOptions"><label for="genre">{{ lang('display genre') }}</label>
</div>
<div class="checkbox">
<div class="setting-box">
<input type="checkbox" value="date" v-model="date" id="date" @change="updateOptions"><label for="date">{{ lang('display date') }}</label>
</div>
<div class="checkbox">
<div class="setting-box">
<input type="checkbox" value="spoiler" v-model="spoiler" id="spoiler" @change="updateOptions"><label for="spoiler">{{ lang('spoiler') }}</label>
</div>
<div class="setting-box">
<input type="checkbox" value="watchlist" v-model="watchlist" id="watchlist" @change="updateOptions"><label for="watchlist">{{ lang('show watchlist') }}</label>
</div>
</div>
</template>
@ -19,16 +22,12 @@
import MiscHelper from '../../../helpers/misc';
import http from 'axios';
import debounce from 'debounce';
const debounceMilliseconds = 700;
export default {
mixins: [MiscHelper],
created() {
this.fetchOptions();
this.updateOptions = debounce(this.updateOptions, debounceMilliseconds);
},
data() {
@ -36,6 +35,7 @@
genre: null,
date: null,
spoiler: null,
watchlist: null
}
},
@ -57,17 +57,23 @@
this.genre = data.genre;
this.date = data.date;
this.spoiler = data.spoiler;
this.watchlist = data.watchlist;
});
},
updateOptions() {
this.SET_LOADING(true);
const date = this.date;
const genre = this.genre;
const spoiler = this.spoiler;
const watchlist = this.watchlist;
http.patch(`${config.api}/settings`, {date, genre, spoiler}).catch(() => {
alert('Error');
});
http.patch(`${config.api}/settings`, {date, genre, spoiler, watchlist}).then(response => {
this.SET_LOADING(false);
}, error => {
alert(error.message);
})
},
}

View File

@ -10,7 +10,7 @@
<div class="big-teaser-data-wrap">
<div class="subpage-poster-wrap-mobile">
<rating :item="item" :set-item="setItem"></rating>
<rating :rated="rated" :item="item" :set-item="setItem"></rating>
<img class="base" :src="noImage" width="120" height="180">
<img class="real" :src="posterImage" width="120" height="180">
</div>
@ -23,7 +23,8 @@
</div>
<div class="big-teaser-buttons no-select" :class="{'without-watchlist': item.rating != null || ! auth}">
<span @click="openTrailer()" v-if="item.youtube_key" class="button-trailer"><i class="icon-trailer"></i> {{ lang('watch trailer') }}</span>
<span v-if="item.rating == null && auth" class="button-watchlist"><i class="icon-watchlist"></i> {{ lang('add to watchlist') }}</span>
<span class="button-watchlist" v-if="item.rating == null && auth && ! rated" @click="addToWatchlist(item)"><i class="icon-watchlist"></i> {{ lang('add to watchlist') }}</span>
<span class="button-watchlist" v-if="item.watchlist && auth && ! rated" @click="removeItem()"><i class="icon-watchlist-remove"></i> {{ lang('remove from watchlist') }}</span>
<a :href="`https://www.themoviedb.org/${item.media_type}/${item.tmdb_id}`" target="_blank" class="button-tmdb-rating">
<i v-if="item.tmdb_rating && item.tmdb_rating != 0"><b>{{ item.tmdb_rating }}</b> TMDb</i>
<i v-else>{{ lang('no tmdb rating') }}</i>
@ -48,7 +49,7 @@
<div class="subpage-sidebar">
<div class="subpage-poster-wrap">
<rating :item="item" :set-item="setItem"></rating>
<rating :rated="rated" :item="item" :set-item="setItem"></rating>
<img class="base" :src="noImage" width="272" height="408">
<img class="real" :src="posterImage" width="272" height="408">
@ -62,7 +63,7 @@
<!-- todo: move to own component -->
<div class="subpage-sidebar-buttons no-select" v-if="item.rating != null && auth">
<span class="refresh-infos" @click="refreshInfos()">{{ lang('refresh infos') }}</span>
<span class="remove-item" @click="removeItem()">{{ lang('delete item') }}</span>
<span class="remove-item" @click="removeItem()" v-if=" ! item.watchlist">{{ lang('delete item') }}</span>
</div>
</div>
</div>
@ -102,7 +103,8 @@
item: {},
latestEpisode: null,
loadingImdb: false,
auth: config.auth
auth: config.auth,
rated: false
}
},
@ -152,7 +154,7 @@
},
methods: {
...mapMutations([ 'SET_LOADING', 'SET_ITEM_LOADED_SUBPAGE', 'OPEN_MODAL', 'CLOSE_MODAL' ]),
...mapMutations([ 'SET_LOADING', 'SET_ITEM_LOADED_SUBPAGE', 'OPEN_MODAL', 'CLOSE_MODAL', 'SET_RATED' ]),
...mapActions([ 'setPageTitle', 'fetchEpisodes' ]),
openTrailer() {
@ -218,15 +220,16 @@
},
removeItem() {
const confirm = window.confirm(this.lang('confirm delete'));
this.rated = true;
if(confirm) {
http.delete(`${config.api}/remove/${this.item.id}`).then(response => {
this.item.rating = null;
}, error => {
alert(error);
});
}
http.delete(`${config.api}/remove/${this.item.id}`).then(response => {
this.rated = false;
this.item.rating = null;
this.item.watchlist = null;
}, error => {
alert(error);
this.rated = false;
});
},
refreshInfos() {

View File

@ -56,7 +56,7 @@
return this.initSuggestions();
case 'trending':
case 'upcoming':
case 'current':
case 'now-playing':
return this.initContent(this.path);
}
},

View File

@ -14,11 +14,12 @@
<ul class="site-nav">
<li><router-link to="/trending" @click.native="refresh('trending')">{{ lang('trending') }}</router-link></li>
<li><router-link to="/current" @click.native="refresh('current')">{{ lang('current') }}</router-link></li>
<li><router-link to="/now-playing" @click.native="refresh('now-playing')">{{ lang('now playing') }}</router-link></li>
<li><router-link to="/upcoming" @click.native="refresh('upcoming')">{{ lang('upcoming') }}</router-link></li>
</ul>
<ul class="site-nav-second">
<li><router-link to="/watchlist" @click.native="refresh('watchlist')" exact>{{ lang('watchlist') }}</router-link></li>
<li><router-link to="/tv" @click.native="refresh('tv')" exact>{{ lang('tv') }}</router-link></li>
<li><router-link to="/movies" @click.native="refresh('movie')" exact>{{ lang('movies') }}</router-link></li>
</ul>

View File

@ -3,10 +3,10 @@
<span v-if="item.rating != null" :class="'item-rating rating-' + item.rating" @click="changeRating()">
<i class="icon-rating"></i>
</span>
<span v-if="item.rating == null && item.tmdb_id && ! rated && auth" class="item-rating item-new" @click="addNewItem()">
<span v-if="item.rating == null && item.tmdb_id && ! localRated && auth" class="item-rating item-new" @click="addNewItem()">
<i class="icon-add"></i>
</span>
<span v-if="item.rating == null && item.tmdb_id && rated" class="item-rating item-new">
<span v-if="(item.rating == null || item.watchlist) && item.tmdb_id && localRated" class="item-rating item-new">
<span class="loader smallsize-loader"><i></i></span>
</span>
</div>
@ -20,15 +20,20 @@
const newItemMilliseconds = 200;
export default {
props: ['item', 'set-item'],
props: ['item', 'set-item', 'rated'],
data() {
return {
rated: false,
auth: config.auth
}
},
computed: {
localRated() {
return this.rated;
}
},
created() {
this.saveNewRating = debounce(this.saveNewRating, ratingMilliseconds);
this.addNewItem = debounce(this.addNewItem, newItemMilliseconds, true);
@ -39,6 +44,7 @@
if(this.auth) {
this.prevRating = this.item.rating;
this.item.rating = this.prevRating == 3 ? 1 : +this.prevRating + 1;
this.item.watchlist = false;
this.saveNewRating();
}
@ -55,8 +61,8 @@
if(this.auth) {
this.rated = true;
http.post(`${config.api}/add`, {item: this.item}).then(value => {
this.setItem(value.data);
http.post(`${config.api}/add`, {item: this.item}).then(response => {
this.setItem(response.data);
this.rated = false;
}, error => {
if(error.status == 409) {

View File

@ -1,7 +1,23 @@
import http from 'axios';
export default {
methods: {
addToWatchlist(item) {
if(this.auth) {
this.rated = true;
http.post(`${config.api}/watchlist`, {item}).then(response => {
this.setItem(response.data);
this.rated = false;
}, error => {
alert(error.message);
this.rated = false;
});
}
},
displaySeason(item) {
return item.media_type == 'tv' && item.rating != null && item.tmdb_id;
return item.media_type == 'tv' && item.rating != null && item.tmdb_id && ! item.watchlist;
},
openSeasonModal(item) {

View File

@ -20,6 +20,7 @@ export default new Router({
// todo: use props for media type
{ path: '/movies', component: Content, name: 'movie' },
{ path: '/tv', component: Content, name: 'tv' },
{ path: '/watchlist/:type?', component: Content, name: 'watchlist' },
{ path: '/movies/:tmdbId/:slug?', component: Subpage, name: 'subpage-movie', props: {mediaType: 'movie'} },
{ path: '/tv/:tmdbId/:slug?', component: Subpage, name: 'subpage-tv', props: {mediaType: 'tv'} },
@ -29,7 +30,7 @@ export default new Router({
{ path: '/suggestions', component: TMDBContent, name: 'suggestions' },
{ path: '/trending', component: TMDBContent, name: 'trending' },
{ path: '/upcoming', component: TMDBContent, name: 'upcoming' },
{ path: '/current', component: TMDBContent, name: 'current' },
{ path: '/now-playing', component: TMDBContent, name: 'now-playing' },
{ path: '*', component: Content }
]

View File

@ -30,7 +30,6 @@
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"vue-html-loader": "^1.2.3",
"vue-loader": "^9.5.1",
"vue-loader": "^9.9.5",
"webpack": "^1.13.2"
}

View File

@ -17,11 +17,15 @@
"trending": "الأكثر رواجا",
"upcoming": "المقبلة",
"current": "Current",
"now playing": "Now Playing",
"tv": "تلفاز",
"movies": "أفلام",
"last seen": "آخر المشاهدة",
"best rated": "أفضل تقييم",
"title": "Title",
"release": "Release",
"tmdb rating": "TMDb Rating",
"imdb rating": "IMDb Rating",
"change color": "تغيير الألوان",
"settings": "إعدادات",
@ -52,8 +56,12 @@
"watch trailer": "Watch Trailer",
"trailer for": "Trailer for",
"add to watchlist": "Add to Watchlist",
"remove from watchlist": "Remove from Watchlist",
"no tmdb rating": "No TMDb Rating",
"loading imdb rating": "Loading IMDb Rating...",
"no imdb rating": "No IMDb Rating",
"overview": "Overview"
"overview": "Overview",
"watchlist": "Watchlist",
"show watchlist": "Show Watchlist Items everywhere",
"feedback": "If you have any feedback for us, please open an issue on"
}

View File

@ -17,11 +17,15 @@
"trending": "Trender",
"upcoming": "Kommende",
"current": "Current",
"now playing": "Now Playing",
"tv": "TV",
"movies": "Movies",
"last seen": "Sidst set",
"best rated": "Bedst bedømt",
"title": "Title",
"release": "Release",
"tmdb rating": "TMDb Rating",
"imdb rating": "IMDb Rating",
"change color": "Skift farver",
"settings": "Indstillinger",
@ -52,8 +56,12 @@
"watch trailer": "Watch Trailer",
"trailer for": "Trailer for",
"add to watchlist": "Add to Watchlist",
"remove from watchlist": "Remove from Watchlist",
"no tmdb rating": "No TMDb Rating",
"loading imdb rating": "Loading IMDb Rating...",
"no imdb rating": "No IMDb Rating",
"overview": "Overview"
"overview": "Overview",
"watchlist": "Watchlist",
"show watchlist": "Show Watchlist Items everywhere",
"feedback": "If you have any feedback for us, please open an issue on"
}

View File

@ -17,11 +17,15 @@
"trending": "Beliebt",
"upcoming": "Kommend",
"current": "Aktuell",
"now playing": "Aktuell",
"tv": "TV",
"movies": "Filme",
"last seen": "Zuletzt gesehen",
"best rated": "Am besten bewertet",
"title": "Titel",
"release": "Release",
"tmdb rating": "TMDb Bewertung",
"imdb rating": "IMDb Bewertung",
"change color": "Farbmodus wechseln",
"settings": "Einstellungen",
@ -52,8 +56,12 @@
"watch trailer": "Trailer ansehen",
"trailer for": "Trailer für",
"add to watchlist": "Zur Watchlist",
"remove from watchlist": "Entferne Watchlist",
"no tmdb rating": "Kein TMDb Rating",
"loading imdb rating": "Lade IMDb Rating...",
"no imdb rating": "Kein IMDb Rating",
"overview": "Zusammenfassung"
"overview": "Zusammenfassung",
"watchlist": "Watchlist",
"show watchlist": "Zeige Watchlist Items überall an",
"feedback": "Solltest du Feedback für uns haben, erstelle bitte ein neues issue auf"
}

View File

@ -17,11 +17,15 @@
"trending": "Τάσεις",
"upcoming": "Προσεχείς",
"current": "Current",
"now playing": "Now Playing",
"tv": "TV",
"movies": "Ταινίες",
"last seen": "Τελευταία προβολή",
"best rated": "Καλύτερη βαθμολογία",
"title": "Title",
"release": "Release",
"tmdb rating": "TMDb Rating",
"imdb rating": "IMDb Rating",
"change color": "Αλλαγή χρωμάτων",
"settings": "Ρυθμίσεις",
@ -52,8 +56,12 @@
"watch trailer": "Watch Trailer",
"trailer for": "Trailer for",
"add to watchlist": "Add to Watchlist",
"remove from watchlist": "Remove from Watchlist",
"no tmdb rating": "No TMDb Rating",
"loading imdb rating": "Loading IMDb Rating...",
"no imdb rating": "No IMDb Rating",
"overview": "Overview"
"overview": "Overview",
"watchlist": "Watchlist",
"show watchlist": "Show Watchlist Items everywhere",
"feedback": "If you have any feedback for us, please open an issue on"
}

View File

@ -17,11 +17,15 @@
"trending": "Trending",
"upcoming": "Upcoming",
"current": "Current",
"now playing": "Now Playing",
"tv": "TV",
"movies": "Movies",
"last seen": "Last seen",
"best rated": "Best rated",
"title": "Title",
"release": "Release",
"tmdb rating": "TMDb Rating",
"imdb rating": "IMDb Rating",
"change color": "Change colors",
"settings": "Settings",
@ -52,8 +56,12 @@
"watch trailer": "Watch Trailer",
"trailer for": "Trailer for",
"add to watchlist": "Add to Watchlist",
"remove from watchlist": "Remove from Watchlist",
"no tmdb rating": "No TMDb Rating",
"loading imdb rating": "Loading IMDb Rating...",
"no imdb rating": "No IMDb Rating",
"overview": "Overview"
"overview": "Overview",
"watchlist": "Watchlist",
"show watchlist": "Show Watchlist Items everywhere",
"feedback": "If you have any feedback for us, please open an issue on"
}

View File

@ -16,11 +16,15 @@
"trending": "Popular",
"upcoming": "Próximamente",
"current": "Current",
"now playing": "Now Playing",
"tv": "TV",
"movies": "Películas",
"last seen": "Última vista",
"best rated": "Mejor calificada",
"title": "Title",
"release": "Release",
"tmdb rating": "TMDb Rating",
"imdb rating": "IMDb Rating",
"change color": "Cambiar colores",
"settings": "Configuración",
@ -50,8 +54,12 @@
"watch trailer": "Watch Trailer",
"trailer for": "Trailer for",
"add to watchlist": "Add to Watchlist",
"remove from watchlist": "Remove from Watchlist",
"no tmdb rating": "No TMDb Rating",
"loading imdb rating": "Loading IMDb Rating...",
"no imdb rating": "No IMDb Rating",
"overview": "Overview"
"overview": "Overview",
"watchlist": "Watchlist",
"show watchlist": "Show Watchlist Items everywhere",
"feedback": "If you have any feedback for us, please open an issue on"
}

View File

@ -17,11 +17,15 @@
"trending": "Tendances",
"upcoming": "Prochainement",
"current": "Current",
"now playing": "Now Playing",
"tv": "Séries TV",
"movies": "Films",
"last seen": "Dernier film/épisode vu",
"best rated": "Les mieux notés",
"title": "Title",
"release": "Release",
"tmdb rating": "TMDb Rating",
"imdb rating": "IMDb Rating",
"change color": "Changer la couleur",
"settings": "Préférences",
@ -52,8 +56,12 @@
"watch trailer": "Watch Trailer",
"trailer for": "Trailer for",
"add to watchlist": "Add to Watchlist",
"remove from watchlist": "Remove from Watchlist",
"no tmdb rating": "No TMDb Rating",
"loading imdb rating": "Loading IMDb Rating...",
"no imdb rating": "No IMDb Rating",
"overview": "Overview"
"overview": "Overview",
"watchlist": "Watchlist",
"show watchlist": "Show Watchlist Items everywhere",
"feedback": "If you have any feedback for us, please open an issue on"
}

View File

@ -17,11 +17,15 @@
"trending": "Trending",
"upcoming": "Aankomende",
"current": "Current",
"now playing": "Now Playing",
"tv": "TV",
"movies": "Films",
"last seen": "Laatst gezien",
"best rated": "Best beoordeeld",
"title": "Title",
"release": "Release",
"tmdb rating": "TMDb Rating",
"imdb rating": "IMDb Rating",
"change color": "Verander kleuren",
"settings": "Instellingen",
@ -52,8 +56,12 @@
"watch trailer": "Watch Trailer",
"trailer for": "Trailer for",
"add to watchlist": "Add to Watchlist",
"remove from watchlist": "Remove from Watchlist",
"no tmdb rating": "No TMDb Rating",
"loading imdb rating": "Loading IMDb Rating...",
"no imdb rating": "No IMDb Rating",
"overview": "Overview"
"overview": "Overview",
"watchlist": "Watchlist",
"show watchlist": "Show Watchlist Items everywhere",
"feedback": "If you have any feedback for us, please open an issue on"
}

View File

@ -95,9 +95,14 @@ main {
}
.recommend-item,
.add-to-watchlist {
.add-to-watchlist,
.remove-from-watchlist {
opacity: .9;
}
.is-on-watchlist {
opacity: 0;
}
}
}
@ -328,6 +333,7 @@ main {
}
.add-to-watchlist,
.remove-from-watchlist,
.edit-item {
position: absolute;
bottom: 0;
@ -359,6 +365,28 @@ main {
}
}
.remove-from-watchlist {
//opacity: 1 !important;
}
.is-on-watchlist {
position: absolute;
bottom: 10px;
right: 10px;
background: #238cce;
padding: 4px 5px;
@include transition(opacity);
@include media(3) {
display: none;
}
i {
margin: 0;
}
}
.edit-item {
background: $rating2;
opacity: 1;
@ -454,8 +482,132 @@ main {
color: $dark;
}
.content-submenu {
margin-bottom: 30px;
margin-top: -30px;
position: relative;
z-index: 150;
}
.sort-wrap {
float: right;
.icon-sort-time,
.icon-sort-star {
float: left;
width: 32px;
height: 30px;
margin: 0 0 0 15px;
cursor: pointer;
opacity: .6;
@include transition(opacity);
&.active {
opacity: 1;
}
&:active {
opacity: .4;
}
&:first-child {
margin: 0;
}
}
}
.sort-direction {
float: left;
padding: 0 10px;
cursor: pointer;
font-size: 18px;
color: #888;
&:active {
opacity: .6;
}
.dark & {
color: #626262;
}
i {
float: left;
font-style: normal;
}
}
.filter-wrap {
float: left;
cursor: pointer;
position: relative;
}
.current-filter {
float: left;
padding: 7px 9px;
color: #888;
font-size: 14px;
.dark & {
color: #626262;
}
}
.arrow-down {
display: inline-block;
width: 0;
height: 0;
margin-left: 2px;
vertical-align: middle;
border-top: 4px solid;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
}
.all-filters {
position: absolute;
top: 70%;
right: 0;
background: $main2;
list-style: none;
min-width: 170px;
//display: none;
opacity: 0;
visibility: hidden;
@include transition(opacity, top);
&.active {
//display: block;
opacity: 1;
top: 100%;
visibility: visible;
}
li {
float: left;
padding: 5px 10px;
color: rgba(#fff, .9);
font-size: 14px;
width: 100%;
border-bottom: 1px solid rgba(#fff, .3);
@include transition(background);
&:hover {
background: $main1;
}
&:last-child {
border: none;
}
}
}
.current-version {
margin: 0 0 10px 0;
margin: 0;
span {
color: gray;
@ -511,6 +663,17 @@ main {
float: left;
font-size: 14px;
color: gray;
clear: both;
margin: 10px 0;
a {
color: $main1;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
span {
float: left;
@ -575,7 +738,7 @@ main {
}
}
.checkbox {
.setting-box {
float: left;
width: 100%;
margin: 0 0 10px 0;

View File

@ -117,6 +117,18 @@
}
}
.icon-watchlist-remove {
background: url(../../../public/assets/img/watchlist-remove.png);
width: 14px;
height: 11px;
float: left;
margin: 7px 7px 0 0;
@include media(4) {
display: none;
}
}
.big-teaser-buttons {
float: left;
clear: both;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

File diff suppressed because one or more lines are too long