Browse Source

media card work for homepage items

causefx 8 years ago
parent
commit
1148764cfd
6 changed files with 245 additions and 49 deletions
  1. 68 41
      api/functions/homepage-connect-functions.php
  2. 3 1
      api/pages/homepage.php
  3. 9 0
      css/organizr.css
  4. 2 2
      css/themes/Organizr.css
  5. 72 0
      js/custom.js
  6. 91 5
      js/functions.js

+ 68 - 41
api/functions/homepage-connect-functions.php

@@ -3,10 +3,13 @@
 function homepageConnect($array){
 	switch ($array['data']['action']) {
         case 'getPlexStreams':
-			return getPlexStreams();
+			return plexConnect('streams');
             break;
 		case 'getPlexRecent':
-        return getPlexRecent();
+            return plexConnect('recent');
+			break;
+        case 'getPlexMetadata':
+            return plexConnect('metadata',$array['data']['key']);
 			break;
         default:
             # code...
@@ -28,8 +31,8 @@ function resolvePlexItem($item) {
     // Static Height & Width
     $height = 300;
     $width = 200;
-    $nowPlayingHeight = 338;
-    $nowPlayingWidth = 600;
+    $nowPlayingHeight = 675;
+    $nowPlayingWidth = 1200;
 	$widthOverride = 100;
     // Cache Directories
     $cacheDirectory = dirname(__DIR__,2).DIRECTORY_SEPARATOR.'plugins'.DIRECTORY_SEPARATOR.'images'.DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR;
@@ -45,6 +48,7 @@ function resolvePlexItem($item) {
             $plexItem['key'] = (string)$item['ratingKey'] . "-list";
             $plexItem['nowPlayingThumb'] = (string)$item['art'];
             $plexItem['nowPlayingKey'] = (string)$item['ratingKey'] . "-np";
+            $plexItem['metadataKey'] = (string)$item['parentRatingKey'];
             break;
         case 'episode':
             $plexItem['type'] = 'tv';
@@ -57,8 +61,8 @@ function resolvePlexItem($item) {
             $plexItem['nowPlayingKey'] = (string)$item['ratingKey'] . "-np";
             $plexItem['nowPlayingTitle'] = (string)$item['grandparentTitle'].' - '.(string)$item['title'];
             $plexItem['nowPlayingBottom'] = 'S'.(string)$item['parentIndex'].' · E'.(string)$item['index'];
+            $plexItem['metadataKey'] = (string)$item['grandparentRatingKey'];
             break;
-
         case 'clip':
             $useImage = (isset($item['live']) ? "images/livetv.png" : null);
             $plexItem['type'] = 'clip';
@@ -84,7 +88,7 @@ function resolvePlexItem($item) {
             $plexItem['nowPlayingKey'] = (string)$item['ratingKey'] . "-np";
             $plexItem['nowPlayingTitle'] = (string)$item['grandparentTitle'].' - '.(string)$item['title'];
             $plexItem['nowPlayingBottom'] = (string)$item['parentTitle'];
-
+            $plexItem['metadataKey'] = isset($item['parentRatingKey']) ? (string)$item['parentRatingKey'] : (string)$item['ratingKey'];
             break;
         default:
             $plexItem['type'] = 'movie';
@@ -97,8 +101,9 @@ function resolvePlexItem($item) {
             $plexItem['nowPlayingKey'] = (string)$item['ratingKey'] . "-np";
             $plexItem['nowPlayingTitle'] = (string)$item['title'];
             $plexItem['nowPlayingBottom'] = (string)$item['year'];
+            $plexItem['metadataKey'] = (string)$item['ratingKey'];
 	}
-    $plexItem['metadataKey'] = (string)$item['ratingKey'];
+    $plexItem['uid'] = (string)$item['ratingKey'];
     $plexItem['elapsed'] = isset($item['viewOffset']) && $item['viewOffset'] !== '0' ? (int)$item['viewOffset'] : null;
     $plexItem['duration'] = isset($item['duration']) ? (int)$item['duration'] : (int)$item->Media['duration'];
     $plexItem['watched'] = ($plexItem['elapsed'] && $plexItem['duration'] ? floor(($plexItem['elapsed'] / $plexItem['duration']) * 100) : 0);
@@ -113,8 +118,15 @@ function resolvePlexItem($item) {
     $plexItem['user'] = ($GLOBALS['homepageShowStreamNames'] && qualifyRequest($GLOBALS['homepageShowStreamNamesAuth']) ) ? (string)$item->User['title'] : "";
     $plexItem['userThumb'] = ($GLOBALS['homepageShowStreamNames'] && qualifyRequest($GLOBALS['homepageShowStreamNamesAuth']) ) ? (string)$item->User['thumb'] : "";
     $plexItem['userAddress'] = ($GLOBALS['homepageShowStreamNames'] && qualifyRequest($GLOBALS['homepageShowStreamNamesAuth']) ) ? (string)$item->Player['address'] : "x.x.x.x";
+    $plexItem['address'] = $GLOBALS['plexTabURL'] ? $GLOBALS['plexTabURL']."/web/index.html#!/server/".$GLOBALS['plexID']."/details?key=/library/metadata/".$item['ratingKey'] : "https://app.plex.tv/web/app#!/server/".$GLOBALS['plexID']."/details?key=/library/metadata/".$item['ratingKey'];
+    $plexItem['nowPlayingOriginalImage'] = 'api/?v1/image&source=plex&img='.$plexItem['nowPlayingThumb'].'&height='.$nowPlayingHeight.'&width='.$nowPlayingWidth.'&key='.$plexItem['nowPlayingKey'].'$'.randString();
+    $plexItem['originalImage'] = 'api/?v1/image&source=plex&img='.$plexItem['thumb'].'&height='.$height.'&width='.$width.'&key='.$plexItem['key'].'$'.randString();
+    $plexItem['openTab'] = $GLOBALS['plexTabURL'] && $GLOBALS['plexTabName'] ? true : false;
+    $plexItem['tabName'] = $GLOBALS['plexTabName'] ? $GLOBALS['plexTabName'] : '';
+    // Stream info
     $plexItem['userStream'] = array(
         'platform' => (string)$item->Player['platform'],
+        'product' => (string)$item->Player['product'],
         'device' => (string)$item->Player['device'],
         'stream' => (string)$item->Media->Part['decision'].($item->TranscodeSession['throttled'] == '1' ? ' (Throttled)': ''),
         'videoResolution' => (string)$item->Media['videoResolution'],
@@ -128,11 +140,39 @@ function resolvePlexItem($item) {
         'container' => (string)$item->TranscodeSession['container'],
         'audioChannels' => (string)$item->TranscodeSession['audioChannels']
     );
-    $plexItem['address'] = $GLOBALS['plexTabURL'] ? $GLOBALS['plexTabURL']."/web/index.html#!/server/".$GLOBALS['plexID']."/details?key=/library/metadata/".$item['ratingKey'] : "https://app.plex.tv/web/app#!/server/".$GLOBALS['plexID']."/details?key=/library/metadata/".$item['ratingKey'];
-    $plexItem['nowPlayingOriginalImage'] = 'api/?v1/image&source=plex&img='.$plexItem['nowPlayingThumb'].'&height='.$nowPlayingHeight.'&width='.$nowPlayingWidth.'&key='.$plexItem['nowPlayingKey'].'$'.randString();
-    $plexItem['originalImage'] = 'api/?v1/image&source=plex&img='.$plexItem['thumb'].'&height='.$height.'&width='.$width.'&key='.$plexItem['key'].'$'.randString();
-    $plexItem['openTab'] = $GLOBALS['plexTabURL'] && $GLOBALS['plexTabName'] ? true : false;
-    $plexItem['tabName'] = $GLOBALS['plexTabName'] ? $GLOBALS['plexTabName'] : '';
+    // Genre catch all
+    if($item->Genre){
+        $genres = array();
+        foreach ($item->Genre as $key => $value) {
+            $genres[] = (string)$value['tag'];
+        }
+    }
+    // Actor catch all
+    if($item->Role ){
+        $actors = array();
+        foreach ($item->Role  as $key => $value) {
+            if($value['thumb']){
+                $actors[] = array(
+                    'name' =>  (string)$value['tag'],
+                    'role' =>  (string)$value['role'],
+                    'thumb' =>  (string)$value['thumb']
+                );
+            }
+        }
+    }
+    // Metadata information
+    $plexItem['metadata'] = array(
+        'guid' => (string)$item['guid'],
+        'summary' => (string)$item['summary'],
+        'rating' => (string)$item['rating'],
+        'duration' => (string)$item['duration'],
+        'originallyAvailableAt' => (string)$item['originallyAvailableAt'],
+        'year' => (string)$item['year'],
+        'studio' => (string)$item['studio'],
+        'tagline' => (string)$item['tagline'],
+        'genres' => ($item->Genre) ?  $genres : '',
+        'actors' => ($item->Role) ?  $actors : ''
+    );
     if (file_exists($cacheDirectory.$plexItem['nowPlayingKey'].'.jpg')){ $plexItem['nowPlayingImageURL'] = $cacheDirectoryWeb.$plexItem['nowPlayingKey'].'.jpg'; }
     if (file_exists($cacheDirectory.$plexItem['key'].'.jpg')){ $plexItem['imageURL']  = $cacheDirectoryWeb.$plexItem['key'].'.jpg'; }
     if (file_exists($cacheDirectory.$plexItem['nowPlayingKey'].'.jpg') && (time() - 604800) > filemtime($cacheDirectory.$plexItem['nowPlayingKey'].'.jpg') || !file_exists($cacheDirectory.$plexItem['nowPlayingKey'].'.jpg')) {
@@ -146,37 +186,24 @@ function resolvePlexItem($item) {
 	if(isset($useImage)){ $plexItem['useImage'] = $useImage; }
     return $plexItem;
 }
-function getPlexStreams(){
+function plexConnect($action,$key=null){
 	if(!empty($GLOBALS['plexURL']) && !empty($GLOBALS['plexToken']) && !empty($GLOBALS['plexID'] && qualifyRequest($GLOBALS['homepagePlexStreamsAuth']))){
+        $url = qualifyURL($GLOBALS['plexURL']);
+        switch ($action) {
+            case 'streams':
+                $url = $url."/status/sessions?X-Plex-Token=".$GLOBALS['plexToken'];
+                break;
+            case 'recent':
+                $url = $url."/library/recentlyAdded?X-Plex-Token=".$GLOBALS['plexToken'];
+                break;
+            case 'metadata':
+                $url = $url."/library/metadata/".$key."?X-Plex-Token=".$GLOBALS['plexToken'];
+                break;
+            default:
+                # code...
+                break;
+        }
 		try{
-			$url = qualifyURL($GLOBALS['plexURL']);
-			$url = $url."/status/sessions?X-Plex-Token=".$GLOBALS['plexToken'];
-			$options = (localURL($url)) ? array('verify' => false ) : array();
-			$response = Requests::get($url, array(), $options);
-			libxml_use_internal_errors(true);
-			if($response->success){
-				$items = array();
-				$plex = simplexml_load_string($response->body);
-				foreach($plex AS $child) {
-					$items[] = resolvePlexItem($child);
-				}
-				$api['content'] = $items;
-				$api['plexID'] = $GLOBALS['plexID'];
-				$api['showNames'] = true;
-				$api['group'] = '1';
-				return $api;
-			}
-		}catch( Requests_Exception $e ) {
-			writeLog('error', 'Plex Connect Function - Error: '.$e->getMessage(), 'SYSTEM');
-		};
-	}
-	return false;
-}
-function getPlexRecent(){
-	if(!empty($GLOBALS['plexURL']) && !empty($GLOBALS['plexToken']) && !empty($GLOBALS['plexID'] && qualifyRequest($GLOBALS['homepagePlexRecentAuth']))){
-		try{
-			$url = qualifyURL($GLOBALS['plexURL']);
-			$url = $url."/library/recentlyAdded?X-Plex-Token=".$GLOBALS['plexToken'];
 			$options = (localURL($url)) ? array('verify' => false ) : array();
 			$response = Requests::get($url, array(), $options);
 			libxml_use_internal_errors(true);

+ 3 - 1
api/pages/homepage.php

@@ -5,7 +5,9 @@ $pageHomepage = '
 </script>
 <link href="plugins/bower_components/owl.carousel/owl.carousel.min.css" rel="stylesheet" type="text/css" />
 <link href="plugins/bower_components/owl.carousel/owl.theme.default.css" rel="stylesheet" type="text/css" />
-<div class="container-fluid p-t-10" id="homepage-items">'.buildHomepage().'</div>
+<div class="container-fluid p-t-10" id="homepage-items">
+    '.buildHomepage().'
+</div>
 <!-- /.container-fluid -->
 ';
 }

+ 9 - 0
css/organizr.css

@@ -166,3 +166,12 @@ object-fit: contain;
   -webkit-filter: drop-shadow(0px 0px 5px #2cabe4);
   filter: drop-shadow(0px 0px 5px #2cabe4);
 }
+.user-bg {
+  margin: -25px;
+  height: 338px;
+  overflow: hidden;
+  position: relative;
+  background-size: cover;
+  background-position: center top;
+  background-repeat: no-repeat;
+}

+ 2 - 2
css/themes/Organizr.css

@@ -105,8 +105,8 @@ body {
 .customtab li.active a,
 .customtab li.active a:hover,
 .customtab li.active a:focus {
-  border-bottom: 2px solid #1f1f1f;
-  color: #1f1f1f;
+  /*border-bottom: 2px solid #1f1f1f;
+  color: #1f1f1f;*/
 }
 .tabs-vertical li.active a,
 .tabs-vertical li.active a:hover,

+ 72 - 0
js/custom.js

@@ -90,6 +90,59 @@ function pageLoad(){
         }
     });
     $(function () {
+        $(".metadata-actors").owlCarousel({
+          autoplay: true,
+          slideSpeed : 300,
+          paginationSpeed : 400,
+          margin:40,
+          nav:false,
+          autoplay:false,
+          dots:false,
+          responsive:{
+              0:{
+                  items:2
+              },
+              500:{
+                  items:3
+              },
+              650:{
+                  items:4
+              },
+              800:{
+                  items:5
+              },
+              950:{
+                  items:6
+              },
+              992:{
+                  items:4
+              },
+              1250:{
+                  items:5
+              },
+              1400:{
+                  items:6
+              },
+              1550:{
+                  items:7
+              },
+              1700:{
+                  items:8
+              },
+              1850:{
+                  items:9
+              }
+          },
+          //singleItem:true
+
+          // "singleItem:true" is a shortcut for:
+           items : 1,
+          // itemsDesktop : false,
+          // itemsDesktopSmall : false,
+          // itemsTablet: false,
+          // itemsMobile : false
+
+      });
         $('.recent-items').owlCarousel({
     	    margin:40,
     	    nav:false,
@@ -408,6 +461,8 @@ function pageLoad(){
     // Inline popups
     $('.inline-popups').magnificPopup({
       removalDelay: 500, //delay removal by X to allow out-animation
+      closeOnBgClick: true,
+      closeOnContentClick: true,
       callbacks: {
         beforeOpen: function() {
            this.st.mainClass = this.st.el.attr('data-effect');
@@ -1548,6 +1603,23 @@ $(document).on("click", ".openTab", function(e) {
 		window.open(source, '_blank');
 	}
 });
+// metadata start
+$(document).on("click", ".metadata-get", function(e) {
+    $('.metadata-info').html('');
+    var key = $(this).attr('data-key');
+    var uid = $(this).attr('data-uid');
+    ajaxloader(".content-wrap","in");
+	organizrAPI('POST','api/?v1/homepage/connect',{action:'getPlexMetadata', key:key}).success(function(data) {
+		var response = JSON.parse(data);
+        console.log(response);
+		$('.'+uid+'-metadata-info').html(buildMetadata(response.data));
+        $('.'+uid).trigger('click')
+	}).fail(function(xhr) {
+		console.error("Organizr Function: API Connection Failed");
+	});
+	ajaxloader();
+
+});
 /* ===== Open-Close Right Sidebar ===== */
 
 $(document).on("click", ".right-side-toggle", function () {

+ 91 - 5
js/functions.js

@@ -1679,6 +1679,7 @@ function radioLoop(element){
 }
 function loadAppearance(appearance){
 	//console.log(appearance);
+	document.title = appearance.title;
 	if(appearance.useLogo === false){
 		$('#main-logo').html(appearance.title);
 		$('#side-logo').html(appearance.title);
@@ -1857,10 +1858,10 @@ function buildPlexStreamItem(array){
 						<div class="el-overlay">
 							<ul class="el-info p-t-20 m-t-20">
 								<li><a class="btn default btn-outline inline-popups" href="#`+v.session+`" data-effect="mfp-zoom-out"><i class="mdi mdi-server-network mdi-24px"></i></a></li>
-								<li><a class="btn default btn-outline image-popup-vertical-fit" href="`+v.nowPlayingImageURL+`"><i class="mdi mdi-information mdi-24px"></i></a></li>
+								<li><a class="btn default btn-outline metadata-get" data-key="`+v.metadataKey+`" data-uid="`+v.uid+`"><i class="mdi mdi-information mdi-24px"></i></a></li>
 								<li><a class="btn default btn-outline openTab" data-tab-name="`+v.tabName+`" data-type="`+v.type+`" data-open-tab="`+v.openTab+`" data-url="`+v.address+`" href="javascript:void(0);"><i class=" mdi mdi-plex mdi-24px"></i></a></li>
 								<li><a class="btn default btn-outline refreshImage" data-image="`+v.nowPlayingOriginalImage+`" href="javascript:void(0);"><i class="mdi mdi-refresh mdi-24px"></i></a></li>
-								<!--<li><a class="btn default btn-outline" href="javascript:void(0);"><i class="icon-graph"></i></a></li>-->
+								<a class="inline-popups `+v.uid+` hidden" href="#`+v.uid+`-metadata-div" data-effect="mfp-zoom-out"></a>
 							</ul>
 						</div>
 					</div>
@@ -1893,7 +1894,7 @@ function buildPlexStreamItem(array){
 									<span class="text-uppercase"><i class="mdi mdi-`+v.bandwidthType+`"></i> `+v.bandwidthType+`</span>
 									<span class="text-uppercase"><i class="mdi mdi-account-network"></i> `+v.userAddress+`</span>
 									`+streamInfo+`
-									<div class="text-muted m-t-20 text-uppercase"><span class="text-uppercase"><i class="mdi mdi-ticket-account"></i> Platform: `+v.userStream.platform+`</span></div>
+									<div class="text-muted m-t-20 text-uppercase"><span class="text-uppercase"><i class="mdi mdi-plex"></i> Product: `+v.userStream.product+`</span></div>
 									<div class="text-muted m-t-20 text-uppercase"><span class="text-uppercase"><i class="mdi mdi-laptop-mac"></i> Device: `+v.userStream.device+`</span></div>
 								</div>
 								<div data-label="`+v.watched+`%" class="css-bar css-bar-`+Math.ceil(v.watched/5)*5+` css-bar-lg m-b-0  css-bar-info pull-right">`+userThumb+`</div>
@@ -1904,6 +1905,11 @@ function buildPlexStreamItem(array){
                 </div>
 			</div>
 		</div>
+		<div id="`+v.uid+`-metadata-div" class="white-popup mfp-with-anim mfp-hide">
+	        <div class="row">
+	            <div class="col-md-8 col-md-offset-2 `+v.uid+`-metadata-info"></div>
+	        </div>
+	    </div>
 		`;
 		if(contains(''+count, end) || count == total ){ cards += '</div><!--end-->'; };
 
@@ -1927,7 +1933,18 @@ function buildPlexRecentItem(array){
 			default:
 
 		}
-		items += '<div class="item lazyload '+className+'" data-src="'+v.imageURL+'"><span class="elip recent-title">'+v.title+'</span></div>';
+		items += `
+		<div class="item lazyload `+className+` metadata-get" data-key="`+v.metadataKey+`" data-uid="`+v.uid+`" data-src="`+v.imageURL+`">
+			<span class="elip recent-title">`+v.title+`</span>
+			<a class="inline-popups `+v.uid+` hidden" href="#`+v.uid+`-metadata-div" data-effect="mfp-zoom-out"></a>
+			<div id="`+v.uid+`-metadata-div" class="white-popup mfp-with-anim mfp-hide">
+		        <div class="row">
+		            <div class="col-md-8 col-md-offset-2 `+v.uid+`-metadata-info"></div>
+		        </div>
+		    </div>
+		</div>
+		`;
+
 
 	});
 	return items;
@@ -1973,7 +1990,7 @@ function buildPlexRecent(array){
 					<div class="clearfix"></div>
 				</div>
 
-                <div class="panel-wrapper p-b-10 collapse in">
+                <div class="panel-wrapper p-b-0 collapse in">
                     <div class="owl-carousel owl-theme recent-items plex-recent">
 						`+buildPlexRecentItem(array.content)+`
                     </div>
@@ -1983,6 +2000,75 @@ function buildPlexRecent(array){
     </div>
 	` : '';
 }
+function buildMetadata(array){
+	var metadata = '';
+	var genres = '';
+	var actors = '';
+	var rating = '<div class="col-xs-4 p-10"></div>';
+	$.each(array.content, function(i,v) {
+		console.log(typeof v.metadata.actors)
+		var hasActor = (typeof v.metadata.actors !== 'string') ? true : false;
+		if(hasActor){
+			$.each(v.metadata.actors, function(i,v) {
+				actors = '<div class="item lazyload recent-poster" data-src="'+v.thumb+'" alt="'+v.name+'" ><span class="elip recent-title">'+v.name+'</span></div>';
+			});
+		}
+		if(v.metadata.rating){
+			var ratingRound = Math.ceil(v.metadata.rating)*10;
+			rating = `<div class="col-xs-4 p-10"><div data-label="`+v.metadata.rating *10+`%" class="css-bar css-bar-`+Math.ceil(ratingRound/5)*5+` css-bar-sm m-b-0  css-bar-info"></div></div>`;
+		}
+
+		var seconds = v.metadata.duration / 1000 ; // or "2000"
+		seconds = parseInt(seconds) //because moment js dont know to handle number in string format
+		var format =  Math.floor(moment.duration(seconds,'seconds').asHours()) + ':' + moment.duration(seconds,'seconds').minutes() + ':' + moment.duration(seconds,'seconds').seconds();
+		console.log(format)
+
+		metadata = `
+		<div class="white-box m-b-0">
+			<div class="user-bg lazyload" data-src="`+v.nowPlayingImageURL+`">
+				`+rating+`
+				<div class="col-xs-8">
+	                <h2 class="m-b-0 font-medium pull-right">`+v.title+`<br>    <small class="text-muted m-t-0">`+v.metadata.tagline+`</small></h2>
+
+	            </div>
+			</div>
+		</div>
+		<div class="panel panel-info p-b-0 p-t-0">
+            <div class="panel-body p-b-0 p-t-0">
+				<div class="row text-center m-t-0">
+					<div class="col-xs-4 b-r">
+						<h2></h2>
+						<h4></h4>
+					</div>
+					<div class="col-xs-4 b-r">
+						<h2></h2>
+						<h4></h4>
+					</div>
+					<div class="col-xs-4">
+						<h2><a class="openTab" data-tab-name="`+v.tabName+`" data-type="`+v.type+`" data-open-tab="`+v.openTab+`" data-url="`+v.address+`" href="javascript:void(0);"><i class=" mdi mdi-plex mdi-24px"></i></a></h2>
+						<h4>Open Now</h4>
+					</div>
+				</div>
+				<div class="p-20 text-center">
+					<p class="">`+v.metadata.summary+`</p>
+					<hr>
+				</div>
+				<div class="row">
+					<div class="col-lg-12">
+						<div class="panel panel-default">
+							<div class="panel-wrapper p-b-0 collapse in">
+								<div class="owl-carousel owl-theme metadata-actors">`+actors+`</div>
+							</div>
+						</div>
+					</div>
+				</div>
+            </div>
+        </div>
+
+		`;
+	});
+	return metadata;
+}
 function plexStream(){
 	ajaxloader(".content-wrap","in");
 	organizrAPI('POST','api/?v1/homepage/connect',{action:'getPlexStreams'}).success(function(data) {