Commit 9ffac488 authored by Carlos Knippschild's avatar Carlos Knippschild Committed by Commit Bot

Update the list presentation of offline content on the dino page

This is a thorough update of the presentation of offline content on the
dino page to match the currently proposed design.

Bug: 852872
Change-Id: I93ead161e14da48742a2791927ed813e9d431c74
Reviewed-on: https://chromium-review.googlesource.com/1232398
Commit-Queue: Carlos Knippschild <carlosk@chromium.org>
Reviewed-by: default avatarDan H <harringtond@google.com>
Reviewed-by: default avatarEdward Jung <edwardjung@chromium.org>
Reviewed-by: default avatarChris Palmer <palmer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595937}
parent dc12f84a
......@@ -7,8 +7,11 @@ module chrome.mojom;
import "url/mojom/url.mojom";
// Categorizes suggested content for metrics reporting.
// This enum is backed by a UMA histogram therefore its entries should not be
// deleted or re-ordered and new ones should only be appended.
// This enum duplicates the values from the NetErrorOfflineSuggestionType
// metrics enum in enums.xml therefore its entries should not be deleted
// or re-ordered and new ones should only be appended. Furthermore, changes
// to this enum might effect the presentation logic in
// components/neterror/resources/neterror.js.
enum AvailableContentType {
// The offline page is prefetched suggested content.
kPrefetchedUnopenedPage = 0,
......
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6Z" fill="#3C4043" /></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" width="24" height="24">
<defs>
<path id="a" d="M0 0h24v24H0V0z"/>
</defs>
<clipPath id="b">
<use xlink:href="#a" overflow="visible"/>
</clipPath>
<path clip-path="url(#b)" d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zm5 16H7v-2h10v2zm-6.7-4L7 10.7l1.4-1.4 1.9 1.9 5.3-5.3L17 7.3 10.3 14z" fill="rgb(154, 160, 166)"/>
</svg>
......@@ -323,7 +323,8 @@ a {
}
#download-link, #download-link-clicked {
margin-bottom: 15px;
margin-bottom: 30px;
margin-top: 30px;
}
#download-link-clicked {
......@@ -342,57 +343,201 @@ a {
opacity: 0;
}
.offline-content-suggestion-image {
height: 35vw;
line-height: 0;
width: 35vw;
flex-basis: 35vw;
flex-grow: 0;
.offline-content-list-title {
color: rgb(95, 99, 104);
font-size: .8em;
line-height: 1;
margin-bottom: .8em;
}
#offline-content-suggestions {
margin-inline-start: -5%;
width: 110%;
}
/* The selectors below adjust the "overflow" of the suggestion cards contents
* based on the same screen size based strategy used for the main frame, which
* is applied by the `interstitial-wrapper` class. */
@media (max-width: 700px) {
#offline-content-suggestions {
margin-inline-start: -5%;
width: 110%;
}
}
@media (max-width: 420px) {
#offline-content-suggestions {
margin-inline-start: -2.5%;
width: 105%;
}
}
@media (max-width: 420px) and (orientation: portrait),
(max-height: 560px) {
#offline-content-suggestions {
margin-inline-start: -12px;
width: calc(100% + 24px);
}
}
.suggestion-with-image .offline-content-suggestion-visual {
flex-basis: 8.2em;
flex-shrink: 0;
}
.offline-content-suggestion-image > img {
border-bottom-left-radius: 15px;
border-top-left-radius: 15px;
height: 35vw;
line-height: 0;
width: 35vw;
.suggestion-with-image .offline-content-suggestion-visual > img {
height: 100%;
width: 100%;
}
#offline-content-list:not(.is-rtl) .suggestion-with-image
.offline-content-suggestion-visual > img {
border-bottom-right-radius: 8px;
border-top-right-radius: 8px;
}
#offline-content-list.is-rtl .suggestion-with-image
.offline-content-suggestion-visual > img {
border-bottom-left-radius: 8px;
border-top-left-radius: 8px;
}
.suggestion-with-icon .offline-content-suggestion-visual {
align-items: center;
display: flex;
justify-content: center;
min-height: 4.2em;
min-width: 4.2em;
}
.suggestion-with-icon .offline-content-suggestion-visual > div {
align-items: center;
background-color: rgb(241, 243, 244);
border-radius: 50%;
display: flex;
height: 2.3em;
justify-content: center;
width: 2.3em;
}
.suggestion-with-icon .offline-content-suggestion-visual > div > img {
height: 1.45em;
width: 1.45em;
}
.image-video {
content: url(images/video.svg);
}
.image-music-note {
content: url(images/music-note.svg);
}
.image-earth {
content: url(images/earth.svg);
}
.image-file {
content: url(images/file.svg);
}
.offline-content-suggestion-texts {
display: flex;
flex-direction: column;
justify-content: space-between;
line-height: 1.3;
padding: .9em;
width: 100%;
}
.offline-content-suggestion-title {
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
color: rgb(32, 33, 36);
display: -webkit-box;
margin: 5%;
max-height: 65px;
font-size: 1.1em;
overflow: hidden;
text-overflow: ellipsis;
}
.offline-content-suggestion-freshness, .offline-content-suggestion-attribution {
color: #646464;
display: inline-block;
font-size: small;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
div.offline-content-suggestion {
align-items: stretch;
border-color: rgb(218, 220, 224);
border-radius: 8px;
border-style: solid;
border-width: 1px;
display: flex;
justify-content: space-between;
margin-bottom: .8em;
}
.suggestion-with-image {
flex-direction: row;
height: 8.2em;
max-height: 8.2em;
}
.suggestion-with-icon {
flex-direction: row-reverse;
height: 4.2em;
max-height: 4.2em;
}
.suggestion-with-icon .offline-content-suggestion-title {
-webkit-line-clamp: 1;
word-break: break-all;
}
.suggestion-with-icon .offline-content-suggestion-texts {
padding-inline-start: 0px;
}
.offline-content-suggestion-attribution-freshness {
color: rgb(95, 99, 104);
display: flex;
font-size: .8em;
}
.offline-content-suggestion-attribution {
margin-left: 5%;
max-width: 35%;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
display: -webkit-box;
flex-shrink: 1;
overflow-wrap: break-word;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
word-break: break-all;
}
div.offline-content-suggestion {
background-color: rgb(241, 243, 244);
border-radius: 15px;
display: flex;
margin-bottom: 5%;
margin-left: 0;
margin-right: 0;
margin-top: 5%;
.offline-content-suggestion-freshness:before {
content: '-';
display: inline-block;
flex-shrink: 0;
margin-inline-end: .1em;
margin-inline-start: .1em;
}
.no-attribution .offline-content-suggestion-freshness:before {
display: none;
}
.offline-content-suggestion-freshness {
flex-shrink: 0;
}
.suggestion-with-image .offline-content-suggestion-pin-spacer {
flex-shrink: 1;
flex-grow: 100;
}
.suggestion-with-image .offline-content-suggestion-pin {
content: url(images/offline_pin.svg);
flex-shrink: 0;
height: 1.4em;
margin-inline-start: .4em;
width: 1.4em;
}
.offline-content-list-action {
text-align: center;
}
#offline-content-summary {
......
......@@ -62,7 +62,18 @@
</div>
</div>
</div>
<div id="offline-content-list" hidden></div>
<div id="offline-content-list" hidden>
<webview>
<div class="offline-content-list-title" jsselect="offlineContentList"
jscontent="title"></div>
<div id="offline-content-suggestions"></div>
<div class="offline-content-list-action">
<a class="link-button" onclick="launchDownloadsPage()"
jsselect="offlineContentList" jscontent="actionText">
</a>
</div>
</webview>
</div>
<div id="offline-content-summary" onclick="launchDownloadsPage()" hidden>
<div class="offline-content-summary-images">
<div class="offline-content-summary-image-truncate">
......
......@@ -164,30 +164,6 @@ function toggleErrorInformationPopup() {
.classList.toggle(HIDDEN_CLASS);
}
function getSuggestedContentDiv(item) {
var visual = '';
if (item.thumbnail_data_uri) {
// html_inline.py will try to replace src attributes with data URIs using
// a simple regex. The following is obfuscated slightly to avoid that.
var src = 'src';
visual = `<img ${src}="${item.thumbnail_data_uri}">`;
}
return `
<div class="offline-content-suggestion"
onclick="launchOfflineItem('${item.ID}', '${item.name_space}')">
<div class="offline-content-suggestion-image">${visual}</div>
<div>
<div class="offline-content-suggestion-title">${item.title}</div>
<span class="offline-content-suggestion-attribution">${
item.attribution
}</span>
<span class="offline-content-suggestion-freshness">${
item.date_modified
}</span>
</div>
</div>`;
}
function launchOfflineItem(itemID, name_space) {
errorPageController.launchOfflineItem(itemID, name_space);
}
......@@ -204,28 +180,80 @@ function offlineContentSummaryAvailable(summary) {
document.getElementById('offline-content-summary').hidden = false;
}
function getIconForSuggestedItem(item) {
// Note: |item.content_type| contains the enum values from
// chrome::mojom::AvailableContentType.
switch (item.content_type) {
case 1: // kVideo
return 'image-video';
case 2: // kAudio
return 'image-music-note';
case 0: // kPrefetchedUnopenedPage
case 3: // kOtherPage
return 'image-earth';
}
return 'image-file';
}
function getSuggestedContentDiv(item) {
// Note: See AvailableContentToValue in available_offline_content_helper.cc
// for the data contained in an |item|.
var visual = '';
var extraContainerClasses = [];
// html_inline.py will try to replace src attributes with data URIs using a
// simple regex. The following is obfuscated slightly to avoid that.
var src = 'src';
if (item.thumbnail_data_uri) {
extraContainerClasses.push('suggestion-with-image');
visual = `<img ${src}="${item.thumbnail_data_uri}">`;
} else {
extraContainerClasses.push('suggestion-with-icon');
iconClass = getIconForSuggestedItem(item);
visual = `<div><img class="${iconClass}"></div>`;
}
if (!item.attribution)
extraContainerClasses.push('no-attribution');
return `
<div class="offline-content-suggestion ${extraContainerClasses.join(' ')}"
onclick="launchOfflineItem('${item.ID}', '${item.name_space}')">
<div class="offline-content-suggestion-texts">
<div class="offline-content-suggestion-title">
${item.title}
</div>
<div class="offline-content-suggestion-attribution-freshness">
<div class="offline-content-suggestion-attribution">
${item.attribution}
</div>
<div class="offline-content-suggestion-freshness">
${item.date_modified}
</div>
<div class="offline-content-suggestion-pin-spacer"></div>
<div class="offline-content-suggestion-pin"></div>
</div>
</div>
<div class="offline-content-suggestion-visual">
${visual}
</div>
</div>`;
}
// Populates a list of suggested offline content.
// TODO(https://crbug.com/852872): Finish implementing offline content list UI.
function offlineContentAvailable(content) {
if (!content || !loadTimeData.valueExists('offlineContentList'))
function offlineContentAvailable(suggestions) {
if (!suggestions || !loadTimeData.valueExists('offlineContentList'))
return;
var contentTitle = loadTimeData.getValue('offlineContentList').title;
var contentOpenAllButton =
loadTimeData.getValue('offlineContentList').actionText;
var suggestionsHTML = [];
suggestionsHTML.push(`<p style="text-align: center;">${contentTitle}</p>`);
for (var c of content)
suggestionsHTML.push(getSuggestedContentDiv(c));
suggestionsHTML.push(`
<div>
<a class="link-button" onclick="launchDownloadsPage()">${
contentOpenAllButton
}</a>
</div>`);
var offlineContentDiv = document.getElementById('offline-content-list');
offlineContentDiv.innerHTML = suggestionsHTML.join('\n');
offlineContentDiv.hidden = false;
for (var item of suggestions)
suggestionsHTML.push(getSuggestedContentDiv(item));
document.getElementById('offline-content-suggestions').innerHTML =
suggestionsHTML.join('\n');
var contentListElement = document.getElementById('offline-content-list')
contentListElement.hidden = false;
if (document.dir == 'rtl')
contentListElement.classList.add('is-rtl');
}
function onDocumentLoad() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment