diff options
author | James Taylor <user234683@users.noreply.github.com> | 2019-08-23 14:48:00 -0700 |
---|---|---|
committer | James Taylor <user234683@users.noreply.github.com> | 2019-08-23 14:48:00 -0700 |
commit | 85572c94de77f4a51d5b64e44c6b50cbe200c946 (patch) | |
tree | 7dd9605ba1f24a32b32dbb3aadab378addc1a21a | |
parent | 70d2cff81760a5bfd2d8f54349cd96d50df5f320 (diff) | |
download | yt-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
-rw-r--r-- | youtube/local_playlist.py | 1 | ||||
-rw-r--r-- | youtube/static/shared.css | 307 | ||||
-rw-r--r-- | youtube/templates/common_elements.html | 140 | ||||
-rw-r--r-- | youtube/templates/search.html | 2 | ||||
-rw-r--r-- | youtube/templates/watch.html | 5 | ||||
-rw-r--r-- | youtube/watch.py | 2 | ||||
-rw-r--r-- | youtube/yt_data_extract.py | 4 |
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' |