aboutsummaryrefslogtreecommitdiffstats
path: root/youtube
diff options
context:
space:
mode:
authorJames Taylor <user234683@users.noreply.github.com>2019-08-23 14:48:00 -0700
committerJames Taylor <user234683@users.noreply.github.com>2019-08-23 14:48:00 -0700
commit85572c94de77f4a51d5b64e44c6b50cbe200c946 (patch)
tree7dd9605ba1f24a32b32dbb3aadab378addc1a21a /youtube
parent70d2cff81760a5bfd2d8f54349cd96d50df5f320 (diff)
downloadyt-local-85572c94de77f4a51d5b64e44c6b50cbe200c946.tar.lz
yt-local-85572c94de77f4a51d5b64e44c6b50cbe200c946.tar.xz
yt-local-85572c94de77f4a51d5b64e44c6b50cbe200c946.zip
Layout: refactor item system to be more maintainable, add vertical item type
Diffstat (limited to 'youtube')
-rw-r--r--youtube/local_playlist.py1
-rw-r--r--youtube/static/shared.css307
-rw-r--r--youtube/templates/common_elements.html140
-rw-r--r--youtube/templates/search.html2
-rw-r--r--youtube/templates/watch.html5
-rw-r--r--youtube/watch.py2
-rw-r--r--youtube/yt_data_extract.py4
7 files changed, 158 insertions, 303 deletions
diff --git a/youtube/local_playlist.py b/youtube/local_playlist.py
index bb05d1a..4b92315 100644
--- a/youtube/local_playlist.py
+++ b/youtube/local_playlist.py
@@ -82,7 +82,6 @@ def get_local_playlist_videos(name, offset=0, amount=50):
else:
info['thumbnail'] = util.get_thumbnail_url(info['id'])
missing_thumbnails.append(info['id'])
- info['item_size'] = 'small'
info['type'] = 'video'
yt_data_extract.add_extra_html_info(info)
videos.append(info)
diff --git a/youtube/static/shared.css b/youtube/static/shared.css
index 415296a..3624272 100644
--- a/youtube/static/shared.css
+++ b/youtube/static/shared.css
@@ -118,218 +118,151 @@ body{
.item-list{
display: grid;
- grid-auto-rows: 138px;
grid-row-gap: 10px;
}
- .item-list .video-thumbnail-box{
- width:246px;
- }
- .item-list .playlist-thumbnail-box{
- width:246px;
- }
.item-grid{
- display:grid;
- grid-template-columns: repeat(auto-fill, 400px);
- grid-auto-rows: 94px;
- grid-row-gap: 10px;
+ display: flex;
+ flex-wrap: wrap;
}
- .item-grid .video-thumbnail-box{
- width:168px;
+ .item-grid > .playlist-item-box{
+ margin-right: 10px;
}
- .item-grid .playlist-thumbnail-box{
- width:168px;
+ .item-grid > * {
+ margin-bottom: 10px;
+ }
+ .item-grid .horizontal-item-box .item{
+ width:370px;
+ }
+ .item-grid .vertical-item-box .item{
}
-
-
-.medium-item-box{
-
- display:grid;
- grid-template-columns: 1fr 30px;
+.item-box{
+ display: inline-flex;
+ flex-direction: row;
}
-.medium-item{
- background-color:#bcbcbc;
- text-decoration:none;
- font-size: 12px;
- color: #767676;
-
- display: grid;
- align-content: start;
- grid-template-columns: auto 1fr auto;
- grid-template-rows: auto auto auto auto auto 1fr;
+.vertical-item-box{
}
- .medium-item .title{
- grid-column:2 / span 2;
- grid-row:1;
- justify-self:start;
- min-width: 0;
- max-height:3.6em;
- overflow:hidden;
-
- color: #333;
- font-size: 16px;
- font-weight: 500;
- text-decoration:initial;
- }
- .medium-item address{
- display:inline;
+.horizontal-item-box{
+}
+ .item{
+ background-color:#bcbcbc;
+ text-decoration:none;
+ font-size: 12px;
+ color: #767676;
}
- /*.medium-item .views{
- grid-column: 3;
- grid-row: 2;
- justify-self:end;
+
+ .horizontal-item-box .item {
+ flex-grow: 1;
+ display: grid;
+ align-content: start;
+ grid-template-columns: auto 1fr;
+ grid-template-rows: auto auto auto auto 1fr;
}
- .medium-item time{
- grid-column: 2;
- grid-row: 3;
- justify-self:start;
- }*/
- .medium-item .stats{
- grid-column: 2 / span 2;
- grid-row: 2;
- max-height:2.4em;
- overflow:hidden;
+ .vertical-item-box .item{
+ width: 168px;
}
- .medium-item .stats > *::after{
- content: " | ";
+ .thumbnail-box{
+ font-size: 0px; /* prevent newlines and blank space from creating gaps */
+ position: relative;
+ display: block;
}
- .medium-item .stats > *:last-child::after{
- content: "";
+ .horizontal-item-box .thumbnail-box{
+ grid-row: 1 / span 5;
}
-
- .medium-item .description{
- grid-column: 2 / span 2;
- grid-row: 4;
- }
- .medium-item .badges{
- grid-column: 2 / span 2;
- grid-row: 5;
- }
- /* thumbnail size */
- .medium-item img{
- /*height:138px;
- width:246px;*/
- height:100%;
- justify-self:center;
- }
-
-.small-item-box{
- color: #767676;
- font-size: 12px;
+ .no-description .thumbnail-box{
+ width: 168px;
+ height:94px;
+ }
+ .has-description .thumbnail-box{
+ width: 246px;
+ height:138px;
+ }
+ .video-item .thumbnail-info{
+ position: absolute;
+ bottom: 2px;
+ right: 2px;
+ opacity: .8;
+ color: #ffffff;
+ font-size: 12px;
+ background-color: #000000;
+ }
+ .playlist-item .thumbnail-info{
+ position: absolute;
+ right: 0px;
+ bottom: 0px;
+ height: 100%;
+ width: 50%;
+ text-align:center;
+ white-space: pre-line;
+ opacity: .8;
+ color: #cfcfcf;
+ font-size: 12px;
+ background-color: #000000;
+ }
+ .playlist-item .thumbnail-info span{ /* trick to vertically center the text */
+ position: absolute;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ }
+ .thumbnail-img{ /* center it */
+ margin: auto;
+ display: block;
+ max-height: 100%;
+ }
+ .horizontal-item-box .thumbnail-img{
+ height: 100%;
+ }
- display:grid;
- grid-template-columns: 1fr 30px;
- grid-template-rows: 94px;
-}
+ .item .title{
+ min-width: 0;
+ max-height:3.6em;
+ overflow:hidden;
-.small-item{
- background-color:#bcbcbc;
- align-content: start;
- text-decoration:none;
-
- display: grid;
- grid-template-columns: 168px 1fr;
- grid-column-gap: 5px;
- grid-template-rows: auto auto auto 1fr;
-}
- .small-item .title{
- grid-column:2;
- grid-row:1;
- margin:0;
+ color: #333;
+ font-size: 16px;
+ font-weight: 500;
+ text-decoration:initial;
+ }
- color: #333;
- font-size: 16px;
- font-weight: 500;
- text-decoration:initial;
- min-width: 0;
- justify-self:start;
+ .stats{
+ list-style: none;
+ padding: 0px;
+ margin: 0px;
+ }
+ .horizontal-stats{
+ max-height:2.4em;
+ overflow:hidden;
+ }
+ .horizontal-stats > li{
+ display: inline;
+ }
- overflow:hidden;
- max-height: 3.3em;
- line-height: 1.1em;
- }
- .small-item address{
- grid-column: 2;
- grid-row: 2;
- justify-self: start;
- }
-
- .small-item .views{
- grid-column: 2;
- grid-row: 3;
- justify-self:start;
- }
- /* thumbnail size */
- .small-item img{
- /*height:94px;
- width:168px;*/
- height:100%;
- justify-self:center;
- }
-
-.item-checkbox{
- justify-self:start;
- align-self:center;
- height:30px;
- width:30px;
-
- grid-column: 2;
-}
+ .horizontal-stats > li::after{
+ content: " | ";
+ }
+ .horizontal-stats > li:last-child::after{
+ content: "";
+ }
-/* ---Thumbnails for videos---- */
-.video-thumbnail-box{
- max-height:100%;
+ .vertical-stats{
+ display: flex;
+ flex-direction: column;
+ }
+ .stats address{
+ display: inline;
+ }
- grid-column:1;
- grid-row:1 / span 6;
-
- display:grid;
- grid-template-columns: 1fr 0fr;
-}
- .video-thumbnail-img{
- grid-column:1 / span 2;
- grid-row:1;
- }
- .video-duration{
- grid-column: 2;
- grid-row: 1;
- align-self: end;
- opacity: .8;
- color: #ffffff;
- font-size: 12px;
- background-color: #000000;
+ .item-checkbox{
+ justify-self:start;
+ align-self:center;
+ height:30px;
+ width:30px;
+ margin: 0px;
}
-/* ---Thumbnails for playlists---- */
-.playlist-thumbnail-box{
- max-height:100%;
-
- grid-column:1;
- grid-row:1 / span 6;
-
- display:grid;
- grid-template-columns: 3fr 2fr;
-}
- .playlist-thumbnail-img{
- grid-column:1 / span 2;
- grid-row:1;
- }
- .playlist-thumbnail-info{
- grid-column:2;
- grid-row:1;
-
- display: grid;
- align-items:center;
-
- text-align:center;
- white-space: pre-line;
- opacity: .8;
- color: #cfcfcf;
- background-color: #000000;
- }
.page-button-row{
justify-self:center;
diff --git a/youtube/templates/common_elements.html b/youtube/templates/common_elements.html
index 49e2fad..b9ceafa 100644
--- a/youtube/templates/common_elements.html
+++ b/youtube/templates/common_elements.html
@@ -14,121 +14,53 @@
{%- endif -%}
{% endmacro %}
-{% macro small_item(info, include_author=true) %}
- <div class="small-item-box">
- <div class="small-item">
- {% if info['type'] == 'video' %}
- <a class="video-thumbnail-box" href="{{ info['url'] }}" title="{{ info['title'] }}">
- <img class="video-thumbnail-img" src="{{ info['thumbnail'] }}">
- <span class="video-duration">{{ info['duration'] }}</span>
- </a>
- <a class="title" href="{{ info['url'] }}" title="{{ info['title'] }}">{{ info['title'] }}</a>
-
- <address>{{ info['author'] }}</address>
- <span class="views">{{ info['views'] }}</span>
-
- {% elif info['type'] == 'playlist' %}
- <a class="playlist-thumbnail-box" href="{{ info['url'] }}" title="{{ info['title'] }}">
- <img class="playlist-thumbnail-img" src="{{ info['thumbnail'] }}">
- <div class="playlist-thumbnail-info">
- <span>{{ info['size'] }}</span>
+{% macro item(info, description=false, horizontal=true, include_author=true) %}
+ <div class="item-box {{ info['type'] + '-item-box' }} {{'horizontal-item-box' if horizontal else 'vertical-item-box'}} {{'has-description' if description else 'no-description'}}">
+ <div class="item {{ info['type'] + '-item' }}">
+ <a class="thumbnail-box" href="{{ info['url'] }}" title="{{ info['title'] }}">
+ <img class="thumbnail-img" src="{{ info['thumbnail'] }}">
+ {% if info['type'] != 'channel' %}
+ <div class="thumbnail-info">
+ <span>{{ info['size'] if info['type'] == 'playlist' else info['duration'] }}</span>
</div>
- </a>
- <a class="title" href="{{ info['url'] }}" title="{{ info['title'] }}">{{ info['title'] }}</a>
-
- <address>{{ info['author'] }}</address>
- {% else %}
- Error: unsupported item type
- {% endif %}
- </div>
- {% if info['type'] == 'video' %}
- <input class="item-checkbox" type="checkbox" name="video_info_list" value="{{ info['video_info'] }}" form="playlist-edit">
- {% endif %}
- </div>
-{% endmacro %}
-
-{% macro get_stats(info, include_author=true) %}
- {% if include_author %}
- {% if 'author_url' is in(info) %}
- <address>By <a href="{{ info['author_url'] }}">{{ info['author'] }}</a></address>
- {% else %}
- <address><b>{{ info['author'] }}</b></address>
- {% endif %}
- {% endif %}
- {% if 'views' is in(info) %}
- <span class="views">{{ info['views'] }}</span>
- {% endif %}
- {% if 'published' is in(info) %}
- <time>{{ info['published'] }}</time>
- {% endif %}
-{% endmacro %}
-
-
-
-{% macro medium_item(info, include_author=true) %}
- <div class="medium-item-box">
- <div class="medium-item">
- {% if info['type'] == 'video' %}
- <a class="video-thumbnail-box" href="{{ info['url'] }}" title="{{ info['title'] }}">
- <img class="video-thumbnail-img" src="{{ info['thumbnail'] }}">
- <span class="video-duration">{{ info['duration'] }}</span>
- </a>
-
- <a class="title" href="{{ info['url'] }}" title="{{ info['title'] }}">{{ info['title'] }}</a>
-
- <div class="stats">
- {{ get_stats(info, include_author) }}
- </div>
-
+ {% endif %}
+ </a>
+
+ <a class="title" href="{{ info['url'] }}" title="{{ info['title'] }}">{{ info['title'] }}</a>
+
+ <ul class="stats {{'vertical-stats' if horizontal and not description and include_author else 'horizontal-stats'}}">
+ {% if info['type'] == 'channel' %}
+ <li><span>{{ info['subscriber_count'] }} subscribers</span></li>
+ <li><span>{{ info['size'] }} videos</span></li>
+ {% else %}
+ {% if include_author %}
+ {% if 'author_url' is in(info) %}
+ <li><address>By <a href="{{ info['author_url'] }}">{{ info['author'] }}</a></address></li>
+ {% else %}
+ <li><address><b>{{ info['author'] }}</b></address></li>
+ {% endif %}
+ {% endif %}
+ {% if 'views' is in(info) %}
+ <li><span class="views">{{ info['views'] }}</span></li>
+ {% endif %}
+ {% if 'published' is in(info) %}
+ <li><time>{{ info['published'] }}</time></li>
+ {% endif %}
+ {% endif %}
+ </ul>
+
+ {% if description %}
<span class="description">{{ text_runs(info.get('description', '')) }}</span>
- <span class="badges">{{ info['badges']|join(' | ') }}</span>
- {% elif info['type'] == 'playlist' %}
- <a class="playlist-thumbnail-box" href="{{ info['url'] }}" title="{{ info['title'] }}">
- <img class="playlist-thumbnail-img" src="{{ info['thumbnail'] }}">
- <div class="playlist-thumbnail-info">
- <span>{{ info['size'] }}</span>
- </div>
- </a>
-
- <a class="title" href="{{ info['url'] }}" title="{{ info['title'] }}">{{ info['title'] }}</a>
-
- <div class="stats">
- {{ get_stats(info, include_author) }}
- </div>
- {% elif info['type'] == 'channel' %}
- <a class="video-thumbnail-box" href="{{ info['url'] }}" title="{{ info['title'] }}">
- <img class="video-thumbnail-img" src="{{ info['thumbnail'] }}">
- </a>
-
- <a class="title" href="{{ info['url'] }}">{{ info['title'] }}</a>
-
- <span>{{ info['subscriber_count'] }} subscribers</span>
- <span>{{ info['size'] }} videos</span>
-
- <span class="description">{{ text_runs(info.get('description', '')) }}</span>
- {% else %}
- Error: unsupported item type
{% endif %}
+ <span class="badges">{{ info['badges']|join(' | ') }}</span>
</div>
{% if info['type'] == 'video' %}
<input class="item-checkbox" type="checkbox" name="video_info_list" value="{{ info['video_info'] }}" form="playlist-edit">
{% endif %}
</div>
-{% endmacro %}
-
-{% macro item(info, include_author=true) %}
- {% if info['item_size'] == 'small' %}
- {{ small_item(info, include_author) }}
- {% elif info['item_size'] == 'medium' %}
- {{ medium_item(info, include_author) }}
- {% else %}
- Error: Unknown item size
- {% endif %}
{% endmacro %}
-
-
{% macro page_buttons(estimated_pages, url, parameters_dictionary) %}
{% set current_page = parameters_dictionary.get('page', 1)|int %}
{% set parameters_dictionary = parameters_dictionary.to_dict() %}
diff --git a/youtube/templates/search.html b/youtube/templates/search.html
index 782a85e..f429da0 100644
--- a/youtube/templates/search.html
+++ b/youtube/templates/search.html
@@ -45,7 +45,7 @@
</div>
<div class="item-list">
{% for info in results %}
- {{ common_elements.item(info) }}
+ {{ common_elements.item(info, description=true) }}
{% endfor %}
</div>
<nav class="page-button-row">
diff --git a/youtube/templates/watch.html b/youtube/templates/watch.html
index 82c1a97..27f9e96 100644
--- a/youtube/templates/watch.html
+++ b/youtube/templates/watch.html
@@ -109,12 +109,9 @@
#related{
grid-column: 4;
display: grid;
- grid-auto-rows: 90px;
+ grid-auto-rows: 94px;
grid-row-gap: 10px;
}
- #related .medium-item{
- grid-template-columns: 160px 1fr 0fr;
- }
.download-dropdown{
z-index:1;
diff --git a/youtube/watch.py b/youtube/watch.py
index 5487dd4..8a08832 100644
--- a/youtube/watch.py
+++ b/youtube/watch.py
@@ -36,7 +36,6 @@ def watch_page_related_video_info(item):
except KeyError:
result['views'] = ''
result['thumbnail'] = util.get_thumbnail_url(item['id'])
- result['item_size'] = 'small'
result['type'] = 'video'
return result
@@ -47,7 +46,6 @@ def watch_page_related_playlist_info(item):
'id': item['list'],
'first_video_id': item['video_id'],
'thumbnail': util.get_thumbnail_url(item['video_id']),
- 'item_size': 'small',
'type': 'playlist',
}
diff --git a/youtube/yt_data_extract.py b/youtube/yt_data_extract.py
index c236c2f..db28e62 100644
--- a/youtube/yt_data_extract.py
+++ b/youtube/yt_data_extract.py
@@ -197,10 +197,6 @@ def renderer_info(renderer, additional_info={}):
info.update(additional_info)
- if type.startswith('compact') or (type.startswith('playlist') and type != 'playlistRenderer'):
- info['item_size'] = 'small'
- else:
- info['item_size'] = 'medium'
if type in ('compactVideoRenderer', 'videoRenderer', 'playlistVideoRenderer', 'gridVideoRenderer'):
info['type'] = 'video'