From f9299eee2aa4e527813f15b7e47533707f9d99e5 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 2 Dec 2023 22:43:16 +0400 Subject: [PATCH] Apply app color scheme, test dynamic header. --- Telegram/Resources/iv_html/page.css | 1049 +++++++++++---------- Telegram/Resources/iv_html/page.js | 16 +- Telegram/SourceFiles/iv/iv_controller.cpp | 192 +++- Telegram/SourceFiles/iv/iv_controller.h | 10 + Telegram/SourceFiles/iv/iv_prepare.cpp | 9 +- 5 files changed, 727 insertions(+), 549 deletions(-) diff --git a/Telegram/Resources/iv_html/page.css b/Telegram/Resources/iv_html/page.css index b5feac073..6f27a6e1c 100644 --- a/Telegram/Resources/iv_html/page.css +++ b/Telegram/Resources/iv_html/page.css @@ -1,871 +1,884 @@ body { - font-family: 'Helvetica Neue'; - font-size: 17px; - line-height: 25px; - padding: 0; - margin: 0; + font-family: 'Helvetica Neue'; + font-size: 17px; + line-height: 25px; + padding: 0; + margin: 0; + background-color: var(--td-window-bg); + color: var(--td-window-fg); } + +html.custom_scroll ::-webkit-scrollbar { + border-radius: 5px !important; + border: 3px solid transparent !important; + background-color: var(--td-scroll-bg) !important; + background-clip: content-box !important; + width: 10px !important; +} +html.custom_scroll ::-webkit-scrollbar:hover { + background-color: var(--td-scroll-bg-over) !important; +} +html.custom_scroll ::-webkit-scrollbar-thumb { + border-radius: 5px !important; + border: 3px solid transparent !important; + background-color: var(--td-scroll-bar-bg) !important; + background-clip: content-box !important; +} +html.custom_scroll ::-webkit-scrollbar-thumb:hover { + background-color: var(--td-scroll-bar-bg-over) !important; +} + article { - padding-bottom: 12px; - overflow: hidden; - white-space: pre-wrap; - max-width: 732px; - margin: 0 auto; + padding-bottom: 12px; + overflow: hidden; + white-space: pre-wrap; + max-width: 732px; + margin: 0 auto; } article h1, article h2 { - font-family: 'Georgia'; - font-size: 28px; - line-height: 31px; - margin: 21px 18px 12px; - font-weight: normal; - min-height: 31px; + font-family: 'Georgia'; + font-size: 28px; + line-height: 31px; + margin: 21px 18px 12px; + font-weight: normal; + min-height: 31px; } article h2 { - font-size: 24px; - line-height: 30px; - margin: -6px 18px 12px; - color: #777; -} -article h6.kicker { - font-family: 'Helvetica Neue'; - font-size: 14px; - line-height: 17px; - margin: 21px 18px 12px; - font-weight: 500; - color: #79828B; -} -article h6.kicker + h1 { - margin-top: 12px; + font-size: 24px; + line-height: 30px; + margin: -6px 18px 12px; + color: var(--td-window-sub-text-fg); } article address { - font-size: 15px; - color: #79828B; - margin: 12px 18px 21px; - font-style: normal; + font-size: 15px; + color: var(--td-window-sub-text-fg); + margin: 12px 18px 21px; + font-style: normal; } article.rtl address { - direction: ltr; - text-align: right; + direction: ltr; + text-align: right; } article address figure { - width: 25px; - height: 25px; - float: right; - margin: 0 0 0 12px; - background: no-repeat center; - background-size: cover; - border-radius: 50%; + width: 25px; + height: 25px; + float: right; + margin: 0 0 0 12px; + background: no-repeat center; + background-size: cover; + border-radius: 50%; } article address a, article address a[href] { - color: #79828B; + color: var(--td-window-sub-text-fg); } article address a[href] { - text-decoration: underline; + text-decoration: underline; } article a[href] { - color: #007EE5; - text-decoration: none; + color: var(--td-window-active-text-fg); + text-decoration: none; } article span.reference { - border: dotted #ddd; - border-width: 1px 1px 1px 2px; - background: rgba(255, 255, 255, 0.7); - margin: 0 1px; - padding: 2px; - position: relative; + border: dotted var(--td-window-sub-text-fg); + border-width: 1px 1px 1px 2px; + background: rgba(255, 255, 255, 0.7); + margin: 0 1px; + padding: 2px; + position: relative; } article.rtl span.reference { - border-width: 1px 0 1px 1px; + border-width: 1px 0 1px 1px; } article code { - font-size: 0.94em; - background: #eee; - border-radius: 2px; - padding: 0 3px 1px; + font-size: 0.94em; + background: var(--td-box-divider-bg); + border-radius: 2px; + padding: 0 3px 1px; } article mark { - background: #fcf8e3; - border-radius: 2px; - padding: 0 3px 1px; + background: var(--td-window-bg-over); + color: var(--td-window-fg); + border-radius: 2px; + padding: 0 3px 1px; } article sup, article sub { - font-size: 0.75em; - line-height: 1; + font-size: 0.75em; + line-height: 1; } article p { - margin: 0 18px 12px; - word-wrap: break-word; + margin: 0 18px 12px; + word-wrap: break-word; } article ul p, article ol p { - margin: 0 0 6px; + margin: 0 0 6px; } article pre, article pre.hljs { - font-family: Menlo; - margin: 14px 0; - padding: 7px 18px; - background: #F5F8FC; - font-size: 16px; - white-space: pre-wrap; - word-wrap: break-word; - overflow-x: visible; - position: relative; + font-family: Menlo; + margin: 14px 0; + padding: 7px 18px; + background: #F5F8FC; + font-size: 16px; + white-space: pre-wrap; + word-wrap: break-word; + overflow-x: visible; + position: relative; } article ul pre, article ol pre, article ul pre.hljs, article ol pre.hljs { - margin: 6px 0 6px -18px; + margin: 6px 0 6px -18px; } article.rtl ul pre, article.rtl ol pre, article.rtl ul pre.hljs, article.rtl ol pre.hljs { - margin-right: -18px; - margin-left: 0; + margin-right: -18px; + margin-left: 0; } article pre + pre { - margin-top: -14px; + margin-top: -14px; } article h3, article h4 { - font-family: 'Georgia'; - font-size: 24px; - line-height: 30px; - margin: 18px 18px 9px; - font-weight: normal; + font-family: 'Georgia'; + font-size: 24px; + line-height: 30px; + margin: 18px 18px 9px; + font-weight: normal; } article h4 { - font-size: 19px; - margin: 18px 18px 7px; + font-size: 19px; + margin: 18px 18px 7px; } article ul h3, article ol h3 { - margin: 12px 0 7px; + margin: 12px 0 7px; } article ul h4, article ol h4 { - margin: 10px 0 5px; + margin: 10px 0 5px; } article blockquote { - font-family: 'Georgia'; - margin: 18px 18px 16px; - padding-left: 22px; - position: relative; - font-style: italic; - word-wrap: break-word; + font-family: 'Georgia'; + margin: 18px 18px 16px; + padding-left: 22px; + position: relative; + font-style: italic; + word-wrap: break-word; } article blockquote:before { - content: ''; - position: absolute; - left: 1px; - top: 3px; - bottom: 3px; - width: 3px; - background-color: #000; - border-radius: 3px; + content: ''; + position: absolute; + left: 1px; + top: 3px; + bottom: 3px; + width: 3px; + background-color: var(--td-window-bg-active); + border-radius: 3px; } article.rtl blockquote { - padding-right: 22px; - padding-left: 0; + padding-right: 22px; + padding-left: 0; } article.rtl blockquote:before { - right: 1px; - left: auto; + right: 1px; + left: auto; } article aside { - font-family: 'Georgia'; - margin: 18px 18px 16px; - padding: 0 18px; - text-align: center; - font-style: italic; + font-family: 'Georgia'; + margin: 18px 18px 16px; + padding: 0 18px; + text-align: center; + font-style: italic; } article ul blockquote, article ol blockquote, article ul aside, article ol aside { - margin: 12px 0 10px; + margin: 12px 0 10px; } article blockquote cite, article aside cite, article footer cite, article .iv-pullquote cite { - font-family: 'Helvetica Neue'; - font-size: 15px; - display: block; - color: #79828B; - line-height: 19px; - padding: 5px 0 2px; - font-style: normal; + font-family: 'Helvetica Neue'; + font-size: 15px; + display: block; + color: var(--td-window-sub-text-fg); + line-height: 19px; + padding: 5px 0 2px; + font-style: normal; } article hr { - width: 50%; - margin: 36px auto 26px; - padding: 2px 0 10px; - border: none; + width: 50%; + margin: 36px auto 26px; + padding: 2px 0 10px; + border: none; } article ul hr, article ol hr { - margin: 18px auto; + margin: 18px auto; } article hr:before { - content: ''; - display: block; - border-top: 1px solid #c9cdd1; - padding: 0 0 2px; + content: ''; + display: block; + border-top: 1px solid var(--td-window-sub-text-fg); + padding: 0 0 2px; } article footer hr { - margin: 18px auto 6px; + margin: 18px auto 6px; } article ul, article ol { - margin: 0 18px 12px; - padding-left: 18px; + margin: 0 18px 12px; + padding-left: 18px; } article.rtl ul, article.rtl ol { - padding-right: 18px; - padding-left: 0; + padding-right: 18px; + padding-left: 0; } /*article ul { - list-style: none; + list-style: none; }*/ article ul > li, article ol > li { - padding-left: 4px; + padding-left: 4px; } article.rtl ul > li, article.rtl ol > li { - padding-right: 4px; - padding-left: 0; + padding-right: 4px; + padding-left: 0; } /*article ul > li { - position: relative; + position: relative; } article ul > li:before { - content: '\2022'; - position: absolute; - display: block; - font-size: 163%; - left: -19px; - top: 1px; + content: '\2022'; + position: absolute; + display: block; + font-size: 163%; + left: -19px; + top: 1px; } article.rtl ul > li:before { - left: auto; - right: -19px; + left: auto; + right: -19px; }*/ article ul ul, article ul ol, article ol ul, article ol ol { - margin: 0 0 12px; + margin: 0 0 12px; } article table { - width: 100%; - border-collapse: collapse; + width: 100%; + border-collapse: collapse; } article table.bordered, article table.bordered td, article table.bordered th { - border: 1px solid #ddd; + border: 1px solid var(--td-box-divider-fg); } article table.striped tr:nth-child(odd) td { - background-color: #f7f7f7; + background-color: var(--td-box-divider-bg); } article table caption { - font-size: 15px; - line-height: 18px; - margin: 4px 0 7px; - text-align: left; - color: #79828B; + font-size: 15px; + line-height: 18px; + margin: 4px 0 7px; + text-align: left; + color: var(--td-window-sub-text-fg); } article.rtl table caption { - text-align: right; + text-align: right; } article td, article th { - font-size: 15px; - line-height: 21px; - padding: 6px 5px 5px; - background-color: #fff; - vertical-align: middle; - font-weight: normal; - text-align: left; + font-size: 15px; + line-height: 21px; + padding: 6px 5px 5px; + background-color: var(--td-window-bg); + vertical-align: middle; + font-weight: normal; + text-align: left; } article th { - background-color: #efefef; + background-color: var(--td-box-divider-bg); } article.rtl table td, article.rtl table th { - text-align: right; + text-align: right; } article details { - position: relative; - margin: 0 0 12px; - padding: 0 0 1px; + position: relative; + margin: 0 0 12px; + padding: 0 0 1px; } article details:before { - content: ''; - display: block; - border-bottom: 1px solid #c8c7cb; - position: absolute; - left: 18px; - right: 0; - bottom: 0; + content: ''; + display: block; + border-bottom: 1px solid var(--td-box-divider-fg); + position: absolute; + left: 18px; + right: 0; + bottom: 0; } article.rtl details:before { - right: 18px; - left: 0; + right: 18px; + left: 0; } article details + details { - margin-top: -12px; + margin-top: -12px; } article details > details:last-child { - margin-bottom: -1px; + margin-bottom: -1px; } article summary { - padding: 10px 18px 10px 42px; - line-height: 25px; - min-height: 25px; + padding: 10px 18px 10px 42px; + line-height: 25px; + min-height: 25px; } article.rtl summary { - padding-left: 18px; - padding-right: 42px; + padding-left: 18px; + padding-right: 42px; } article summary:hover { - cursor: pointer; + cursor: pointer; } article summary:focus { - outline: none; + outline: none; } article summary::-webkit-details-marker { - display: none; + display: none; } article summary::marker { - content: ''; + content: ''; } article summary:before { - content: ''; - background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAICAYAAADN5B7xAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAH1JREFUeNqEjUEKgCAQRSfrNi1bdZFadJjsMC46SSAIHqjB5mcFqdFfhD3eUyKZtb6ln92O2janmXdvrRu+ZTfAgasu1jAHU4qiHAwc/Ff4oCQKsxxZ0NT33XrxUTjkWvgiXFf3TWkU6Vt+XihH515yFiQRpfLnEMUw3yHAABZNTT9emBrvAAAAAElFTkSuQmCC'); - transition: all .2s ease; - display: inline-block; - position: absolute; - width: 12px; - height: 8px; - left: 18px; - top: 18px; + content: ''; + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAICAYAAADN5B7xAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAH1JREFUeNqEjUEKgCAQRSfrNi1bdZFadJjsMC46SSAIHqjB5mcFqdFfhD3eUyKZtb6ln92O2janmXdvrRu+ZTfAgasu1jAHU4qiHAwc/Ff4oCQKsxxZ0NT33XrxUTjkWvgiXFf3TWkU6Vt+XihH515yFiQRpfLnEMUw3yHAABZNTT9emBrvAAAAAElFTkSuQmCC'); + transition: all .2s ease; + display: inline-block; + position: absolute; + width: 12px; + height: 8px; + left: 18px; + top: 18px; } article.rtl summary:before { - right: 18px; - left: auto; + right: 18px; + left: auto; } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { - article summary:before { - background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAQCAYAAAAMJL+VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPxJREFUeNq8lEESgiAUhgFbZ0epSW28gB2pZbrrSukBHDWto1TrwHih45AiaDOxesLP9w1PBlzXNfrLSNPqkGWV8ysHGMBqv4mAlyFC7MRPk+T51Z0Lh73AAJZgIoRFUR/bEMb4TggJPG9TTIUzxmIuWHWzOCLfQQgwRiedRMBpIsObFvn+NgSTLEE2bCiKm6eDQ0bAkS2v4AjYuPvJcqtEu9DDshaB665zFZzSV6yCfyr5JplLTOA9wZiEg/a+72Qic9nxubMOPijQSZraCK4UjEiezSVYmsBHBSrJAEIJ1wr0knG4kUAt0cONBX2JGXzGi1uG7SNmOt4CDADc4r+K4txg+wAAAABJRU5ErkJggg=='); - background-size: 12px 8px; - } + article summary:before { + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAQCAYAAAAMJL+VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPxJREFUeNq8lEESgiAUhgFbZ0epSW28gB2pZbrrSukBHDWto1TrwHih45AiaDOxesLP9w1PBlzXNfrLSNPqkGWV8ysHGMBqv4mAlyFC7MRPk+T51Z0Lh73AAJZgIoRFUR/bEMb4TggJPG9TTIUzxmIuWHWzOCLfQQgwRiedRMBpIsObFvn+NgSTLEE2bCiKm6eDQ0bAkS2v4AjYuPvJcqtEu9DDshaB665zFZzSV6yCfyr5JplLTOA9wZiEg/a+72Qic9nxubMOPijQSZraCK4UjEiezSVYmsBHBSrJAEIJ1wr0knG4kUAt0cONBX2JGXzGi1uG7SNmOt4CDADc4r+K4txg+wAAAABJRU5ErkJggg=='); + background-size: 12px 8px; + } } article details[open] > summary:before { - /*transform: rotateZ(-180deg);*/ - transform: scaleY(-1); + /*transform: rotateZ(-180deg);*/ + transform: scaleY(-1); } article li summary { - padding-left: 24px; + padding-left: 24px; } article li details:before, article li summary:before { - left: 0; + left: 0; } img, video, iframe { - max-width: 100%; - max-height: 400px; - vertical-align: top; + max-width: 100%; + max-height: 400px; + vertical-align: top; } video { - width: 100%; + width: 100%; } audio { - width: 100%; - width: calc(100% - 36px); - margin: 0 18px; - vertical-align: top; + width: 100%; + width: calc(100% - 36px); + margin: 0 18px; + vertical-align: top; } img { - font-size: 12px; - line-height: 14px; - color: #999; + font-size: 12px; + line-height: 14px; + color: var(--td-window-sub-text-fg); } img.pic { - max-height: none; - font-size: inherit; - vertical-align: middle; - position: relative; - top: -0.1em; + max-height: none; + font-size: inherit; + vertical-align: middle; + position: relative; + top: -0.1em; } img.pic.optional { - opacity: 0.4; + opacity: 0.4; } body:hover img.pic.optional { - opacity: 1; + opacity: 1; } iframe.autosize { - max-height: none; + max-height: none; } .iframe-wrap { - max-width: 100%; - vertical-align: top; - display: inline-block; - position: relative; + max-width: 100%; + vertical-align: top; + display: inline-block; + position: relative; } .iframe-wrap iframe { - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; } figure { - margin: 0 0 16px; - padding: 0; - text-align: center; - position: relative; + margin: 0 0 16px; + padding: 0; + text-align: center; + position: relative; } figure.nowide { - margin-left: 18px; - margin-right: 18px; + margin-left: 18px; + margin-right: 18px; } figure.nowide figcaption { - padding-left: 0; - padding-right: 0; + padding-left: 0; + padding-right: 0; } ul figure.nowide, ol figure.nowide { - margin: 0 0 12px; + margin: 0 0 12px; } figure > figure { - margin: 0; + margin: 0; } figcaption { - font-size: 15px; - color: #79828B; - padding: 6px 18px 0; - line-height: 19px; - text-align: left; + font-size: 15px; + color: var(--td-window-sub-text-fg); + padding: 6px 18px 0; + line-height: 19px; + text-align: left; } article.rtl figcaption { - text-align: right; + text-align: right; } ul figcaption, ol figcaption { - padding-left: 0; - padding-right: 0; + padding-left: 0; + padding-right: 0; } figcaption > cite { - font-family: 'Helvetica Neue'; - font-size: 12px; - display: block; - line-height: 15px; - padding: 2px 0 0; - font-style: normal; + font-family: 'Helvetica Neue'; + font-size: 12px; + display: block; + line-height: 15px; + padding: 2px 0 0; + font-style: normal; } footer { - margin: 12px 18px; - color: #79828B; + margin: 12px 18px; + color: var(--td-window-sub-text-fg); } figure.slideshow-wrap { - position: relative; + position: relative; } figure.slideshow { - position: relative; - white-space: nowrap; - width: 100%; - background: #000; - overflow: hidden; + position: relative; + white-space: nowrap; + width: 100%; + background: #000; + overflow: hidden; } figure.slideshow > figure { - position: static !important; - display: inline-block; - width: 100%; - vertical-align: middle; - transition: margin .3s; + position: static !important; + display: inline-block; + width: 100%; + vertical-align: middle; + transition: margin .3s; } figure.slideshow > figure figcaption { - box-sizing: border-box; - position: absolute; - bottom: 0; - width: 100%; - padding-bottom: 36px; + box-sizing: border-box; + position: absolute; + bottom: 0; + width: 100%; + padding-bottom: 36px; } figure.slideshow > figure figcaption:after { - content: ''; - display: block; - position: absolute; - left: 0; - right: 0; - bottom: 0; - top: -75px; - background: -moz-linear-gradient(top,rgba(64,64,64,0),rgba(64,64,64,.55)); - background: -webkit-gradient(linear,0 0,0 100%,from(rgba(64,64,64,0)),to(rgba(64,64,64,.55))); - background: -o-linear-gradient(rgba(64,64,64,0),rgba(64,64,64,.55)); - pointer-events: none; + content: ''; + display: block; + position: absolute; + left: 0; + right: 0; + bottom: 0; + top: -75px; + background: -moz-linear-gradient(top,rgba(64,64,64,0),rgba(64,64,64,.55)); + background: -webkit-gradient(linear,0 0,0 100%,from(rgba(64,64,64,0)),to(rgba(64,64,64,.55))); + background: -o-linear-gradient(rgba(64,64,64,0),rgba(64,64,64,.55)); + pointer-events: none; } figure.slideshow > figure figcaption > span, figure.slideshow > figure figcaption > cite { - position: relative; - color: #fff; - text-shadow: 0 1px rgba(0, 0, 0, .4); - z-index: 1; - display: block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + position: relative; + color: #fff; + text-shadow: 0 1px rgba(0, 0, 0, .4); + z-index: 1; + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } figure.slideshow > figure figcaption > span { - display: -webkit-box; - max-height: 3.8em; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; - white-space: pre-wrap; + display: -webkit-box; + max-height: 3.8em; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + white-space: pre-wrap; } figure.slideshow > figure figcaption code { - text-shadow: none; - background: rgba(204, 204, 204, .7); - color: #fff; + text-shadow: none; + background: rgba(204, 204, 204, .7); + color: #fff; } figure.slideshow > figure figcaption mark { - text-shadow: none; - background: rgba(33, 123, 134, .7); - color: #fff; + text-shadow: none; + background: rgba(33, 123, 134, .7); + color: #fff; } figure.slideshow > figure figcaption a, figure.slideshow > figure figcaption a:hover { - color: #66baff; + color: #66baff; } .slideshow-buttons { - position: absolute; - width: 100%; - bottom: 10px; - white-space: nowrap; - overflow: hidden; - z-index: 3; + position: absolute; + width: 100%; + bottom: 10px; + white-space: nowrap; + overflow: hidden; + z-index: 3; } .slideshow-buttons > fieldset { - padding: 0 10px 20px; - margin: 0 0 -20px; - border: none; - line-height: 0; - overflow: hidden; - overflow-x: auto; - min-width: auto; + padding: 0 10px 20px; + margin: 0 0 -20px; + border: none; + line-height: 0; + overflow: hidden; + overflow-x: auto; + min-width: auto; } .slideshow-buttons label { - display: inline-block; - padding: 7px; - cursor: pointer; + display: inline-block; + padding: 7px; + cursor: pointer; } .slideshow-buttons input { - position: absolute; - left: -10000px; + position: absolute; + left: -10000px; } .slideshow-buttons label i { - display: inline-block; - background: #fff; - box-shadow: 0 0 3px rgba(0, 0, 0, .4); - border-radius: 3.5px; - width: 7px; - height: 7px; - opacity: .6; - transition: opacity .3s; + display: inline-block; + background: #fff; + box-shadow: 0 0 3px rgba(0, 0, 0, .4); + border-radius: 3.5px; + width: 7px; + height: 7px; + opacity: .6; + transition: opacity .3s; } .slideshow-buttons input:checked ~ i { - opacity: 1; + opacity: 1; } figure.collage { - margin: -2px 16px; - text-align: left; + margin: -2px 16px; + text-align: left; } figure.collage > figure { - display: inline-block; - vertical-align: top; - width: calc(25% - 4px); - margin: 2px; - box-sizing: border-box; + display: inline-block; + vertical-align: top; + width: calc(25% - 4px); + margin: 2px; + box-sizing: border-box; } figure.collage > figure > i { - background: no-repeat center; - background-size: cover; - display: inline-block; - vertical-align: top; - width: 100%; - padding-top: 100%; + background: no-repeat center; + background-size: cover; + display: inline-block; + vertical-align: top; + width: 100%; + padding-top: 100%; } figure.table-wrap { - overflow: auto; - -webkit-overflow-scrolling: touch; + overflow: auto; + -webkit-overflow-scrolling: touch; } figure.table { - display: table-cell; - padding: 0 18px; + display: table-cell; + padding: 0 18px; } article ol figure.table-wrap, article ul figure.table-wrap { - margin-top: 7px; + margin-top: 7px; } article ol figure.table, article ul figure.table { - padding: 0; + padding: 0; } figure blockquote.embed-post { - text-align: left; - margin-bottom: 0; + text-align: left; + margin-bottom: 0; } article.rtl figure blockquote.embed-post { - text-align: right; + text-align: right; } blockquote.embed-post address { - margin: 0; - padding: 5px 0 9px; - overflow: hidden; + margin: 0; + padding: 5px 0 9px; + overflow: hidden; } blockquote.embed-post address figure { - width: 50px; - height: 50px; - float: left; - margin: 0 12px 0 0; - background: no-repeat center; - background-size: cover; - border-radius: 50%; + width: 50px; + height: 50px; + float: left; + margin: 0 12px 0 0; + background: no-repeat center; + background-size: cover; + border-radius: 50%; } article.rtl blockquote.embed-post address figure { - float: right; - margin-left: 12px; - margin-right: 0; + float: right; + margin-left: 12px; + margin-right: 0; } blockquote.embed-post address a { - display: inline-block; - padding-top: 2px; - font-size: 17px; - font-weight: 600; - color: #000; + display: inline-block; + padding-top: 2px; + font-size: 17px; + font-weight: 600; + color: var(--td-window-fg); } blockquote.embed-post address time { - display: block; - line-height: 19px; + display: block; + line-height: 19px; } blockquote.embed-post p, blockquote.embed-post blockquote { - margin: 0 0 7px; - clear: left; + margin: 0 0 7px; + clear: left; } blockquote.embed-post figcaption { - padding-left: 0; - padding-right: 0; + padding-left: 0; + padding-right: 0; } blockquote.embed-post figure.collage { - margin-left: -2px; - margin-right: -2px; + margin-left: -2px; + margin-right: -2px; } blockquote.embed-post footer { - margin: 12px 0 0; - font-style: normal; + margin: 12px 0 0; + font-style: normal; } blockquote.embed-post footer hr { - display: none; + display: none; } section.embed-post { - display: block; - width: auto; - height: auto; - background: #f7f7f7; - margin: 0 18px 12px; - padding: 24px 18px; - text-align: center; + display: block; + width: auto; + height: auto; + background: var(--td-box-divider-bg); + margin: 0 18px 12px; + padding: 24px 18px; + text-align: center; } section.embed-post strong { - font-size: 21px; - font-weight: normal; - display: block; - color: #777; + font-size: 21px; + font-weight: normal; + display: block; + color: var(--td-window-sub-text-fg); } section.embed-post small { - display: block; - color: #777; + display: block; + color: var(--td-window-sub-text-fg); } section.related { - margin: 7px 0 12px; + margin: 7px 0 12px; } section.related h4 { - font-family: 'Helvetica Neue'; - font-size: 17px; - line-height: 26px; - font-weight: 500; - display: block; - padding: 7px 18px; - background: #f7f7f7; - margin: 0; - color: #000; + font-family: 'Helvetica Neue'; + font-size: 17px; + line-height: 26px; + font-weight: 500; + display: block; + padding: 7px 18px; + background: var(--td-box-divider-bg); + margin: 0; + color: var(--td-window-fg); } section.related a.related-link { - display: block; - padding: 15px 18px 16px; - background: #fff; - position: relative; - overflow: hidden; + display: block; + padding: 15px 18px 16px; + background: var(--td-window-bg); + position: relative; + overflow: hidden; } section.related a.related-link:after { - content: ''; - display: block; - border-bottom: 1px solid #c8c7cb; - position: absolute; - left: 18px; - right: 0; - bottom: 0; + content: ''; + display: block; + border-bottom: 1px solid var(--td-box-divider-fg); + position: absolute; + left: 18px; + right: 0; + bottom: 0; } section.related .related-link-url { - display: block; - font-size: 15px; - line-height: 18px; - padding: 7px 0; - color: #999; - word-break: break-word; + display: block; + font-size: 15px; + line-height: 18px; + padding: 7px 0; + color: var(--td-window-sub-text-fg); + word-break: break-word; } section.related .related-link-thumb { - display: inline-block; - float: right; - width: 87px; - height: 87px; - border-radius: 4px; - background: no-repeat center; - background-size: cover; - margin-left: 15px; + display: inline-block; + float: right; + width: 87px; + height: 87px; + border-radius: 4px; + background: no-repeat center; + background-size: cover; + margin-left: 15px; } section.related .related-link-content { - display: block; - margin: -3px 0; + display: block; + margin: -3px 0; } section.related .related-link-title { - font-size: 15px; - font-weight: 500; - line-height: 18px; - display: block; - display: -webkit-box; - margin-bottom: 4px; - max-height: 36px; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - text-overflow: ellipsis; - white-space: pre-wrap; - color: #000; + font-size: 15px; + font-weight: 500; + line-height: 18px; + display: block; + display: -webkit-box; + margin-bottom: 4px; + max-height: 36px; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; + white-space: pre-wrap; + color: var(--td-window-fg); } section.related .related-link-desc { - font-size: 14px; - line-height: 17px; - display: block; - display: -webkit-box; - max-height: 51px; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; - overflow: hidden; - text-overflow: ellipsis; - white-space: pre-wrap; - color: #000; + font-size: 14px; + line-height: 17px; + display: block; + display: -webkit-box; + max-height: 51px; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; + white-space: pre-wrap; + color: var(--td-window-fg); } section.related .related-link-source { - font-size: 13px; - line-height: 17px; - display: block; - overflow: hidden; - margin-top: 4px; - text-overflow: ellipsis; - white-space: nowrap; - color: #818181; + font-size: 13px; + line-height: 17px; + display: block; + overflow: hidden; + margin-top: 4px; + text-overflow: ellipsis; + white-space: nowrap; + color: var(--td-window-sub-text-fg); } section.message { - position: absolute; - display: table; - width: 100%; - height: 100%; + position: absolute; + display: table; + width: 100%; + height: 100%; } section.message.static { - position: static; - min-height: 200px; - height: 100vh; + position: static; + min-height: 200px; + height: 100vh; } section.message > aside { - display: table-cell; - vertical-align: middle; - text-align: center; - color: #999; - font-size: 24px; - pointer-events: none; + display: table-cell; + vertical-align: middle; + text-align: center; + color: var(--td-window-sub-text-fg); + font-size: 24px; + pointer-events: none; } section.message > aside > cite { - display: block; - font-size: 14px; - padding: 10px 0 0; - font-style: normal; - color: #ccc; + display: block; + font-size: 14px; + padding: 10px 0 0; + font-style: normal; + color: var(--td-window-sub-text-fg); } section.channel { - margin-top: -16px; - margin-bottom: -9px; + margin-top: -16px; + margin-bottom: -9px; } section.channel:first-child { - margin-top: 0; + margin-top: 0; } section.channel > a { - display: block; - padding: 7px 18px; - background: #f7f7f7; + display: block; + padding: 7px 18px; + background: var(--td-box-divider-bg); } section.channel > a:before { - content: 'Join'; - color: #3196e8; - font-weight: 500; - margin-left: 7px; - float: right; + content: var(--td-lng-group-call-join); + color: var(--td-window-active-text-fg); + font-weight: 500; + margin-left: 7px; + float: right; } section.channel > a > h4 { - font-family: 'Helvetica Neue'; - font-size: 17px; - line-height: 26px; - font-weight: 500; - margin: 0; - color: #000; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + font-family: 'Helvetica Neue'; + font-size: 17px; + line-height: 26px; + font-weight: 500; + margin: 0; + color: var(--td-window-fg); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .iv-pullquote { - text-align: center; - max-width: 420px; - font-size: 19px; - display: block; - margin: 0 auto; + text-align: center; + max-width: 420px; + font-size: 19px; + display: block; + margin: 0 auto; } .iv-photo-wrap { - width: 100%; - background-size: 100%; - margin: 0 auto; + width: 100%; + background-size: 100%; + margin: 0 auto; } .iv-photo { - background-size: 100%; + background-size: 100%; } diff --git a/Telegram/Resources/iv_html/page.js b/Telegram/Resources/iv_html/page.js index 8486e2cc7..b81a556b1 100644 --- a/Telegram/Resources/iv_html/page.js +++ b/Telegram/Resources/iv_html/page.js @@ -49,15 +49,13 @@ var IV = { }); } }, - postMessageHandler: function(event) { - if (event.source !== window.parent || - event.origin != window.parentOrigin) { - return; - } - try { - var data = JSON.parse(event.data); - } catch(e) { - var data = {}; + updateStyles: function (styles) { + if (IV.styles !== styles) { + console.log('Setting', styles); + IV.styles = styles; + document.getElementsByTagName('html')[0].style = styles; + } else { + console.log('Skipping', styles); } }, slideshowSlide: function(el, next) { diff --git a/Telegram/SourceFiles/iv/iv_controller.cpp b/Telegram/SourceFiles/iv/iv_controller.cpp index 709461eaa..b2e6e0582 100644 --- a/Telegram/SourceFiles/iv/iv_controller.cpp +++ b/Telegram/SourceFiles/iv/iv_controller.cpp @@ -8,13 +8,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "iv/iv_controller.h" #include "base/platform/base_platform_info.h" +#include "base/invoke_queued.h" #include "iv/iv_data.h" +#include "lang/lang_keys.h" #include "ui/widgets/rp_window.h" #include "webview/webview_data_stream_memory.h" #include "webview/webview_embed.h" #include "webview/webview_interface.h" #include "styles/palette.h" +#include "base/call_delayed.h" +#include "ui/effects/animations.h" + #include #include #include @@ -23,8 +28,99 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include namespace Iv { +namespace { -Controller::Controller() = default; +[[nodiscard]] QByteArray ComputeStyles() { + static const auto map = base::flat_map{ + { "scroll-bg", &st::scrollBg }, + { "scroll-bg-over", &st::scrollBgOver }, + { "scroll-bar-bg", &st::scrollBarBg }, + { "scroll-bar-bg-over", &st::scrollBarBgOver }, + { "window-bg", &st::windowBg }, + { "window-bg-over", &st::windowBgOver }, + { "window-bg-ripple", &st::windowBgRipple }, + { "window-fg", &st::windowFg }, + { "window-sub-text-fg", &st::windowSubTextFg }, + { "window-active-text-fg", &st::windowActiveTextFg }, + { "window-bg-active", &st::windowBgActive }, + { "box-divider-bg", &st::boxDividerBg }, + { "box-divider-fg", &st::boxDividerFg }, + }; + static const auto phrases = base::flat_map>{ + { "group-call-join", tr::lng_group_call_join }, + }; + static const auto serialize = [](const style::color *color) { + const auto qt = (*color)->c; + if (qt.alpha() == 255) { + return '#' + + QByteArray::number(qt.red(), 16).right(2) + + QByteArray::number(qt.green(), 16).right(2) + + QByteArray::number(qt.blue(), 16).right(2); + } + return "rgba(" + + QByteArray::number(qt.red()) + "," + + QByteArray::number(qt.green()) + "," + + QByteArray::number(qt.blue()) + "," + + QByteArray::number(qt.alpha() / 255.) + ")"; + }; + static const auto escape = [](tr::phrase<> phrase) { + const auto text = phrase(tr::now); + + auto result = QByteArray(); + for (auto i = 0; i != text.size(); ++i) { + uint ucs4 = text[i].unicode(); + if (QChar::isHighSurrogate(ucs4) && i + 1 != text.size()) { + ushort low = text[i + 1].unicode(); + if (QChar::isLowSurrogate(low)) { + ucs4 = QChar::surrogateToUcs4(ucs4, low); + ++i; + } + } + if (ucs4 == '\'' || ucs4 == '\"' || ucs4 == '\\') { + result.append('\\').append(char(ucs4)); + } else if (ucs4 < 32 || ucs4 > 127) { + result.append('\\' + QByteArray::number(ucs4, 16) + ' '); + } else { + result.append(char(ucs4)); + } + } + return result; + }; + auto result = QByteArray(); + for (const auto &[name, phrase] : phrases) { + result += "--td-lng-" + name + ":'" + escape(phrase) + "'; "; + } + for (const auto &[name, color] : map) { + result += "--td-" + name + ':' + serialize(color) + ';'; + } + return result; +} + +[[nodiscard]] QByteArray EscapeForAttribute(QByteArray value) { + return value + .replace('&', "&") + .replace('"', """) + .replace('\'', "'") + .replace('<', "<") + .replace('>', ">"); +} + +[[nodiscard]] QByteArray EscapeForScriptString(QByteArray value) { + return value + .replace('\\', "\\\\") + .replace('"', "\\\"") + .replace('\'', "\\\'"); +} + +} // namespace +Controller::Controller() +: _updateStyles([=] { + const auto str = EscapeForScriptString(ComputeStyles()); + if (_webview) { + _webview->eval("IV.updateStyles(\"" + str + "\");"); + } +}) { +} Controller::~Controller() { _webview = nullptr; @@ -32,21 +128,66 @@ Controller::~Controller() { } void Controller::show(const QString &dataPath, Prepared page) { + createWindow(); + InvokeQueued(_container, [=, page = std::move(page)]() mutable { + showInWindow(dataPath, std::move(page)); + }); +} + +void Controller::createWindow() { _window = std::make_unique(); const auto window = _window.get(); window->setGeometry({ 200, 200, 600, 800 }); - const auto container = Ui::CreateChild( - window->body().get()); - window->sizeValue() | rpl::start_with_next([=](QSize size) { - container->setGeometry(QRect(QPoint(), size)); - }, container->lifetime()); - container->show(); + const auto skip = window->lifetime().make_state>(0); + _container = Ui::CreateChild(window->body().get()); + rpl::combine( + window->body()->sizeValue(), + skip->value() + ) | rpl::start_with_next([=](QSize size, int skip) { + _container->setGeometry(QRect(QPoint(), size).marginsRemoved({ 0, skip, 0, 0 })); + }, _container->lifetime()); + + base::call_delayed(5000, window, [=] { + const auto animation = window->lifetime().make_state(); + animation->start([=] { + *skip = animation->value(64); + if (!animation->animating()) { + base::call_delayed(4000, window, [=] { + animation->start([=] { + *skip = animation->value(0); + }, 64, 0, 200, anim::easeOutCirc); + }); + } + }, 0, 64, 200, anim::easeOutCirc); + }); + + window->body()->paintRequest() | rpl::start_with_next([=](QRect clip) { + auto p = QPainter(window->body()); + p.fillRect(clip, st::windowBg); + p.fillRect(clip, QColor(0, 128, 0, 128)); + }, window->body()->lifetime()); + + _container->paintRequest() | rpl::start_with_next([=](QRect clip) { + QPainter(_container).fillRect(clip, st::windowBg); + }, _container->lifetime()); + + _container->show(); + window->show(); +} + +void Controller::showInWindow(const QString &dataPath, Prepared page) { + Expects(_container != nullptr); + + const auto window = _window.get(); _webview = std::make_unique( - container, - Webview::WindowConfig{ .userDataPath = dataPath }); + _container, + Webview::WindowConfig{ + .opaqueBg = st::windowBg->c, + .userDataPath = dataPath, + }); const auto raw = _webview.get(); window->lifetime().add([=] { @@ -69,14 +210,10 @@ void Controller::show(const QString &dataPath, Prepared page) { }, window->lifetime()); raw->widget()->show(); - container->geometryValue( - ) | rpl::start_with_next([=](QRect geometry) { - raw->widget()->setGeometry(geometry); - }, container->lifetime()); - - container->paintRequest() | rpl::start_with_next([=](QRect clip) { - QPainter(container).fillRect(clip, st::windowBg); - }, container->lifetime()); + _container->sizeValue( + ) | rpl::start_with_next([=](QSize size) { + raw->widget()->setGeometry(QRect(QPoint(), size)); + }, _container->lifetime()); raw->setNavigationStartHandler([=](const QString &uri, bool newWindow) { return true; @@ -113,12 +250,27 @@ void Controller::show(const QString &dataPath, Prepared page) { .stream = std::make_unique( std::move(data), std::move(mime)), - }); + }); return Webview::DataResult::Done; }; const auto id = std::string_view(request.id).substr(3); if (id == "page.html") { - return finishWith(page.html, "text/html"); + const auto i = page.html.indexOf("= 0); + const auto colored = page.html.mid(0, i + 5) + + " style=\"" + EscapeForAttribute(ComputeStyles()) + "\"" + + page.html.mid(i + 5); + if (!_subscribedToColors) { + _subscribedToColors = true; + + rpl::merge( + Lang::Updated(), + style::PaletteChanged() + ) | rpl::start_with_next([=] { + _updateStyles.call(); + }, _webview->lifetime()); + } + return finishWith(colored, "text/html"); } const auto css = id.ends_with(".css"); const auto js = !css && id.ends_with(".js"); @@ -140,8 +292,6 @@ void Controller::show(const QString &dataPath, Prepared page) { raw->init(R"( )"); raw->navigateToData("iv/page.html"); - - window->show(); } bool Controller::active() const { diff --git a/Telegram/SourceFiles/iv/iv_controller.h b/Telegram/SourceFiles/iv/iv_controller.h index 7e623f7ce..5a081ca32 100644 --- a/Telegram/SourceFiles/iv/iv_controller.h +++ b/Telegram/SourceFiles/iv/iv_controller.h @@ -7,12 +7,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "base/invoke_queued.h" + namespace Webview { struct DataRequest; class Window; } // namespace Webview namespace Ui { +class RpWidget; class RpWindow; } // namespace Ui @@ -45,14 +48,21 @@ public: [[nodiscard]] rpl::lifetime &lifetime(); private: + void createWindow(); + void showInWindow(const QString &dataPath, Prepared page); + void escape(); void close(); void quit(); std::unique_ptr _window; + Ui::RpWidget *_container = nullptr; std::unique_ptr _webview; rpl::event_stream _dataRequests; rpl::event_stream _events; + SingleQueuedInvokation _updateStyles; + bool _subscribedToColors = false; + rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/iv/iv_prepare.cpp b/Telegram/SourceFiles/iv/iv_prepare.cpp index 69a86689c..dc93510c7 100644 --- a/Telegram/SourceFiles/iv/iv_prepare.cpp +++ b/Telegram/SourceFiles/iv/iv_prepare.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "iv/iv_data.h" #include "lang/lang_keys.h" #include "ui/image/image_prepare.h" +#include "styles/palette.h" #include @@ -1009,8 +1010,14 @@ QByteArray Parser::prepare(QByteArray body) { } QByteArray Parser::html(const QByteArray &head, const QByteArray &body) { +#ifdef Q_OS_MAC + const auto classAttribute = ""_q; +#else // Q_OS_MAC + const auto classAttribute = " class=\"custom_scroll\""_q; +#endif // Q_OS_MAC + return R"( - +