Last active
July 20, 2020 14:36
-
-
Save bdalenoord/a33346a1d7fcc500bf6312cabbecc78f to your computer and use it in GitHub Desktop.
Combined stylesheets and javascript for Simplify GMail so it can be used in RAMBOX
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function applyCss(css){ | |
var head = document.getElementsByTagName("head")[0]; | |
var s = document.createElement("style"); | |
s.setAttribute("type", "text/css"); | |
s.appendChild(document.createTextNode(css)); | |
head.appendChild(s); | |
} | |
// https://raw.githubusercontent.com/leggett/simplify/master/gmail/style.css | |
applyCss(` | |
/* ==================================================================== | |
* SIMPLIFY GMAIL v1.7.17 | |
* By Michael Leggett: leggett.org | |
* Copyright (c) 2020 Michael Hart Leggett | |
* Repo: github.com/leggett/simplify/blob/master/gmail/ | |
* License: github.com/leggett/simplify/blob/master/gmail/LICENSE.md | |
* More info: simpl.fyi | |
*/ | |
/* ==================================================================== | |
* BUNDLE ITEMS IN INBOX | |
html.simpl div[gh='tl'] tr[labels*='Promotions'] ~ tr[labels*='Promotions'], | |
html.simpl div[gh='tl'] tr[labels*='Social'] ~ tr[labels*='Social'], | |
html.simpl div[gh='tl'] tr[labels*='Updates'] ~ tr[labels*='Updates'], | |
html.simpl div[gh='tl'] tr[labels*='Forums'] ~ tr[labels*='Forums'] { | |
display: none; | |
} | |
*/ | |
/* ==================================================================== | |
* KEEP CHAT ROSTER MINIMIZED AFTER RELOAD | |
*/ | |
html.simpl.chatClosed .aeN div[role="complementary"] { | |
height: 0px !important; | |
} | |
html.simpl.chatClosed .aeN div[gh="ns"] { | |
display: none !important; | |
} | |
html.simpl.chatClosed .aeN div[role="navigation"] { | |
height: calc(100vh - 95px) !important; | |
} | |
/* ==================================================================== | |
* SHRINK FOOTPRINT OF MEET SECTION IN NAV TO ONE LINE | |
*/ | |
/* Hide "New" badge */ | |
html.simpl | |
.aeN | |
div[role="complementary"] | |
> div[role="navigation"] | |
> div:first-child | |
> span { | |
display: none; | |
} | |
/* Shrink width of title to make room for icons */ | |
html.simpl | |
.aeN | |
div[role="complementary"] | |
> div[role="navigation"] | |
> div:first-child { | |
float: left; | |
width: 122px; | |
} | |
/* Shrink two actions to icons and put them inline with the title */ | |
html.simpl | |
.aeN | |
div[role="complementary"] | |
> div[role="navigation"] | |
> div:nth-child(2) { | |
display: block; | |
position: absolute; | |
right: 12px; | |
} | |
html.simpl | |
.aeN | |
div[role="complementary"] | |
> div[role="navigation"] | |
> div:nth-child(2) | |
.aim { | |
width: 40px; | |
float: left; | |
} | |
html.simpl | |
.aeN | |
div[role="complementary"] | |
> div[role="navigation"] | |
> div:nth-child(2) | |
.aim | |
.TN { | |
padding: 0 10px; | |
} | |
html.simpl | |
.aeN | |
div[role="complementary"] | |
> div[role="navigation"] | |
> div:nth-child(2) | |
.aim | |
.TO { | |
border-radius: 16px; | |
} | |
/* Change action label to something shown on hover */ | |
html.simpl | |
.aeN | |
div[role="complementary"] | |
> div[role="navigation"] | |
> div:nth-child(2) | |
.aim | |
.aio { | |
display: none; | |
} | |
html.simpl | |
.aeN | |
div[role="complementary"] | |
> div[role="navigation"] | |
> div:nth-child(2) | |
.aim:hover | |
.aio { | |
display: block !important; | |
position: absolute; | |
top: 0px; | |
left: -150px; | |
width: fit-content; | |
max-width: 130px; | |
border-radius: 4px; | |
padding: 5px 12px 7px 12px; | |
background-color: white; | |
} | |
html.simpl | |
.aeN | |
div[role="complementary"] | |
> div[role="navigation"] | |
> div:nth-child(2) | |
.aim:nth-child(2):hover | |
.aio { | |
left: -190px; | |
} | |
html.simpl | |
.aeN | |
div[role="complementary"] | |
> div[role="navigation"] | |
> div:nth-child(2) | |
.aim:hover | |
.aio | |
a { | |
color: #202124; | |
text-shadow: none; | |
white-space: nowrap; | |
} | |
/* Move start call buttons when chat is minimized */ | |
html.simpl | |
.aeN | |
div[role="complementary"][style*="height: 0px"] | |
> div[role="navigation"] | |
> div:nth-child(2) { | |
z-index: 999; | |
right: 48px; | |
} | |
html.simpl | |
.aeN | |
div[role="complementary"][style*="height: 0px"] | |
> div[role="navigation"] | |
> div:nth-child(2) | |
.aim:hover | |
.aio { | |
display: none !important; | |
} | |
/* ==================================================================== | |
* INBOX DATE GROUPING | |
*/ | |
html.simpl tr[date="today"], | |
html.simpl tr[date="yesterday"], | |
html.simpl tr[date="month0"], | |
html.simpl tr[date="month1"], | |
html.simpl tr[date="month2"], | |
html.simpl tr[date="earlier"] { | |
margin-top: 3em; | |
} | |
html.simpl tr[date="today"] ~ tr[date="today"], | |
html.simpl tr[date="yesterday"] ~ tr[date="yesterday"], | |
html.simpl tr[date="month0"] ~ tr[date="month0"], | |
html.simpl tr[date="month1"] ~ tr[date="month1"], | |
html.simpl tr[date="month2"] ~ tr[date="month2"], | |
html.simpl tr[date="earlier"] ~ tr[date="earlier"] { | |
margin-top: initial; | |
} | |
html.simpl tr[date="today"]::before, | |
html.simpl tr[date="yesterday"]::before, | |
html.simpl tr[date="month0"]::before, | |
html.simpl tr[date="month1"]::before, | |
html.simpl tr[date="month2"]::before, | |
html.simpl tr[date="earlier"]::before { | |
height: 0px; | |
width: 0px; | |
white-space: nowrap; | |
overflow: visible; | |
font-size: 0.7em; | |
letter-spacing: 1.2; | |
color: #aaa; | |
font-weight: bold; | |
display: block; | |
position: relative; | |
top: -32px; | |
left: 16px; | |
} | |
html.simpl.mediumTheme tr[date="today"]::before, | |
html.simpl.mediumTheme tr[date="yesterday"]::before, | |
html.simpl.mediumTheme tr[date="month0"]::before, | |
html.simpl.mediumTheme tr[date="month1"]::before, | |
html.simpl.mediumTheme tr[date="month2"]::before, | |
html.simpl.mediumTheme tr[date="earlier"]::before, | |
html.simpl.darkTheme tr[date="today"]::before, | |
html.simpl.darkTheme tr[date="yesterday"]::before, | |
html.simpl.darkTheme tr[date="month0"]::before, | |
html.simpl.darkTheme tr[date="month1"]::before, | |
html.simpl.darkTheme tr[date="month2"]::before, | |
html.simpl.darkTheme tr[date="earlier"]::before { | |
color: #ffffff; | |
} | |
html.simpl tr[date="today"]::before { | |
content: "TODAY"; | |
} | |
html.simpl tr[date="yesterday"]::before { | |
content: "YESTERDAY"; | |
} | |
html.simpl tr[date="month0"]::before { | |
content: "THIS MONTH"; | |
} | |
html.simpl tr[date="month1"]::before { | |
content: "LAST MONTH"; | |
} | |
html.simpl tr[date="earlier"]::before { | |
content: "EARLIER"; | |
} | |
html.simpl tr[date="today"] ~ tr[date="today"]::before, | |
html.simpl tr[date="yesterday"] ~ tr[date="yesterday"]::before, | |
html.simpl tr[date="month0"] ~ tr[date="month0"]::before, | |
html.simpl tr[date="month1"] ~ tr[date="month1"]::before, | |
html.simpl tr[date="month2"] ~ tr[date="month2"]::before, | |
html.simpl tr[date="earlier"] ~ tr[date="earlier"]::before { | |
content: ""; | |
display: none; | |
} | |
/* ==================================================================== | |
* GLOBAL / APP-LEVEL | |
*/ | |
/* Hide footer | |
html.simpl.multiBoxHorz .pfiaof, | |
html.simpl.multiBoxVert .pfiaof, | |
html.simpl .ae4 + .pfiaof, | |
*/ | |
html.simpl .aeG, | |
html.simpl .pfiaof, | |
html.simpl.readingPane .apc, | |
html.simpl.readingPane .apO { | |
display: none; | |
} | |
/* Move and restyle banners (vacation auto-responder, account delegation) */ | |
html.simpl .w-MH, | |
html.simpl .ZY, | |
html.simpl .w-asV .aG, | |
html.simpl .bir { | |
position: fixed; | |
width: auto; | |
max-width: 300px; | |
text-align: left; | |
padding: 18px 24px; | |
bottom: 24px; | |
left: 24px; | |
font-size: 0.875rem; | |
font-weight: bold; | |
border: none; | |
box-shadow: 0 1px 3px 0 rgba(60, 64, 67, 0.302), | |
0 4px 8px 3px rgba(60, 64, 67, 0.149); | |
border-radius: 2px; | |
/* Override the black on yellow default theme */ | |
color: #fff; | |
background-color: #202124; | |
} | |
html.simpl .w-MH .e, | |
html.simpl .ZY .e, | |
html.simpl .w-asV .aG a, | |
html.simpl .bir a { | |
margin-left: 16px; | |
color: #8ab4f8; | |
} | |
/* ==================================================================== | |
* APP BAR (menu and account switcher + container for search) | |
*/ | |
/* Hide Gmail logo and name */ | |
html.simpl #gb a[href="#inbox"] { | |
display: none !important; | |
} | |
/* Hide App Switcher */ | |
html.simpl #gbwa { | |
display: none !important; | |
position: absolute; | |
right: 0px; | |
padding: 12px 66px 14px 12px; | |
margin: -8px -12px 0 0; | |
} | |
html.simpl.appSwitcher #gbwa { | |
display: block !important; | |
} | |
html.simpl.appSwitcher.quickSettings #gb .FI, | |
html.simpl.appSwitcher.quickSettings #gb div[data-tooltip="Settings"] { | |
display: none; | |
} | |
/* Remove padding around profile photo so settings is better spaced */ | |
/* UNSTABLE */ | |
html.simpl .gb_Da { | |
padding-left: 2px !important; | |
} | |
/* Clean up the butter bar (loading, etc) */ | |
html.simpl .vX .vh { | |
border: none; | |
border-radius: 0 0 4px 4px; | |
padding: 8px 16px; | |
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); | |
} | |
/* Reduce width of app bar when Addons are open */ | |
html.simpl.addOnsOpen header#gb { | |
width: calc(100vw - 300px); | |
} | |
/* Hide Support button */ | |
html.simpl #gb .zo, | |
html.simpl #gb img[src*="help_outline"] { | |
display: none; | |
} | |
/* ==================================================================== | |
* ACTION BAR (actions, pagination, and settings) | |
*/ | |
/* Move action bar on top of app bar and to right of menu button */ | |
html.simpl .aeH { | |
position: absolute !important; | |
top: 0px !important; | |
left: 60px !important; | |
width: calc(var(--action-bar-width) - 300px); | |
/* Reduce z-index from 986 so action bar can live on top of it */ | |
z-index: 6; | |
} | |
html.simpl .aeH .G-atb { | |
height: 64px; | |
} | |
/* Remove extra right margin from action bar so it is spaced correctly */ | |
html.simpl .aeH .G-atb[gh="tm"] { | |
margin-right: 0px !important; | |
top: 0px; | |
} | |
/* Hide extra drop shadow on action bar - it bleeds through on the filter pop-up */ | |
html.simpl .aeH .G-atb::before { | |
box-shadow: none; | |
-webkit-box-shadow: none; | |
} | |
/* Make bar wider when search is hidden */ | |
html.simpl { | |
--quickSettingsGap: 0px; | |
} | |
html.simpl.quickSettings { | |
--quickSettingsGap: 42px; | |
} | |
html.simpl.hideSearch .aeH { | |
width: calc(100vw - 172px - var(--quickSettingsGap)); | |
} | |
html.simpl.hideSearch.addOnsOpen .aeH { | |
width: calc(100vw - 172px - 300px - var(--quickSettingsGap)); | |
} | |
/* Dim pagination controls unless hovered over | |
html.simpl .aeH .G-atb .aqJ, | |
html.simpl .aeF .G-atb .aqJ, | |
html.simpl .aeH .G-atb .adF { | |
opacity: 0.5; | |
transition: opacity 0.2s ease-in 0s; | |
} | |
html.simpl .aeH .G-atb .aqJ:hover, | |
html.simpl .aeF .G-atb .aqJ:hover, | |
html.simpl .aeH .G-atb .adF:hover { | |
opacity: 1; | |
} | |
*/ | |
/* Don't show pagination menu */ | |
html.simpl .aeH .G-atb .aqJ .amG, | |
html.simpl .aeF .G-atb .aqJ .amG, | |
html.simpl .aeH .G-atb .adF .amG { | |
display: none; | |
} | |
/* Below 1350px, hide pagination when search and addOns are both open */ | |
@media only screen and (max-width: 1370.98px) { | |
html.simpl.addOnsOpen:not(.hideSearch) .aeH .G-atb .aqJ > div:not([gh="s"]), | |
html.simpl.addOnsOpen:not(.hideSearch) .aeH .G-atb .adF > div:not([gh="s"]) { | |
display: none; | |
} | |
} | |
/* Below 1200px, hide pagination AND settings when search and addOns are both open */ | |
@media only screen and (max-width: 1200.98px) { | |
html.simpl.addOnsOpen:not(.hideSearch) .adF, | |
html.simpl.addOnsOpen:not(.hideSearch) .aqJ { | |
display: none; | |
} | |
} | |
/* Below 1100px wide, when search is expanded, hide pagination controls even if AddOns aren't open */ | |
@media only screen and (max-width: 1100.98px) { | |
html.simpl:not(.hideSearch) .aeH .G-atb .aqJ > div:not([gh="s"]), | |
html.simpl:not(.hideSearch) .aeH .G-atb .adF > div:not([gh="s"]) { | |
display: none; | |
} | |
} | |
/* Below 850px wide, when search is expanded, pagination AND settings */ | |
@media only screen and (max-width: 850.98px) { | |
html.simpl:not(.hideSearch) .aeH .G-atb .aqJ, | |
html.simpl:not(.hideSearch) .aeH .G-atb .adF { | |
display: none; | |
} | |
} | |
/* Remove drop shadow from action bar */ | |
html.simpl .aeI .G-atb { | |
box-shadow: none; | |
-webkit-box-shadow: none; | |
} | |
/* Move action bar for Horizontal Multiple Inboxes */ | |
html.simpl.multiBoxHorz .aeF .G-atb[gh="tm"] { | |
position: fixed; | |
top: 8px; | |
left: 60px; | |
z-index: 6 !important; | |
width: calc(var(--action-bar-width) - 128px); | |
transition: width 0s ease-in 0s; /* was 0.15s - Looks bad with 3rd party extensions */ | |
} | |
html.simpl.multiBoxHorz .aeF .G-atb[gh="tm"]::before { | |
box-shadow: none; | |
-webkit-box-shadow: none; | |
} | |
html.simpl.multiBoxHorz.hideSearch:not(.addOnsOpen) .aeF .G-atb[gh="tm"] { | |
width: calc(100vw - 206px) !important; | |
} | |
html.simpl.multiBoxHorz.hideSearch.addOnsOpen .aeF .G-atb[gh="tm"] { | |
width: calc(var(--action-bar-width) - 152px); | |
} | |
html.simpl.multiBoxHorz.addOnsOpen:not(.hideSearch) .aeF .G-atb[gh="tm"] { | |
width: calc(var(--action-bar-width) - 370px); | |
} | |
/* Further adjustments for side-by-side multiple inboxes */ | |
html.simpl.multiBoxHorz div[role="main"] .byR { | |
margin-top: 0px; | |
} | |
@media only screen and (max-width: 1441.98px) { | |
html.simpl.multiBoxHorz .aeF > div.nH { | |
max-width: 1400px !important; | |
} | |
/* Keep the max-width of the conversation narrow -- fragile due to use of .BltHke */ | |
/* TODO: I should do this at all resolutions for horizontal split view */ | |
html.simpl.multiBoxHorz .aeF > div.nH > div.nH:last-child:not(.BltHke) { | |
max-width: 960px !important; | |
margin: 0 auto; | |
} | |
} | |
@media only screen and (min-width: 1441.98px) { | |
/* Allow the side-by-side multiBox to be a lot wider... */ | |
html.simpl.multiBoxHorz .aeF > div.nH { | |
max-width: 2200px !important; | |
} | |
/* ... while keeping the max-width of the conversation narrow */ | |
html.simpl.multiBoxHorz .aeF > div.nH > div.nH[role="main"]:not(.BltHke) { | |
max-width: 1100px !important; | |
margin: 0 auto; | |
} | |
} | |
/* Nudge the offline button closer to the settings gear */ | |
html.simpl .aqJ .bvX, | |
html.simpl .adF .bvX { | |
margin-right: 16px !important; | |
} | |
/* Hide the Offline icon */ | |
html.simpl .bvE { | |
display: none; | |
} | |
/* ==================================================================== | |
* ALIGN ACTION BAR WITH CONTENT | |
*/ | |
/* | |
Resolutions | |
Low (< 960px) | |
Mid (961 - 1440) | |
High (> 1441) | |
Views | |
Default inbox w/ tabs | |
Search (including label) | |
Priority inbox | |
Preview pane vertical | |
Preview pane horizontal | |
Multiple inboxes vertical | |
Multiple inboxes horizontal | |
States (icon buttons) | |
Menu closed | |
Menu closed, Right side chat | |
Menu closed, Right side chat, Search open | |
Menu closed, Add-ons open | |
Menu closed, Add-ons open, Search open | |
Menu open | |
Menu open, Right side chat | |
Menu open, Right side chat, Search open | |
Menu open, Add-ons open | |
Menu open, Add-ons open, Search open | |
States (text button labels) | |
Menu closed | |
Menu closed, Right side chat | |
Menu closed, Right side chat, Search open | |
Menu closed, Add-ons open | |
Menu closed, Add-ons open, Search open | |
Menu open | |
Menu open, Right side chat | |
Menu open, Right side chat, Search open | |
Menu open, Add-ons open | |
Menu open, Add-ons open, Search open | |
*/ | |
@media only screen and (max-width: 1278.97px) { | |
html.simpl { | |
--content-width: 100%; | |
} | |
} | |
@media only screen and (min-width: 1278.98px) { | |
/* DETAULT VIEWS: Move actions to left edge of content */ | |
html.simpl { | |
--content-width: 960px; | |
--left-offset: 60px; | |
} | |
html.simpl.quickSettings { | |
--left-offset: 60px; /* was 88px */ | |
} | |
html.simpl.navOpen { | |
--left-offset: -32px; | |
} | |
html.simpl.navOpen.quickSettings { | |
--left-offset: -32px; /* was -4px */ | |
} | |
html.simpl.readingPane.navOpen:not(.noSplitPane) { | |
--left-offset: -1px; | |
} | |
html.simpl.rhsChat.navOpen { | |
--left-offset: 68px; | |
--content-width: 1164px; | |
} | |
html.simpl.rhsChat:not(.navOpen) { | |
--left-offset: 160px; | |
} | |
html.simpl.addOnsOpen, | |
html.simpl.addOnsOpen.rhsChat { | |
--left-offset: 210px; | |
--content-width: 1260px; | |
} | |
html.simpl.addOnsOpen.rhsChat { | |
--left-offset: 12px; | |
} | |
html.simpl.addOnsOpen.navOpen { | |
--left-offset: 118px; | |
} | |
html.simpl.addOnsOpen.rhsChat.navOpen { | |
--left-offset: -82px; | |
} | |
/* No Split Reading pane */ | |
html.simpl.noSplitPane { | |
--left-offset: 64px; | |
} | |
html.simpl.noSplitPane.navOpen { | |
--left-offset: -60px; | |
} | |
html.simpl.noSplitPane.addOnsOpen { | |
--content-width: 960px; | |
--left-offset: 212px; | |
} | |
html.simpl.noSplitPane.navOpen.addOnsOpen { | |
--left-offset: 90px; | |
} | |
/* Apply variables to align left edge except if the menu and addOns or rhsChat are both open */ | |
html.simpl:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert):not(.addOnsOpen):not(.rhsChat):not(.textButtons) | |
.aeH | |
.G-atb, | |
html.simpl:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert):not(.navOpen):not(.textButtons) | |
.aeH | |
.G-atb, | |
html.simpl.noSplitPane:not(.multiBoxHorz):not(.multiBoxVert):not(.textButtons) /* :not(.multiBoxVert2):not(.readingPane) */ | |
.aeF | |
.G-atb, | |
html.simpl.noSplitPane:not(.multiBoxHorz):not(.multiBoxVert):not(.textButtons) /* :not(.multiBoxVert2):not(.readingPane) */ | |
.aeH | |
.G-atb { | |
padding-left: calc( | |
((100vw - var(--content-width)) / 2) - var(--left-offset) | |
); | |
margin-left: 16px !important; /* 44px */ | |
} | |
/* | |
html.simpl.multiBoxVert2 .G-atb[gh="tm"] { | |
padding-left: calc( | |
((100vw - var(--content-width)) / 2) - var(--left-offset) | |
); | |
margin-left: 18px !important; | |
} | |
html.simpl.readingPane.noSplitPane .G-atb { | |
padding-left: calc( | |
((100vw - var(--content-width)) / 2) - var(--left-offset) | |
); | |
margin-left: 16px !important; | |
} | |
*/ | |
/* Adjust width of action bar for reading pane */ | |
html.simpl.readingPane.hideSearch:not(.navOpen) .G-atb[gh="tm"] { | |
width: calc(100vw - 234px); | |
} | |
html.simpl.readingPane:not(.hideSearch):not(.navOpen) .G-atb[gh="tm"] { | |
width: calc(var(--action-bar-width) - 126px); | |
} | |
html.simpl.readingPane.navOpen.hideSearch .G-atb[gh="tm"] { | |
width: calc(100vw - 430px); | |
} | |
html.simpl.readingPane.navOpen:not(.hideSearch) .G-atb[gh="tm"] { | |
width: calc(var(--action-bar-width) - 126px); | |
} | |
/* Correct width of action bar for No Split reading pane */ | |
html.simpl.noSplitPane.hideSearch:not(.navOpen) .G-atb[gh="tm"] { | |
width: calc(var(--content-width) / 2 + 50vw - 170px); | |
} | |
html.simpl.noSplitPane.hideSearch.navOpen .G-atb[gh="tm"] { | |
width: calc(var(--content-width) / 2 + 50vw - 294px); | |
} | |
html.simpl.noSplitPane:not(.navOpen):not(.hideSearch) .G-atb[gh="tm"] { | |
width: calc(var(--content-width) / 2 + 50vw - 152px - 16%); | |
} | |
html.simpl.noSplitPane.navOpen:not(.hideSearch) .G-atb[gh="tm"] { | |
width: calc(var(--content-width) / 2 + 50vw - 276px - 16%); | |
} | |
html.simpl.noSplitPane.addOnsOpen:not(.hideSearch) .G-atb[gh="tm"] { | |
width: calc(var(--content-width) / 2 + 50vw - 253px - 16%); | |
} | |
html.simpl.noSplitPane.hideSearch.addOnsOpen:not(.navOpen) .G-atb[gh="tm"] { | |
width: calc(var(--content-width) / 2 + 50vw - 324px); | |
} | |
html.simpl.noSplitPane.hideSearch.addOnsOpen.navOpen .G-atb[gh="tm"] { | |
width: calc(var(--content-width) / 2 + 50vw - 446px); | |
} | |
html.simpl.noSplitPane.addOnsOpen.navOpen:not(.hideSearch) .G-atb[gh="tm"] { | |
width: calc(var(--content-width) / 2 + 50vw - 375px - 16%); | |
} | |
/* Move pagination controls to right edge of content | |
* while leaving settings to far right */ | |
html.simpl.hideSearch { | |
--right-offset: 158px; | |
} | |
html.simpl.hideSearch.navOpen { | |
--right-offset: 252px; | |
} | |
html.simpl.hideSearch.addOnsOpen { | |
--right-offset: 310px; | |
} | |
html.simpl.hideSearch.rhsChat { | |
--right-offset: 58px; | |
} | |
html.simpl.hideSearch.rhsChat.navOpen { | |
--right-offset: 150px; | |
} | |
html.simpl.hideSearch.addOnsOpen.rhsChat { | |
--right-offset: 208px; | |
} | |
html.simpl.hideSearch.navOpen.addOnsOpen { | |
--right-offset: 400px; | |
} | |
html.simpl.hideSearch.navOpen.addOnsOpen.rhsChat { | |
--right-offset: 300px; | |
} | |
/* No Split reading pane */ | |
html.simpl.hideSearch.noSplitPane { | |
--right-offset: 218px; | |
} | |
html.simpl.hideSearch.noSplitPane.navOpen { | |
--right-offset: 340px; | |
} | |
html.simpl.hideSearch.noSplitPane.addOnsOpen { | |
--right-offset: 368px; | |
} | |
html.simpl.hideSearch.noSplitPane.addOnsOpen.navOpen { | |
--right-offset: 490px; | |
} | |
/* Quick Settings Alt */ | |
html.simpl.hideSearch { | |
--right-offset: 132px; | |
} | |
html.simpl.hideSearch.navOpen.quickSettings { | |
--right-offset: 220px; | |
} | |
html.simpl.hideSearch.addOnsOpen.quickSettings { | |
--right-offset: 278px; | |
} | |
html.simpl.hideSearch.rhsChat.quickSettings { | |
--right-offset: 26px; | |
} | |
html.simpl.hideSearch.rhsChat.navOpen.quickSettings { | |
--right-offset: 118px; | |
} | |
html.simpl.hideSearch.addOnsOpen.rhsChat.quickSettings { | |
--right-offset: 176px; | |
} | |
html.simpl.hideSearch.navOpen.addOnsOpen.quickSettings { | |
--right-offset: 368px; | |
} | |
html.simpl.hideSearch.navOpen.addOnsOpen.rhsChat.quickSettings { | |
--right-offset: 268px; | |
} | |
html.simpl.hideSearch.noSplitPane.quickSettings { | |
--right-offset: 186px; | |
} | |
html.simpl.hideSearch.noSplitPane.navOpen.quickSettings { | |
--right-offset: 308px; | |
} | |
html.simpl.hideSearch.noSplitPane.addOnsOpen.quickSettings { | |
--right-offset: 336px; | |
} | |
html.simpl.hideSearch.noSplitPane.addOnsOpen.navOpen.quickSettings { | |
--right-offset: 458px; | |
} | |
/* Apply variables to align right edge with content */ | |
html.simpl.hideSearch:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert):not(.addOnsOpen):not(.rhsChat):not(.textButtons) | |
.aeH | |
.ar5, | |
html.simpl.hideSearch:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert):not(.addOnsOpen):not(.rhsChat):not(.textButtons) | |
.adF | |
.iG, | |
html.simpl.hideSearch:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert):not(.navOpen):not(.textButtons) | |
.aeH | |
.ar5, | |
html.simpl.hideSearch:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert):not(.navOpen):not(.textButtons) | |
.adF | |
.iG, | |
html.simpl.hideSearch.noSplitPane:not(.multiBoxHorz):not(.multiBoxVert):not(.textButtons) | |
.aeF | |
.ar5 { | |
padding-right: calc( | |
((100vw - var(--content-width)) / 2) - var(--right-offset) | |
); | |
} | |
/* There is no split pane button in conversation view -- add more padding */ | |
html.simpl.hideSearch.noSplitPane:not(.multiBoxHorz):not(.multiBoxVert):not(.textButtons) | |
.adF | |
.iG { | |
padding-right: calc( | |
((100vw - var(--content-width)) / 2) - var(--right-offset) + 60px | |
); | |
} | |
/* Keep pagination next to settings when search is open */ | |
html.simpl:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert):not(.addOnsOpen):not(.rhsChat):not(.textButtons) | |
.aeH | |
.ar5, | |
html.simpl:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert):not(.addOnsOpen):not(.rhsChat):not(.textButtons) | |
.adF | |
.iG, | |
html.simpl:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert):not(.navOpen):not(.textButtons) | |
.aeH | |
.ar5, | |
html.simpl:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert):not(.navOpen):not(.textButtons) | |
.adF | |
.iG, | |
html.simpl.noSplitPane:not(.hideSearch):not(.multiBoxHorz):not(.multiBoxVert):not(.textButtons) | |
.aeF | |
.ar5, | |
html.simpl.noSplitPane:not(.hideSearch):not(.multiBoxHorz):not(.multiBoxVert):not(.textButtons) | |
.adF | |
.iG { | |
padding-right: initial; | |
} | |
} | |
@media only screen and (min-width: 1278.98px) and (max-width: 1638.98px) { | |
/* Don't align the actions if the nav and add-ons are both open */ | |
html.simpl.noSplitPane.navOpen.addOnsOpen .aeF .G-atb[gh="tm"], | |
html.simpl.noSplitPane.navOpen.addOnsOpen .aeH .G-atb[gh="tm"] { | |
padding-left: initial; | |
width: calc(100vw - 445px - 16%); | |
} | |
} | |
/* Adjust aligment and spacing for higher resolutions */ | |
@media only screen and (min-width: 1441.98px) { | |
html.simpl { | |
--content-width: 1100px !important; | |
} | |
html.simpl.rhsChat { | |
--content-width: 1304px; | |
} | |
html.simpl.addOnsOpen, | |
html.simpl.addOnsOpen.rhsChat { | |
--content-width: 1400px; | |
} | |
/* Reading pane: Apply variables to align left edge for vertical reading pane when the nav is open */ | |
html.simpl.navOpen.readingPane:not(.hideSearch):not(.noSplitPane):not(.multiBoxHorz):not(.multiBoxVert):not(.textButtons):not(.rhsChat):not(.addOnsOpen) | |
.aeF | |
.G-atb { | |
padding-left: 196px !important; | |
margin-left: 16px !important; | |
width: calc(var(--action-bar-width) - 322px) !important; | |
} | |
html.simpl.navOpen.readingPane.hideSearch:not(.noSplitPane):not(.multiBoxHorz):not(.multiBoxVert):not(.textButtons):not(.rhsChat):not(.addOnsOpen) | |
.adF | |
.G-atb { | |
padding-left: 196px !important; | |
margin-left: 16px !important; | |
width: calc(var(--action-bar-width) - 49px) !important; | |
} | |
} | |
@media only screen and (min-width: 1638.98px) { | |
/* Apply variables to align left edge */ | |
html.simpl.navOpen.addOnsOpen:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert) { | |
--left-offset: 94px; | |
} | |
html.simpl:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert) | |
.aeH | |
.G-atb, | |
html.simpl.noSplitPane:not(.multiBoxHorz):not(.multiBoxVert) | |
.aeF | |
.G-atb[gh="tm"] { | |
padding-left: calc( | |
((100vw - var(--content-width)) / 2) - var(--left-offset) | |
); | |
margin-left: 16px !important; | |
} | |
/* Apply variables to align right edge with content */ | |
html.simpl.hideSearch:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert) | |
.aeH | |
.ar5, | |
html.simpl.hideSearch:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert) | |
.adF | |
.iG { | |
padding-right: calc( | |
((100vw - var(--content-width)) / 2) - var(--right-offset) | |
); | |
} | |
/* Keep pagination next to settings when search is open */ | |
html.simpl:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert) .aeH .ar5, | |
html.simpl:not(.readingPane):not(.multiBoxHorz):not(.multiBoxVert) .adF .iG { | |
padding-right: initial; | |
} | |
} | |
/* ==================================================================== | |
* SEARCH | |
*/ | |
/* Push search to the right */ | |
html.simpl #gb form { | |
float: right; | |
width: 350px; | |
max-width: none; | |
margin-right: 8px; | |
position: relative; | |
right: 0px; | |
transition: width 0s; | |
} | |
html.simpl.quickSettings #gb form { | |
width: 16%; | |
} | |
html.simpl { | |
--action-bar-width: 79%; | |
} | |
/* Make search wider and hide pagination/settings when search is focused */ | |
html.simpl.searchFocused #gb form { | |
width: 40%; | |
} | |
html.simpl.searchFocused { | |
--action-bar-width: 59%; | |
} | |
/* Hack fix b/c I'm not using --action-bar-width in all cases */ | |
html.simpl.searchFocused.readingPane .aeF .G-atb, | |
html.simpl.searchFocused.textButtons .aeH .G-atb { | |
width: 40% !important; | |
overflow: hidden; | |
} | |
html.simpl.searchFocused .aeH .G-atb .aqJ, | |
html.simpl.searchFocused .aeF .G-atb .aqJ, | |
html.simpl.searchFocused .aeH .G-atb .adF { | |
display: none; | |
} | |
/* Shorter search box when using text label buttons | |
html.simpl.textButtons #gb form { | |
width: 25%; | |
} | |
html.simpl.textButtons { | |
--action-bar-width: 74.5%; | |
} | |
*/ | |
/* Shorter search box when nav is open on smaller screens | |
@media only screen and (max-width: 1441.98px) { | |
html.simpl.navOpen #gb form { | |
width: 25%; | |
} | |
html.simpl.navOpen { | |
--action-bar-width: 74.5%; | |
} | |
} | |
*/ | |
/* Minimize search to an icon when hidden */ | |
html.simpl.hideSearch #gb form { | |
width: 54px; | |
margin-right: 0px; | |
box-shadow: none; | |
background-color: transparent; | |
} | |
/* Hide all search form buttons except search button when search is hidden */ | |
html.simpl.hideSearch #gb form button { | |
display: none; | |
} | |
html.simpl.hideSearch #gb form button[role="button"]:not([gh="sda"]) { | |
display: block; | |
} | |
/* Move filter form to be under search box */ | |
html.simpl .ZF-Av { | |
left: auto !important; | |
right: 71px !important; | |
width: calc(100% - var(--action-bar-width) + 1%) !important; | |
min-width: 450px; | |
} | |
html.simpl .ZF-Av > div { | |
border: 0px; | |
} | |
/* Hide or shrink search when app switcher is shown */ | |
html.simpl.appSwitcher.hideSearch #gb form { | |
display: none; | |
} | |
html.simpl.appSwitcher:not(.hideSearch) #gb form { | |
width: calc(100% - var(--action-bar-width) - 1% - 50px); | |
margin-right: 58px; | |
} | |
/* Hide search options button until you hover over search box | |
html.simpl:not(.hideSearch) #gb form button[gh="sda"] { | |
display: none; | |
} | |
html.simpl:not(.hideSearch) #gb form:hover button[gh="sda"] { | |
display: block; | |
} | |
*/ | |
/* Hide "Search the web" option from search auto-complete */ | |
html.simpl #gb form td.gssb_e tr[role="separator"], | |
html.simpl #gb form td.gssb_e tr[role="option"]:last-child { | |
display: none; | |
} | |
/* ==================================================================== | |
* SEARCH REFINEMENT BAR | |
*/ | |
/* Move search refinement bar below action bar */ | |
html.simpl .aeH div[gh="tm"] div[role="toolbar"] { | |
position: absolute; | |
top: 44px; | |
} | |
/* Reading pane */ | |
html.simpl.readingPane .G-atb[gh="tm"] > div.G6 { | |
position: absolute; | |
top: 60px; | |
height: 54px; | |
margin-bottom: 14px; | |
overflow-y: hidden; | |
overflow-x: auto; | |
} | |
html.simpl.readingPane .G-atb[gh="tm"] > div[role="toolbar"] > div:first-child { | |
overflow-y: hidden; | |
overflow-x: inherit; | |
height: 54px; | |
margin-right: 0px; | |
} | |
/* No Split Pane only */ | |
html.simpl.noSplitPane .G-atb[gh="tm"] > div.G6, | |
html.simpl.noSplitPane .G-atb[gh="tm"] > div[role="toolbar"] { | |
width: calc(var(--content-width) - 16px); | |
max-width: calc(var(--content-width) - 16px); | |
} | |
/* Reading pane only */ | |
html.simpl.readingPane:not(.noSplitPane) .G-atb[gh="tm"] > div.G6 { | |
left: -32px; | |
width: var(--readingPane-width); | |
} | |
/* BUG: The search refinement bar is pos:absolute making it a higher | |
* z-index than the search auto-complete that is pos:relative. | |
* FIX: (More of a temporary hack): Hide the search refinement bar | |
* when search is focused because | |
*/ | |
html.simpl.searchFocused .G-atb[gh="tm"] > div.G6, | |
html.simpl.searchFocused .G-atb[gh="tm"] > div[role="toolbar"] { | |
display: none; | |
} | |
/* Add expand button to show all the search chips | |
* TODO: setup event listener for .G6 and see if e.target = .G6 | |
* if so, toggle width of search chips bar | |
html.simpl.readingPane:not(.noSplitPane) .G-atb[gh='tm'] > div.G6 { | |
pointer-events: none; | |
} | |
html.simpl.readingPane .G-atb[gh='tm'] > div[role='toolbar'] > div:first-child { | |
pointer-events: auto; | |
} | |
html.simpl.readingPane:not(.noSplitPane) .G-atb[gh='tm'] > div.G6::before { | |
content: '»'; | |
width: 30px; | |
height: 30px; | |
background: white; | |
display: block; | |
position: absolute; | |
right: 30px; | |
top: 0px; | |
z-index: 1; | |
border-radius: 16px; | |
box-shadow: 0 1px 1px #aaa; | |
line-height: 1.2; | |
text-align: center; | |
font-size: 24px; | |
font-family: Arial, sans-serif; | |
color: #4185f4; | |
border: 1px solid #eee; | |
letter-spacing: -2px; | |
pointer-events: auto; | |
cursor: pointer; | |
} | |
*/ | |
/* Move search refinement bar over when nav and add-ons are open */ | |
/* TODO: set left to be dynamic when nav is closed below 1278px so it stays with the content */ | |
@media only screen and (max-width: 960.98px) { | |
html.simpl div[gh="tm"] div[role="toolbar"] { | |
left: -36px; | |
} | |
} | |
@media only screen and (max-width: 1278.98px) { | |
html.simpl.navOpen div[gh="tm"] div[role="toolbar"] { | |
left: 205px; | |
} | |
} | |
@media only screen and (max-width: 1638.98px) { | |
html.simpl.navOpen.readingPane:not(.noSplitPane) | |
div[gh="tm"] | |
div[role="toolbar"], | |
html.simpl.navOpen.readingPane:not(.noSplitPane) div[gh="tm"] div.G6 { | |
left: 205px; | |
max-width: calc(100vw - 266px); | |
} | |
html.simpl.navOpen.addOnsOpen div[gh="tm"] div[role="toolbar"], | |
html.simpl.navOpen.addOnsOpen div[gh="tm"] div.G6 { | |
left: 205px; | |
max-width: calc(100vw - 566px); | |
} | |
html.simpl.navOpen.addOnsOpen.noSplitPane | |
div.G-atb[gh="tm"] | |
div[role="toolbar"], | |
html.simpl.navOpen.addOnsOpen.noSplitPane div.G-atb[gh="tm"] div.G6 { | |
left: 185px; | |
max-width: calc(100vw - 566px); | |
} | |
} | |
@media only screen and (min-width: 1638.98px) { | |
html.simpl.navOpen.readingPane:not(.noSplitPane) div[gh="tm"] div.G6 { | |
left: 205px; | |
} | |
} | |
/* Hide search refinement bar when you scroll */ | |
/* .aeI is added to a parent Div when you are scrolled to the top */ | |
/* but not for Reading Pane = Vertical|Horizontal */ | |
html.simpl .aeI .aeH div.G-atb[gh="tm"] div[role="toolbar"], | |
html.simpl .aeI .aeF div.G-atb[gh="tm"] div[role="toolbar"] { | |
display: none; | |
} | |
/* Move action bar into correct spot */ | |
/* Maybe add .inSearch for not reading pane? */ | |
html.simpl .aeH div[gh="tm"] div[role="toolbar"] + .aqK { | |
margin-top: 22px; | |
} | |
/* Reading pane */ | |
html.simpl.readingPane.inSearch .G-atb[gh="tm"] > div.G6 ~ div.aqK, | |
html.simpl.readingPane.inSearch | |
.G-atb[gh="tm"] | |
> div[role="toolbar"] | |
~ div.aqK { | |
margin-top: 14px; | |
} | |
/* Create more space above the results for the search chips in Reading pane */ | |
/* TODO not sure if .PY only is added when the search chips are present or if it is a stable classname */ | |
html.simpl.noSplitPane.inSearch .aeF .G-atb.PY ~ .UI .ae4 { | |
padding-top: 20px; | |
} | |
html.simpl.readingPane.inSearch:not(.noSplitPane) .aeF .G-atb.PY ~ .UI .ae4 { | |
padding-top: 70px; | |
} | |
/* Make space for the Did you mean bar when it comes up */ | |
html.simpl.inSearch .Wz { | |
margin-top: 70px; | |
margin-bottom: -50px; | |
} | |
html.simpl.inSearch.noSplitPane .Wz { | |
margin-top: 70px; | |
margin-bottom: -50px; | |
max-width: var(--content-width); | |
margin-left: auto; | |
margin-right: auto; | |
} | |
html.simpl.inSearch.readingPane:not(.noSplitPane) .Wz { | |
max-width: var(--readingPane-width); | |
} | |
/* Keep the action bar from covering the left nav */ | |
html.simpl.readingPane.inSearch .G-atb[gh="tm"] { | |
height: 54px; | |
} | |
/* Shift message list down to make space for search chips */ | |
html.simpl.inSearch .aeF div[role="main"] > .bX, | |
html.simpl.inSearch .aeF div[role="main"] > .afn + .ae4 { | |
margin-top: 72px; | |
} | |
/* Hide Advanced search link */ | |
html.simpl | |
div.G-atb[gh="tm"] | |
div[role="toolbar"] | |
div[data-impression-suffix="ADVANCED_SEARCH_LINK"], | |
html.simpl | |
.aeH | |
div[gh="tm"] | |
div[role="toolbar"] | |
div:first-child | |
> div[role="button"]:last-child { | |
display: none; | |
} | |
/* ==================================================================== | |
* NAV & COMPOSE BUTTON | |
*/ | |
/* SHOW NAV ON HOVER */ | |
/* This is buggy b/c the animation is not instant and flipping between positions is */ | |
html.simpl .bhZ:not(.bym) div[role="navigation"] { | |
/* display: none; */ | |
} | |
html.simpl .bhZ.bym { | |
/* position: absolute; */ | |
} | |
/* Don't show the nav when hovering over the compose button | |
* TODO: fix this, probably by adding a class on hover of the compose button | |
*/ | |
html.simpl .bym { | |
box-shadow: none !important; | |
} | |
html.simpl .bhZ div[role="complementary"], | |
html.simpl .bhZ div[gh="ns"] { | |
display: none !important; | |
} | |
/* Hide nav when minimized or in Settings */ | |
html.simpl .bhZ, | |
html.simpl.inSettings .aeN { | |
position: relative; | |
z-index: 3 !important; | |
/* Remove this to show nav on hover */ | |
max-width: 0px !important; | |
min-width: 0px !important; | |
} | |
html.simpl.inSettings .aeN { | |
width: 0px !important; | |
overflow: hidden; | |
} | |
/* No shadow or label on compose button */ | |
html.simpl .z0 > .L3 { | |
box-shadow: 0 1px 2px 0 rgba(60, 64, 67, 0.3) !important; | |
border-radius: 28px; | |
font-size: 0; | |
height: 56px; | |
padding: 0; | |
width: 56px; | |
} | |
/* Make FAB dark in dark themes */ | |
html.simpl.darkTheme .z0 > .L3 { | |
background-color: rgba(51, 51, 51, 0.9); | |
} | |
/* Move compose button out of menu */ | |
html.simpl .z0 { | |
position: absolute; | |
left: calc(100vw - 92px); | |
top: calc(100vh - 140px); | |
z-index: 3 !important; | |
width: 54px; | |
margin: 0; | |
padding: 0; | |
} | |
/* Move it over futher if RHS Chat is enabled */ | |
html.simpl.rhsChat .z0 { | |
left: calc(100vw - 275px); | |
} | |
/* Add some padding above the nav that the compose button used to provide */ | |
html.simpl .wT { | |
padding-top: 20px; | |
} | |
/* Hide top shadow when you scroll long label list */ | |
html.simpl .aeN .ajj:before { | |
-webkit-box-shadow: none; | |
box-shadow: none; | |
} | |
/* Hide the compose and add-ons button when in Settings */ | |
html.simpl.inSettings .z0, | |
html.simpl.inSettings .bAw { | |
display: none; | |
} | |
/* Make the bottom Hangouts tabs a little less ugly */ | |
html.simpl div[gh="gt"] { | |
text-align: left; | |
border-top: 0px; | |
padding-left: 18px; | |
} | |
html.simpl.rhsChat div[gh="gt"] { | |
text-align: right; | |
border-top: 0px; | |
padding-left: 0px; | |
} | |
html.simpl.rhsChat .akj { | |
margin-top: 12px; | |
} | |
/* Remove extra right padding from rhsChat */ | |
html.simpl.rhsChat .aCl .akj { | |
padding-right: 0px !important; | |
} | |
/* Hide unread counts in nav if Simplify Setting enabled */ | |
html.simpl.hideUnreads .bsU { | |
display: none !important; | |
} | |
/* ==================================================================== | |
* INBOX | |
*/ | |
/* Bump up the line height a little in the inbox */ | |
html.simpl.lowDensityInbox:not(.readingPane) .zA { | |
padding-top: 12px !important; | |
padding-bottom: 12px !important; | |
} | |
html.simpl.highDensityInbox:not(.readingPane) .zA { | |
padding-top: 4px !important; | |
padding-bottom: 4px !important; | |
} | |
/* Right and bottom padding on inbox and messages */ | |
html.simpl .aeF { | |
padding-right: 56px !important; | |
margin-bottom: 150px; | |
} | |
/* Max width inbox and conversation and add top padding */ | |
html.simpl .AO .aeF > .nH { | |
margin: 40px auto 0 auto; | |
max-width: 960px; | |
} | |
html.simpl.readingPane.inSettings .AO .aeF > .nH { | |
margin: 40px auto 100px auto !important; | |
max-width: 960px !important; | |
} | |
@media only screen and (min-width: 1441.98px) { | |
html.simpl:not(.readingPane) .AO .aeF > .nH { | |
max-width: 1100px; | |
} | |
html.simpl.readingPane.inSettings .AO .aeF > .nH { | |
max-width: 1100px !important; | |
} | |
} | |
/* Less padding on inbox and messages for low resolutions */ | |
@media only screen and (max-width: 960.98px) { | |
html.simpl .bhZ + .bkK { | |
margin-left: 12px !important; | |
} | |
html.simpl .aeF { | |
padding-right: 12px !important; | |
margin-bottom: 50px; | |
} | |
html.simpl .AO .aeF > .nH { | |
margin-top: 12px !important; | |
} | |
} | |
/* Add extra padding between inbox groups */ | |
html.simpl div[gh="tl"] div[role="tabpanel"] { | |
padding-bottom: 1em; | |
} | |
/* TODO: Remove that extra padding if the section is hidden | |
* This doesn't work | |
html.simpl div[gh="tl"] div[role="tabpanel"] > div.afn { | |
margin-bottom: -2em; | |
} | |
*/ | |
/* Remove top border on TL */ | |
html.simpl:not(.readingPane) .aeF div[gh="tl"] { | |
border-top: 0px; | |
} | |
/* Add spacing between vertically stacked Multiple Inboxes */ | |
html.simpl.multiBoxVert .nH > .nK { | |
margin-top: 1em; | |
} | |
/* Hide toggle next to inbox groups */ | |
html.simpl div[gh="tl"] div[role="tabpanel"] h3 img { | |
display: none; | |
} | |
/* Different treatment of read items in inbox except highlighted items in splitpane view*/ | |
html.simpl.lightTheme .yO:not(.aps), | |
html.simpl.mediumTheme .yO:not(.aps) { | |
/* White with lighter text */ | |
background-color: rgba(255, 255, 255, 0.8); | |
color: #333; | |
} | |
/* Back to defaults for selected items */ | |
html.simpl.lightTheme .yO.x7, | |
html.simpl.mediumTheme .yO.x7 { | |
background-color: #c2dbff; | |
color: #202124; | |
} | |
/* Dim snippets for read messages a little more */ | |
html.simpl.lightTheme .yO .y2, | |
html.simpl.mediumTheme .yO .y2 { | |
opacity: 0.7; | |
} | |
/* Make sure minimized search icon is white for medium themes */ | |
html.simpl.mediumTheme.hideSearch #gb form button[role="button"] > svg, | |
html.simpl.mediumTheme.hideSearch #gb form button[role="button"] > svg > path { | |
color: rgba(255, 255, 255, 0.87); | |
} | |
/* Different background colors for dark themes */ | |
html.simpl.darkTheme .yO:not(.aps) { | |
background: rgba(0, 0, 0, 0.8); | |
color: rgba(255, 255, 255, 0.7); | |
} | |
html.simpl.darkTheme .yO.x7 { | |
color: rgba(255, 255, 255, 1); | |
background: #174ea6; | |
} | |
/* Dim the Snoozed N days ago text in the inbox */ | |
html.simpl .zA .cL { | |
font-weight: normal; | |
opacity: 0.8; | |
} | |
html.simpl .zA.yO .cL { | |
opacity: 0.4; | |
} | |
/* Less shadow on items on hover */ | |
html.simpl .zA:hover { | |
box-shadow: inset 1px 0 0 #dadce0, 0 1px 2px 0 rgba(60, 64, 67, 0.15) !important; | |
} | |
/* Dim Default Inbox category tabs */ | |
html.simpl .aKh { | |
opacity: 0.7; | |
transition: opacity 0.2s ease-in 0s; | |
border-radius: 8px 8px 0 0; | |
} | |
html.simpl .aKh:hover { | |
opacity: 1; | |
} | |
/* Further dim the non-active category tab */ | |
html.simpl .aKh .aAy[aria-selected="false"] { | |
opacity: 0.5; | |
transition: opacity 0.2s ease-in 0s; | |
} | |
html.simpl .aKh .aAy[aria-selected="false"]:hover, | |
html.simpl .aKh .aAy[aria-selected="true"] { | |
opacity: 1; | |
} | |
/* Make "new" badges on tabs grayscale */ | |
html.simpl .aKh .aDG { | |
filter: grayscale(100%); | |
} | |
/* Hide ads in top of inbox tabs */ | |
html.simpl div[gh="tl"] .aKB, /* old way */ | |
html.simpl div[gh="tl"] div[role="tabpanel"] > div.Cp:first-child, | |
html.simpl div[gh="tl"] .U9:first-child + .Cp + .Cp { | |
display: none; | |
} | |
/* Dim attachment type icons on read messages */ | |
html.simpl div[gh="tl"] tr.yO img.brf { | |
/* filter: grayscale(100%) brightness(135%); */ | |
opacity: 0.6; | |
} | |
/* Hide underlines on category tabs in default inbox */ | |
html.simpl div[role="main"] .J-KU-KO.aAy:before { | |
background-color: transparent !important; | |
} | |
/* ==================================================================== | |
* POPOUTS | |
*/ | |
/* Correct max-width */ | |
html.simpl.popout .aeF { | |
padding-right: 0px !important; | |
margin-bottom: 0px !important; | |
max-width: 960px; | |
} | |
html.simpl.popout .aeF > div { | |
box-shadow: none !important; | |
} | |
html.simpl.popout .G-atb[gh="tm"] { | |
max-width: 930px; | |
margin: 0 auto !important; | |
} | |
@media only screen and (min-width: 799.98px) { | |
html.simpl.popout .G-atb[gh="tm"] { | |
min-width: 730px; | |
} | |
} | |
@media only screen and (min-width: 1441.98px) { | |
html.simpl.popout .aeF { | |
max-width: 1100px; | |
} | |
html.simpl.popout .G-atb[gh="tm"] { | |
max-width: 1070px; | |
} | |
} | |
@media only screen and (min-width: 1679.98px) { | |
html.simpl.popout .aeF { | |
max-width: 100%; | |
} | |
html.simpl.popout .aeF > div { | |
max-width: 100% !important; | |
} | |
html.simpl.popout .aDc { | |
max-width: 100% !important; | |
} | |
html.simpl.popout .G-atb[gh="tm"] { | |
max-width: calc(100% - 30px); | |
} | |
} | |
/* Hide theme background */ | |
html.simpl.popout .wl, | |
html.simpl.popout .wl div, | |
html.simpl.popout .wq, | |
html.simpl.popout .wp { | |
background-image: none !important; | |
background-color: #fff !important; | |
} | |
/* ==================================================================== | |
* READING PANE VIEW | |
*/ | |
/* Move action bar over app bar */ | |
html.simpl.readingPane .G-atb[gh="tm"] { | |
position: fixed; | |
top: 5px; | |
left: 60px; | |
z-index: 7 !important; | |
padding-right: 0px !important; | |
height: 54px; | |
} | |
/* Different top pos for when search chips are enabled */ | |
html.simpl.readingPane.inSearch .PY.G-atb[gh="tm"] { | |
top: 8px; | |
} | |
html.simpl.readingPane .G-atb[gh="tm"]:before { | |
box-shadow: none; | |
-webkit-box-shadow: none; | |
} | |
@media only screen and (min-width: 1278.98px) { | |
html.simpl.readingPane.navOpen.hideSearch:not(.noSplitPane) .G-atb[gh="tm"] { | |
padding-left: 212px; | |
} | |
} | |
/* Add border under app bar, remove for threadlist */ | |
html.simpl.readingPane header#gb { | |
border-bottom: 1px solid rgba(100, 121, 143, 0.122); | |
} | |
html.simpl.readingPane .UJ { | |
border-top: none; | |
} | |
/* Adjust width of action bar for small resolutions */ | |
@media only screen and (max-width: 1278.98px) { | |
html.simpl.readingPane.hideSearch .G-atb[gh="tm"] { | |
width: calc(100vw - 234px); | |
} | |
html.simpl.readingPane:not(.hideSearch) .G-atb[gh="tm"] { | |
width: calc(var(--action-bar-width) - 126px); | |
} | |
html.simpl.readingPane.addOnsOpen.hideSearch .G-atb[gh="tm"] { | |
width: calc(100vw - 502px); | |
} | |
html.simpl.readingPane.addOnsOpen:not(.hideSearch) .G-atb[gh="tm"] { | |
width: calc(var(--action-bar-width) - 366px); | |
} | |
} | |
/* Reduce left margin on main view */ | |
html.simpl.readingPane .bhZ + .bkK { | |
margin-left: 12px !important; | |
} | |
/* Override padding around main view */ | |
html.simpl.readingPane .aeF { | |
padding-right: 0px !important; | |
margin-bottom: 0px !important; | |
} | |
/* Max width view 100% */ | |
html.simpl.readingPane .AO .aeF > .nH { | |
margin: 0px; /*40px auto 0 auto;*/ | |
max-width: 100%; | |
} | |
/* Max-width and margin on conversation */ | |
html.simpl.readingPane .apg .aNW .age .Bs { | |
max-width: 1050px; | |
} | |
html.simpl.readingPane .aNW td.Bu:first-child > div.nH:last-child { | |
padding-bottom: 200px; | |
} | |
@media only screen and (min-width: 1441.98px) { | |
html.simpl.readingPane .apg .aNW .age .Bs { | |
max-width: 1100px; | |
/* float conversation view | |
margin: 1.5vw auto 200px auto; | |
border-radius: 8px; | |
*/ | |
margin: 0 auto; | |
} | |
/* Swap margin for padding when message is likely to | |
* switch from pane to floating card */ | |
html.simpl.readingPane .aNW td.Bu:first-child > div.nH:last-child { | |
padding-bottom: 0px; | |
} | |
} | |
/* Add right margin to inbox tabs */ | |
html.simpl.readingPane .aeF .aKh { | |
margin-right: 16px; | |
} | |
/* No bottom border on app bar */ | |
html.simpl.readingPane .aiw { | |
box-shadow: none; | |
-webkit-box-shadow: none; | |
} | |
/* Drop the double border between panes to a single border */ | |
html.simpl.readingPane .apj { | |
border-right: none; | |
border-left: none; | |
background-color: transparent; | |
} | |
html.simpl.readingPane .aph { | |
border-bottom: none; | |
} | |
/* Below 1250px, hide the pagination controls */ | |
/* TODO: Shouldn't I do this for all setups, not just reading pane? */ | |
@media only screen and (max-width: 1278.98px) { | |
html.simpl.readingPane.addOnsOpen:not(.hideSearch) | |
.aE3 | |
.G-atb | |
.aqJ | |
> div:not([gh="s"]) { | |
display: none; | |
} | |
} | |
@media only screen and (max-width: 1100.98px) { | |
html.simpl.readingPane:not(.hideSearch) .aE3 .G-atb .aqJ > div:not([gh="s"]) { | |
display: none; | |
} | |
} | |
/* Move the right aligned actions on the inline reply over so the | |
* compose button doesn't cover them | |
* TODO: Find a more elegant solution to this problem | |
*/ | |
html.simpl.readingPane div[role="listitem"] .btC > .az5 { | |
padding-right: 50px; | |
} | |
/* Add a bit of right margin to the "Select all?" butter bar */ | |
html.simpl.readingPane .Tm .ya { | |
margin-right: 16px; | |
} | |
/* ==================================================================== | |
* NO SPLIT PREVIEW PANE | |
*/ | |
/* Center the inbox */ | |
html.simpl.noSplitPane div[gh="tl"] .ae4 { | |
max-width: var(--content-width); | |
margin: 0 auto; | |
} | |
@media only screen and (min-width: 1278.98px) { | |
/* Inbox tabs */ | |
html.simpl.noSplitPane .aeF .aKh { | |
max-width: var(--content-width); | |
margin: 0 auto; | |
position: relative; | |
left: -8px; | |
} | |
html.simpl.noSplitPane.navOpen.addOnsOpen .aeF .aKh { | |
max-width: calc(100vw - 573px); | |
} | |
html.simpl.noSplitPane .aeF .aKh > table.aKk { | |
min-width: var(--content-width); | |
} | |
} | |
/* Add padding below inbox */ | |
html.simpl.noSplitPane:not(.multiBoxVert2) .aeF .Nu { | |
padding-bottom: 150px; | |
} | |
html.simpl.noSplitPane.multiBoxVert2 .aeF .Nu { | |
padding-bottom: 40px; | |
} | |
/* Add padding above inbox if there are no tabs */ | |
html.simpl.noSplitPane .aeF .Nu { | |
padding-top: 35px; | |
} | |
/* More padding if there are search chips */ | |
html.simpl.noSplitPane .aeF .PY.G-atb ~ .UI > .Nu { | |
padding-top: 55px; | |
} | |
html.simpl.noSplitPane .aeF .aKh ~ .UI .Nu { | |
padding-top: initial; | |
} | |
/* Center the conversation */ | |
html.simpl.noSplitPane .aeF div[role="main"][class="nH"] { | |
max-width: var(--content-width); | |
margin: 40px auto 200px auto; | |
} | |
/* Correctly position toolbar in Conversation view | |
html.simpl.noSplitPane .aeH .G-atb[gh='tm'] { | |
top: 0px !important; | |
} | |
*/ | |
/* Center "Select all?" butter bar */ | |
html.simpl.readingPane.noSplitPane .Tm .ya { | |
max-width: var(--content-width); | |
margin: 4px auto; | |
position: relative; | |
left: -8px; | |
} | |
@media only screen and (max-width: 1278.98px) { | |
html.simpl.readingPane.noSplitPane .Tm .ya { | |
left: 0; | |
margin-right: 16px; | |
} | |
} | |
/* ==================================================================== | |
* CONVERSATION VIEW | |
*/ | |
/* Not sure why, but sometimes this div (the footer I believe) below the conversation gets 440px bottom padding */ | |
html.simpl .pfiaof { | |
padding-bottom: 0px !important; | |
} | |
/* Round corners of conversation for themes */ | |
html.simpl .bAn { | |
border-radius: 8px; | |
} | |
/* Dim print and pop-out icons in conversation view */ | |
html.simpl .bAn .ade { | |
opacity: 0.2; | |
transition: opacity 0.4s ease-in 0s; | |
} | |
html.simpl .bAn .ade:hover { | |
opacity: 1; | |
} | |
/* Make the right gutter inside the card the same as the left */ | |
html.simpl div[role="listitem"] .a3s { | |
padding-right: 48px; | |
} | |
/* Slightly larger message body text in conversation view and composer | |
* TODO: There are some bugs with this -- so I'm disabling for now until I can be sure it works 100%; | |
html.simpl div[contenteditable="true"], | |
html.simpl div[contenteditable="true"] font[size="2"] { | |
font-size: 0.874rem; | |
} | |
html.simpl div[role="listitem"] .a3s, | |
html.simpl div[role="listitem"] .a3s font[size="2"], | |
html.simpl div[role="listitem"] .g6, | |
html.simpl div[role="listitem"] div:not(.ajA) h3.iw { | |
font-size: 0.875rem; | |
} | |
*/ | |
/* Force it when the font size is set inline | |
html.simpl div[role="listitem"] .a3s [style*="font-size: small"], | |
html.simpl div[role="listitem"] .a3s [style*="font-size:small"] { | |
font-size: 0.875rem !important; | |
} | |
html.simpl div[role="listitem"] .a3s [style*="font-size: .875rem"], | |
html.simpl div[role="listitem"] .a3s [style*="font-size:.875rem"], | |
html.simpl div[role="listitem"] .a3s [style*="font-size: 0.875rem"], | |
html.simpl div[role="listitem"] .a3s [style*="font-size:0.875rem"] { | |
font-size: 1rem !important; | |
background-color: yellow; | |
} | |
html.simpl div[role="listitem"] .a3s [style*="font-size: .874rem"], | |
html.simpl div[role="listitem"] .a3s [style*="font-size:.874rem"], | |
html.simpl div[role="listitem"] .a3s [style*="font-size: 0.874rem"], | |
html.simpl div[role="listitem"] .a3s [style*="font-size:0.874rem"] { | |
font-size: 1rem !important; | |
background-color: red; | |
color: white; | |
} | |
*/ | |
/* In case the font size is set to 14px or .875rem, bump it up so it is noticably larger | |
html.simpl div[contenteditable="true"] [style*="font-size: 0.875rem"], | |
html.simpl div[contenteditable="true"] [style*="font-size:0.875rem"], | |
html.simpl div[contenteditable="true"] [style*="font-size: .875rem"], | |
html.simpl div[contenteditable="true"] [style*="font-size:.875rem"], | |
html.simpl div[contenteditable="true"] [style*="font-size: 14px"], | |
html.simpl div[contenteditable="true"] [style*="font-size:14px"], | |
html.simpl div[contenteditable="true"] [style*="font-size: small"], | |
html.simpl div[contenteditable="true"] [style*="font-size:small"] { | |
font-size: 1rem !important; | |
background: yellow; | |
} | |
html.simpl div[contenteditable="true"] [style*="font-size: 0.874rem"], | |
html.simpl div[contenteditable="true"] [style*="font-size:0.874rem"] { | |
font-size: 1rem !important; | |
background: red; | |
color: white; | |
} | |
*/ | |
/* Dim from email address in conversation view */ | |
html.simpl div[role="listitem"] h3.iw .go { | |
opacity: 0.5; | |
} | |
/* Clean up "New message from" banner */ | |
html.simpl .ata-asE { | |
right: auto; | |
left: 24px; | |
bottom: 24px; | |
font-size: 0.875rem; | |
color: #fff; | |
background-color: #202124; | |
padding: 18px; | |
border: none; | |
box-shadow: 0 1px 3px 0 rgba(60, 64, 67, 0.302), | |
0 4px 8px 3px rgba(60, 64, 67, 0.149); | |
} | |
html.simpl .ata-asE > span:first-child:not(.ata-asJ) { | |
padding-right: 12px; | |
} | |
html.simpl .ata-asE .ata-asJ { | |
color: #8ab4f8; | |
padding-left: 12px; | |
} | |
/* Keep inline images from being wider than the current view */ | |
html.simpl table.Bs .gs > div:not(.gE) img:not([src*="cleardot.gif"]) { | |
max-width: 100%; | |
/* Without this, large portrait images will be squished | |
* but with this, large images that are forced to be small | |
* but not given a height in css are made their actual big size */ | |
height: auto; | |
} | |
/* If the content is wider, the image will still scroll horizontally | |
* We can set the max-width the the max-width of the content but | |
* this sometimes has unintended consequences in html emails | |
html.simpl table.Bs .gs img { | |
max-width: calc(var(--content-width) - 80px); | |
height: auto; | |
} | |
html.simpl.readingPane table.Bs .gs img { | |
max-width: 100%; | |
} | |
*/ | |
/* Boost width of the cell that has the reply and more actions buttons */ | |
html.simpl | |
div[role="listitem"] | |
div:not([dir="ltr"]) | |
table | |
td:last-child[rowspan="2"] { | |
width: 110px; | |
} | |
/* ==================================================================== | |
* COMPOSER | |
*/ | |
/* A touch more padding above the from field and subject */ | |
html.simpl .dw form.bAs, | |
html.simpl .aSs .aSt .I5 > form.bAs { | |
padding-top: 6px; | |
} | |
/* Make full screen composer less wide */ | |
html.simpl .aSs > .aSt { | |
width: 900px !important; | |
left: calc(50vw - 450px) !important; | |
} | |
html.simpl .aSs .aDg > .aDj { | |
width: 865px !important; | |
left: calc(50vw - 435px) !important; | |
} | |
/* Make scrim behind full screen composer darker */ | |
html.simpl .aSs { | |
background-color: rgba(0, 0, 0, 0.7); | |
} | |
/* BUGS: moving stuff around here is causing problems */ | |
/* Move extended compose buttons inline | |
html.simpl .aSs .aDl > .Ur, | |
html.simpl .aSs .aDn > .aDl > .Ur, | |
html.simpl .aSs .aDi > .aDl > .Ur { | |
left: 205px !important; | |
bottom: -54px !important; | |
} | |
html.simpl .aSs .aZ > .J-Z { | |
box-shadow: none !important; | |
-webkit-box-shadow: none !important; | |
} | |
*/ | |
/* Hide useless buttons in full screen compose and move bar inline | |
html.simpl .aSs .aZ .J-Z-I[command^="+undo"], | |
html.simpl .aSs .aZ .J-Z-I[command^="+redo"], | |
html.simpl .aSs .aZ .J-Z-I[command^="+bold"], | |
html.simpl .aSs .aZ .J-Z-I[command^="+italic"], | |
html.simpl .aSs .aZ .J-Z-I[command^="+underline"], | |
html.simpl .aSs .btC .oc.gU, | |
html.simpl .aSs .a8X .wG[command^="docs"], | |
html.simpl .aSs .a8X .wG[command^="op.money"] { | |
display: none !important; | |
} | |
*/ | |
/* ==================================================================== | |
* ADD-ONS RIGHT SIDE PANE | |
*/ | |
/* Shrink the add-on chooser to a small FAB when not hovered on */ | |
html.simpl .bAw { | |
position: fixed; | |
right: 47px !important; | |
bottom: 100px !important; | |
height: 36px !important; | |
width: 36px !important; | |
min-width: 36px !important; | |
overflow-y: hidden; | |
overflow-x: hidden; | |
border-radius: 27px; | |
box-shadow: 0 1px 2px 0 rgba(60, 64, 67, 0.3) !important; | |
transition: height 0s ease-out 0s; | |
transition: width 0s ease-out 0s; | |
transition: right 0s ease-out 0s; | |
background-color: rgba(255, 255, 255, 0.9); | |
background-image: url("https://www.gstatic.com/images/icons/material/system/2x/more_horiz_grey600_24dp.png"); | |
background-repeat: no-repeat; | |
background-position: 6px 7px; | |
background-size: 24px; | |
} | |
html.simpl.darkTheme .bAw { | |
background-color: rgba(51, 51, 51, 0.9); | |
background-image: url("https://www.gstatic.com/images/icons/material/system/2x/more_horiz_white_24dp.png"); | |
} | |
/* Hide add-ons chooser entirely if Simplify Setting enabled */ | |
html.simpl.hideAddons .bAw { | |
display: none !important; | |
} | |
/* Hide everything inside the add-ons menu until you hover on it */ | |
html.simpl .bAw > div:first-child { | |
display: none; | |
} | |
/* Show add-ons when you hover over the menu */ | |
:root { | |
--add-on-height: 168px; | |
} | |
html.simpl .bAw:hover { | |
background: initial; | |
right: 38px !important; | |
width: 54px !important; | |
height: var(--add-on-height) !important; | |
} | |
html.simpl .bAw:hover > div:first-child { | |
display: flex !important; | |
border-left: 0px; | |
border-radius: 16px; | |
background-color: #fff; | |
} | |
html.simpl .bAw > div:first-child > div { | |
margin: 0px; | |
opacity: 1; | |
} | |
/* Hide buttons other than add-ons */ | |
html.simpl .bAw div[role="tablist"] > div[role="tab"] { | |
display: block !important; | |
} | |
html.simpl .bAw div[role="tablist"] > div[role="tab"]:nth-last-child(-n + 2), | |
html.simpl .bAw div[role="separator"], | |
html.simpl .bAw div[role="presentation"] { | |
display: none !important; | |
} | |
/* Hide the add-on minimize button in the add-on chooser */ | |
html.simpl .bAw .brC-dA-I-Jw { | |
display: none !important; | |
} | |
/* Hide the about button in the add-on chooser */ | |
html.simpl .bAw .brC-by0-P6-I { | |
display: none; | |
} | |
/* Style the add-ons pane */ | |
html.simpl.darkTheme .bAw div[role="navigation"] { | |
background-color: rgba(51, 51, 51, 0.9); | |
} | |
html.simpl .bAw div[role="navigation"] > div:first-child { | |
margin: -var(--add-on-height) 0px 0px -10px; | |
} | |
/* Move add-on chooser labels to left so they aren't easily | |
* hovered on (which causes add-on chooser to hide) */ | |
html.simpl .brC-ays { | |
margin: -41px 0 0 -65px; | |
max-width: 54px; | |
overflow: hidden; | |
white-space: nowrap; | |
text-overflow: ellipsis; | |
} | |
/* Set the active add-on icon to still have a white background */ | |
html.simpl .aT5-aOt-I-JX-Jw { | |
background-color: #fff !important; | |
} | |
/* Move Add-ons chooser over when Add-ons pane and/or quick settings are open */ | |
html.simpl.addOnsOpen .bAw { | |
right: 347px !important; | |
} | |
html.simpl.addOnsOpen .bAw:hover { | |
right: 338px !important; | |
} | |
html.simpl.addOnsOpen.quickSettingsOpen .bAw { | |
right: 637px !important; | |
} | |
html.simpl.addOnsOpen.quickSettingsOpen .bAw:hover { | |
right: 628px !important; | |
} | |
html.simpl.quickSettingsOpen .bAw { | |
right: 337px !important; | |
} | |
html.simpl.quickSettingsOpen .bAw:hover { | |
right: 326px !important; | |
} | |
/* Move Add-ons chooser over when Right side chat is enabled */ | |
html.simpl.rhsChat:not(.addOnsOpen) .bAw { | |
right: 229px !important; | |
} | |
html.simpl.rhsChat:not(.addOnsOpen) .bAw:hover { | |
right: 219px !important; | |
} | |
/* Move the compose button over when the add on pane and/or quick settings are open */ | |
html.simpl.addOnsOpen .z0 { | |
left: calc(100vw - 392px); | |
} | |
html.simpl.quickSettingsOpen .z0 { | |
left: calc(100vw - 382px); | |
} | |
html.simpl.addOnsOpen.quickSettingsOpen .z0 { | |
left: calc(100vw - 682px); | |
} | |
/* Less shadow on the button to show the add-ons pane */ | |
html.simpl .brC-dA-I.aT5-aOt-I-Jp .aT5-aOt-I-JX-Jw { | |
box-shadow: 0 1px 1px 0 rgba(60, 64, 67, 0.2) !important; | |
-webkit-box-shadow: 0 1px 1px 0 rgba(60, 64, 67, 0.2) !important; | |
} | |
/* Change the add-ons pane drop shadow to a stroke */ | |
html.simpl .bq9, | |
html.simpl .bq9 div { | |
box-shadow: none; | |
} | |
html.simpl .bq9 { | |
border-left: 1px solid rgba(0, 0, 0, 0.1); | |
} | |
/* Shrink the action bar when the AddOnsPane AND Search are open */ | |
html.simpl.addOnsOpen:not(.hideSearch):not(.noSplitPane) .aeH { | |
width: calc(var(--action-bar-width) - 92px) !important; | |
} | |
html.simpl.addOnsOpen.readingPane:not(.hideSearch):not(.noSplitPane) | |
.G-atb[gh="tm"] { | |
width: calc(var(--action-bar-width) - 365px) !important; | |
} | |
/* Shrink the action bar when the AddOnsPane is open BUT NOT Search */ | |
html.simpl.addOnsOpen.hideSearch:not(.noSplitPane) .aeH { | |
width: calc(100vw - 540px) !important; | |
} | |
html.simpl.addOnsOpen.hideSearch.readingPane:not(.noSplitPane) .G-atb[gh="tm"] { | |
width: calc(100vw - 535px) !important; | |
} | |
@media only screen and (min-width: 1278.98px) { | |
html.simpl.addOnsOpen.hideSearch.navOpen.readingPane:not(.noSplitPane) | |
.G-atb[gh="tm"] { | |
width: calc(100vw - 731px) !important; | |
} | |
} | |
/* Quick Settings changes */ | |
html.simpl .bkK ~ .nH.nn[style*="width: 56px"]:not(.bAw) { | |
width: 0px !important; | |
min-width: 0px !important; | |
} | |
html.simpl .bkK ~ .nH.nn[style*="width: 356px"]:not(.bAw) { | |
width: 300px !important; | |
min-width: 300px !important; | |
} | |
/* ==================================================================== | |
* SETTINGS | |
*/ | |
/* Hide app bar and action bar when in Settings */ | |
html.simpl.inSettings #gb { | |
height: 0px !important; | |
} | |
html.simpl.inSettings .aeH, | |
html.simpl.inSettings.hideSearch .aeH { | |
position: relative !important; | |
left: 0px !important; | |
width: calc(100vw - 144px) !important; | |
margin-top: -8px; | |
} | |
/* Shift settings Tessa tabs over so they don't cover the back button */ | |
html.simpl.inSettings.readingPane .aeH { | |
left: 64px !important; | |
} | |
html.simpl.inSettings .bkK { | |
margin-left: 72px !important; | |
} | |
html.simpl.inSettings .aeH .G-atb, | |
html.simpl.inSettings.hideSearch .aeH .G-atb { | |
display: none; | |
} | |
html.simpl.inSettings .aeH .nH, | |
html.simpl.inSettings.hideSearch .aeH .nH { | |
box-shadow: none; | |
-webkit-box-shadow: none; | |
} | |
html.simpl.inSettings .aeH .nH > div, | |
html.simpl.inSettings.hideSearch .aeH .nH > div { | |
padding: 4px 8px !important; | |
} | |
html.simpl.inSettings header#gb form, | |
html.simpl.inSettings.hideSearch header#gb form { | |
display: none; | |
} | |
html.simpl.inSettings .aeH .f2 .fY { | |
margin: 16px 0 0 0 !important; | |
padding: 0 8px !important; | |
border-radius: 8px; | |
} | |
/* I'm not sure what element is for but it is ugly when using themes */ | |
html.simpl.inSettings .aeH .f2 .dJ { | |
display: none; | |
} | |
/* Invert the settings tab bar in the dark theme so it is more seamless */ | |
html.simpl.inSettings.darkTheme .fY { | |
filter: invert(0.93); | |
} | |
/* Invert back the selected tab */ | |
html.simpl.inSettings.darkTheme .fY .fZ { | |
filter: invert(1); | |
} | |
/* Hide right side chat when in Settings */ | |
html.simpl.inSettings.rhsChat .aCl { | |
display: none; | |
} | |
/* ==================================================================== | |
* 3RD PARTY EXTENTIONS | |
*/ | |
/* BOOMERANG ---------------------------------------- */ | |
/* Hide Pause Inbox button when Nav is hidden */ | |
html.simpl:not(.navOpen) .aeN #ibp-main { | |
display: none; | |
} | |
/* Reduce action button to icon and desaturate until hover */ | |
html.simpl .gm-boomerang-button-home, | |
html.simpl .gm-boomerang-button-thread { | |
border: 0px !important; | |
font-size: 0px !important; | |
background: transparent !important; | |
width: auto; | |
filter: grayscale(100%); | |
} | |
html.simpl .gm-boomerang-button-home:hover, | |
html.simpl .gm-boomerang-button-thread:hover { | |
filter: grayscale(0%); | |
} | |
/* STREAK / INBOX SDK ------------------------------- */ | |
/* Reduce action button to icon and desaturate until hover */ | |
html.simpl .inboxsdk__button { | |
filter: grayscale(100%); | |
} | |
html.simpl .inboxsdk__button:hover { | |
filter: grayscale(0%); | |
} | |
html.simpl .streak__appToolbarButton_title { | |
display: none; | |
} | |
/* MIXMAX ------------------------------------------ */ | |
/* Turn big blue buttons in action bar into subtle gray icon buttons */ | |
html.simpl div.G-atb div.mixmax-reminder-thread-button, | |
html.simpl div.G-atb div.mixmax-collaborator-thread-button { | |
font-size: 0 !important; | |
background-image: linear-gradient(transparent, transparent) !important; | |
background-color: transparent !important; | |
filter: invert(50%); | |
max-width: 20px !important; | |
border: none !important; | |
box-shadow: none !important; | |
width: 20px !important; | |
padding-left: 8px !important; | |
min-width: 20px !important; | |
padding-right: 8px !important; | |
} | |
html.simpl div.G-atb div.mixmax-reminder-thread-button { | |
padding-left: 0px !important; | |
} | |
html.simpl div.G-atb div.mixmax-reminder-thread-button i, | |
html.simpl div.G-atb div.mixmax-collaborator-thread-button i { | |
font-size: initial !important; | |
padding: 0 8px; | |
} | |
/* Turn labeled color buttons in the conversation into grey icons */ | |
html.simpl .mixmax-export-buttons .js-mixmax-export-menu-button-text { | |
display: none !important; | |
} | |
html.simpl .mixmax-export-buttons { | |
margin: 1px 8px 0 16px !important; | |
} | |
html.simpl .mixmax-export-buttons ~ .mixmax-reply-button, | |
html.simpl .mixmax-export-buttons + div[role="button"] { | |
margin-left: 4px !important; | |
} | |
html.simpl .mixmax-export-buttons i.mixmax-icon-export { | |
background-color: #5f6368; | |
} | |
/* If/when I support a true dark theme... | |
html.simpl.lightTheme .mixmax-export-buttons i.mixmax-icon-export { | |
background-color: #5f6368; | |
} | |
html.simpl.darkTheme .mixmax-export-buttons i.mixmax-icon-export, | |
html.simpl.mediumTheme .mixmax-export-buttons i.mixmax-icon-export { | |
background-color: #fff; | |
} | |
*/ | |
html.simpl.mixmax | |
table[role="presentation"] | |
div[role="listitem"] | |
td[rowspan="2"] { | |
width: 123px !important; | |
} | |
/* MAIL TRACK ---------------------------------------- */ | |
/* For some reason Mail Track sets the action bar to position:relative | |
* which screws up moving it on top of the app bar | |
*/ | |
html.simpl.otherExtensions .aeN + .bkK { | |
position: static !important; | |
} | |
/* GMELIUS ------------------------------------------ */ | |
/* Hide the "The tracker was blocked on this email" notification */ | |
/* TODO: Restyle this instead of hiding it */ | |
html.simpl .gmelius-tracking_notification { | |
display: none; | |
} | |
/* Vertically center unread count */ | |
html.simpl .inboxsdk__navItem .gmelius-nav_accessory > img { | |
top: 4px; | |
} | |
/* ALL EXTENSIONS ----------------------------------- */ | |
/* Hide top-right icons by default */ | |
html.simpl:not(.appSwitcher) #gb .manage_menu, /* Boomerang */ | |
html.simpl:not(.appSwitcher) #gb .mixmax-appbar, /* Mixmax */ | |
html.simpl:not(.appSwitcher) #gb #mailtrack-menu-opener, /* Mail track */ | |
html.simpl:not(.appSwitcher) #gb .inboxsdk__appButton /* Streak */ { | |
display: none !important; | |
} | |
/* Hide label on Streak button */ | |
html.simpl #gb .inboxsdk__button_icon { | |
margin-right: 0px; | |
} | |
html.simpl #gb .inboxsdk__appButton_title { | |
font-size: 0px; | |
} | |
html.simpl #gb .streak__appToolbarButton_title::after { | |
margin-top: -8px; | |
} | |
/* Show them when you hover over the profile pic */ | |
html.simpl.appSwitcher #gb .manage_menu, /* Boomerang */ | |
html.simpl.appSwitcher #gb .mixmax-appbar, /* Mixmax */ | |
html.simpl.appSwitcher #gb #mailtrack-menu-opener, /* Mail track */ | |
html.simpl.appSwitcher #gb .inboxsdk__appButton /* Streak */ { | |
display: block !important; | |
position: absolute; | |
right: 100px; | |
padding: inherit 0px !important; | |
margin: inherit 0px !important; | |
} | |
/* Hide Search and Settings when showing extension buttons */ | |
html.simpl.appSwitcher.otherExtensions div[gh="tm"] div[gh="s"], | |
html.simpl.appSwitcher.otherExtensions #gb form, | |
html.simpl.appSwitcher.otherExtensions .aeH .aqJ, | |
html.simpl.appSwitcher.otherExtensions .aeF .aqJ, | |
html.simpl.appSwitcher.otherExtensions .aeH .adF { | |
display: none; | |
} | |
html.simpl.appSwitcher.otherExtensions .aeH, | |
html.simpl.appSwitcher.otherExtensions div.G-atb[gh="tm"] { | |
width: 50vw !important; | |
} | |
/* ==================================================================== | |
* SIMPLIFY IN-GMAIL NOTIFICATIONS | |
*/ | |
#simplNotification { | |
position: absolute; | |
z-index: 999; | |
top: 100px; | |
right: 48px; | |
max-width: 300px; | |
line-height: 1.7em; | |
border-radius: 8px; | |
padding: 20px 24px 24px 24px; | |
background-color: white; | |
box-shadow: 0 1px 3px 0 rgba(60, 64, 67, 0.151), | |
0 4px 8px 3px rgba(60, 64, 67, 0.091); | |
} | |
#simplNotification button { | |
user-select: none; | |
font-size: 0.87em; | |
font-weight: bold; | |
color: white; | |
padding: 8px 16px; | |
background: #0a6cdd; | |
border-radius: 4px; | |
text-decoration: none; | |
margin: 24px 16px 0 0; | |
border-color: rgba(0, 0, 0, 0.12); | |
cursor: pointer; | |
/* | |
text-shadow: 0 1px 1px rgba(0,0,0,.5); | |
border: 2px solid #0A6CDD; | |
box-shadow: inset 0 -1px 0 rgba(100,121,143,0.122), 0 3px 4px -2px rgba(0,0,0,.3); | |
*/ | |
} | |
#simplNotification button.secondary { | |
color: #0a6cdd; | |
background-color: #f5f5f5; | |
/* | |
background: #fff; | |
border: 2px solid rgba(0,0,0,0.12); | |
text-shadow: 0 1px 1px rgba(0,0,0,.12); | |
*/ | |
} | |
#simplNotification button:focus { | |
outline: none; | |
} | |
/* ==================================================================== | |
* SIMPLIFY EXTENSION OPTIONS PAGE | |
*/ | |
#simplOptions { | |
padding: 10px 50px 50px 50px; | |
max-width: 800px; | |
margin: 5vh auto 0 auto; | |
font-family: system-ui, sans-serif; | |
font-size: 15px; | |
line-height: 2em; | |
text-align: center; | |
} | |
#simplOptions img { | |
margin-bottom: 2em; | |
zoom: 60%; | |
} | |
#simplOptions a { | |
color: #555; | |
} | |
#simplOptions kbd { | |
background-color: #eee; | |
border-radius: 3px; | |
border: 1px solid #b4b4b4; | |
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), | |
0 2px 0 0 rgba(255, 255, 255, 0.7) inset; | |
color: #333; | |
display: inline-block; | |
font-size: 1em; | |
font-family: monospace; | |
font-weight: 700; | |
line-height: 1; | |
padding: 4px 6px; | |
margin: 0 4px; | |
white-space: nowrap; | |
} | |
#simplOptions .footer { | |
opacity: 0.3; | |
} | |
#simplOptions table { | |
padding: 0; | |
margin: 0 auto; | |
border: 0; | |
border-spacing: 0; | |
min-width: 550px; | |
} | |
#simplOptions td { | |
padding: 16px 8px; | |
text-align: left; | |
border: 0; | |
} | |
#simplOptions tr td { | |
border-bottom: 1px solid #ddd; | |
} | |
#simplOptions tr.label td { | |
font-weight: bold; | |
} | |
#simplOptions tr:first-child td { | |
border-top: 0px; | |
} | |
#simplOptions tr:not(.label):hover td { | |
background-color: rgba(0, 0, 0, 0.04); | |
} | |
#simplOptions td.toggle { | |
width: 48px; | |
text-align: center; | |
} | |
#simplOptions label { | |
width: 100%; | |
display: block; | |
} | |
#simplOptions label, | |
#simplOptions input { | |
cursor: pointer; | |
} | |
#simplOptions .beta { | |
display: none; | |
} | |
/* Toggle buttons */ | |
#simplOptions button.toggle { | |
margin: 8px 0 0 0; | |
border-radius: 20px; | |
border: 2px solid #d0d0d0; | |
height: 28px; | |
cursor: pointer; | |
width: 54px; | |
position: relative; | |
display: inline-block; | |
user-select: none; | |
-webkit-user-select: none; | |
-ms-user-select: none; | |
-moz-user-select: none; | |
} | |
#simplOptions button.toggle:focus { | |
outline: none; | |
} | |
#simplOptions button.toggle span { | |
position: absolute; | |
left: 0; | |
top: 0; | |
border-radius: 100%; | |
width: 26px; | |
height: 26px; | |
background-color: white; | |
float: left; | |
margin: -3px 0 0 -3px; | |
border: 2px solid #d0d0d0; | |
transition: left 0.3s; | |
} | |
#simplOptions button.toggle.on { | |
background-color: #59e20e; | |
border: 2px solid #4ecd09; | |
} | |
#simplOptions button.toggle.on span { | |
left: 26px; | |
top: 0; | |
margin: 0; | |
border: none; | |
width: 24px; | |
height: 24px; | |
box-shadow: 0 0 4px rgba(0, 0, 0, 0.1); | |
} | |
`); | |
// https://raw.githubusercontent.com/leggett/simplify/master/gmail/style-images.css | |
applyCss(` | |
/* ================================================== | |
* SIMPLIFY GMAIL | |
* By Michael Leggett: leggett.org | |
* Copyright (c) 2019 Michael Hart Leggett | |
* Repo: github.com/leggett/simplify/blob/master/gmail/ | |
* License: github.com/leggett/simplify/blob/master/gmail/LICENSE | |
* More info: simpl.fyi | |
*/ | |
/* Add CSS for when the height html attribute is used instead of CSS | |
* so height:auto (above) doesn't override the extected height | |
* See more at https://issues.simpl.fyi/196 | |
*/ | |
html.simpl table.Bs .gs > div:not(.gE) img[height="0"] { height: 0px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="1"] { height: 1px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="2"] { height: 2px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="3"] { height: 3px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="4"] { height: 4px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="5"] { height: 5px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="6"] { height: 6px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="7"] { height: 7px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="8"] { height: 8px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="9"] { height: 9px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="10"] { height: 10px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="11"] { height: 11px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="12"] { height: 12px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="13"] { height: 13px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="14"] { height: 14px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="15"] { height: 15px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="16"] { height: 16px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="17"] { height: 17px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="18"] { height: 18px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="19"] { height: 19px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="20"] { height: 20px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="21"] { height: 21px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="22"] { height: 22px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="23"] { height: 23px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="24"] { height: 24px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="25"] { height: 25px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="26"] { height: 26px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="27"] { height: 27px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="28"] { height: 28px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="29"] { height: 29px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="30"] { height: 30px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="31"] { height: 31px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="32"] { height: 32px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="33"] { height: 33px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="34"] { height: 34px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="35"] { height: 35px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="36"] { height: 36px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="37"] { height: 37px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="38"] { height: 38px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="39"] { height: 39px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="40"] { height: 40px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="41"] { height: 41px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="42"] { height: 42px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="43"] { height: 43px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="44"] { height: 44px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="45"] { height: 45px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="46"] { height: 46px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="47"] { height: 47px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="48"] { height: 48px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="49"] { height: 49px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="50"] { height: 50px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="51"] { height: 51px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="52"] { height: 52px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="53"] { height: 53px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="54"] { height: 54px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="55"] { height: 55px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="56"] { height: 56px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="57"] { height: 57px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="58"] { height: 58px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="59"] { height: 59px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="60"] { height: 60px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="61"] { height: 61px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="62"] { height: 62px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="63"] { height: 63px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="64"] { height: 64px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="65"] { height: 65px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="66"] { height: 66px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="67"] { height: 67px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="68"] { height: 68px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="69"] { height: 69px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="70"] { height: 70px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="71"] { height: 71px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="72"] { height: 72px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="73"] { height: 73px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="74"] { height: 74px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="75"] { height: 75px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="76"] { height: 76px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="77"] { height: 77px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="78"] { height: 78px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="79"] { height: 79px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="80"] { height: 80px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="81"] { height: 81px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="82"] { height: 82px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="83"] { height: 83px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="84"] { height: 84px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="85"] { height: 85px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="86"] { height: 86px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="87"] { height: 87px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="88"] { height: 88px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="89"] { height: 89px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="90"] { height: 90px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="91"] { height: 91px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="92"] { height: 92px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="93"] { height: 93px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="94"] { height: 94px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="95"] { height: 95px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="96"] { height: 96px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="97"] { height: 97px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="98"] { height: 98px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="99"] { height: 99px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="100"] { height: 100px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="101"] { height: 101px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="102"] { height: 102px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="103"] { height: 103px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="104"] { height: 104px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="105"] { height: 105px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="106"] { height: 106px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="107"] { height: 107px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="108"] { height: 108px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="109"] { height: 109px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="110"] { height: 110px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="111"] { height: 111px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="112"] { height: 112px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="113"] { height: 113px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="114"] { height: 114px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="115"] { height: 115px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="116"] { height: 116px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="117"] { height: 117px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="118"] { height: 118px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="119"] { height: 119px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="120"] { height: 120px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="121"] { height: 121px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="122"] { height: 122px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="123"] { height: 123px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="124"] { height: 124px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="125"] { height: 125px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="126"] { height: 126px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="127"] { height: 127px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="128"] { height: 128px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="129"] { height: 129px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="130"] { height: 130px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="131"] { height: 131px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="132"] { height: 132px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="133"] { height: 133px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="134"] { height: 134px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="135"] { height: 135px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="136"] { height: 136px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="137"] { height: 137px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="138"] { height: 138px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="139"] { height: 139px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="140"] { height: 140px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="141"] { height: 141px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="142"] { height: 142px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="143"] { height: 143px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="144"] { height: 144px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="145"] { height: 145px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="146"] { height: 146px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="147"] { height: 147px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="148"] { height: 148px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="149"] { height: 149px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="150"] { height: 150px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="151"] { height: 151px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="152"] { height: 152px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="153"] { height: 153px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="154"] { height: 154px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="155"] { height: 155px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="156"] { height: 156px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="157"] { height: 157px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="158"] { height: 158px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="159"] { height: 159px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="160"] { height: 160px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="161"] { height: 161px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="162"] { height: 162px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="163"] { height: 163px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="164"] { height: 164px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="165"] { height: 165px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="166"] { height: 166px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="167"] { height: 167px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="168"] { height: 168px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="169"] { height: 169px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="170"] { height: 170px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="171"] { height: 171px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="172"] { height: 172px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="173"] { height: 173px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="174"] { height: 174px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="175"] { height: 175px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="176"] { height: 176px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="177"] { height: 177px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="178"] { height: 178px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="179"] { height: 179px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="180"] { height: 180px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="181"] { height: 181px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="182"] { height: 182px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="183"] { height: 183px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="184"] { height: 184px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="185"] { height: 185px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="186"] { height: 186px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="187"] { height: 187px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="188"] { height: 188px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="189"] { height: 189px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="190"] { height: 190px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="191"] { height: 191px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="192"] { height: 192px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="193"] { height: 193px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="194"] { height: 194px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="195"] { height: 195px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="196"] { height: 196px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="197"] { height: 197px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="198"] { height: 198px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="199"] { height: 199px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="200"] { height: 200px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="201"] { height: 201px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="202"] { height: 202px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="203"] { height: 203px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="204"] { height: 204px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="205"] { height: 205px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="206"] { height: 206px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="207"] { height: 207px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="208"] { height: 208px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="209"] { height: 209px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="210"] { height: 210px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="211"] { height: 211px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="212"] { height: 212px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="213"] { height: 213px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="214"] { height: 214px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="215"] { height: 215px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="216"] { height: 216px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="217"] { height: 217px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="218"] { height: 218px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="219"] { height: 219px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="220"] { height: 220px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="221"] { height: 221px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="222"] { height: 222px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="223"] { height: 223px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="224"] { height: 224px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="225"] { height: 225px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="226"] { height: 226px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="227"] { height: 227px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="228"] { height: 228px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="229"] { height: 229px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="230"] { height: 230px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="231"] { height: 231px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="232"] { height: 232px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="233"] { height: 233px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="234"] { height: 234px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="235"] { height: 235px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="236"] { height: 236px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="237"] { height: 237px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="238"] { height: 238px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="239"] { height: 239px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="240"] { height: 240px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="241"] { height: 241px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="242"] { height: 242px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="243"] { height: 243px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="244"] { height: 244px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="245"] { height: 245px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="246"] { height: 246px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="247"] { height: 247px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="248"] { height: 248px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="249"] { height: 249px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="250"] { height: 250px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="251"] { height: 251px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="252"] { height: 252px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="253"] { height: 253px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="254"] { height: 254px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="255"] { height: 255px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="256"] { height: 256px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="257"] { height: 257px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="258"] { height: 258px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="259"] { height: 259px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="260"] { height: 260px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="261"] { height: 261px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="262"] { height: 262px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="263"] { height: 263px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="264"] { height: 264px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="265"] { height: 265px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="266"] { height: 266px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="267"] { height: 267px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="268"] { height: 268px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="269"] { height: 269px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="270"] { height: 270px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="271"] { height: 271px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="272"] { height: 272px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="273"] { height: 273px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="274"] { height: 274px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="275"] { height: 275px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="276"] { height: 276px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="277"] { height: 277px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="278"] { height: 278px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="279"] { height: 279px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="280"] { height: 280px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="281"] { height: 281px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="282"] { height: 282px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="283"] { height: 283px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="284"] { height: 284px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="285"] { height: 285px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="286"] { height: 286px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="287"] { height: 287px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="288"] { height: 288px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="289"] { height: 289px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="290"] { height: 290px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="291"] { height: 291px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="292"] { height: 292px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="293"] { height: 293px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="294"] { height: 294px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="295"] { height: 295px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="296"] { height: 296px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="297"] { height: 297px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="298"] { height: 298px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="299"] { height: 299px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[height="399"] { height: 399px; } | |
/* Add CSS for when the width html attribute is used instead of CSS | |
* so height:auto (above) doesn't override the extected height | |
* See more at https://issues.simpl.fyi/196 | |
*/ | |
html.simpl table.Bs .gs > div:not(.gE) img[width="0"] { max-width: 0px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="1"] { max-width: 1px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="2"] { max-width: 2px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="3"] { max-width: 3px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="4"] { max-width: 4px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="5"] { max-width: 5px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="6"] { max-width: 6px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="7"] { max-width: 7px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="8"] { max-width: 8px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="9"] { max-width: 9px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="10"] { max-width: 10px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="11"] { max-width: 11px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="12"] { max-width: 12px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="13"] { max-width: 13px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="14"] { max-width: 14px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="15"] { max-width: 15px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="16"] { max-width: 16px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="17"] { max-width: 17px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="18"] { max-width: 18px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="19"] { max-width: 19px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="20"] { max-width: 20px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="21"] { max-width: 21px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="22"] { max-width: 22px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="23"] { max-width: 23px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="24"] { max-width: 24px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="25"] { max-width: 25px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="26"] { max-width: 26px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="27"] { max-width: 27px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="28"] { max-width: 28px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="29"] { max-width: 29px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="30"] { max-width: 30px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="31"] { max-width: 31px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="32"] { max-width: 32px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="33"] { max-width: 33px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="34"] { max-width: 34px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="35"] { max-width: 35px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="36"] { max-width: 36px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="37"] { max-width: 37px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="38"] { max-width: 38px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="39"] { max-width: 39px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="40"] { max-width: 40px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="41"] { max-width: 41px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="42"] { max-width: 42px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="43"] { max-width: 43px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="44"] { max-width: 44px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="45"] { max-width: 45px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="46"] { max-width: 46px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="47"] { max-width: 47px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="48"] { max-width: 48px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="49"] { max-width: 49px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="50"] { max-width: 50px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="51"] { max-width: 51px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="52"] { max-width: 52px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="53"] { max-width: 53px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="54"] { max-width: 54px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="55"] { max-width: 55px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="56"] { max-width: 56px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="57"] { max-width: 57px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="58"] { max-width: 58px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="59"] { max-width: 59px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="60"] { max-width: 60px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="61"] { max-width: 61px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="62"] { max-width: 62px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="63"] { max-width: 63px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="64"] { max-width: 64px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="65"] { max-width: 65px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="66"] { max-width: 66px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="67"] { max-width: 67px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="68"] { max-width: 68px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="69"] { max-width: 69px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="70"] { max-width: 70px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="71"] { max-width: 71px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="72"] { max-width: 72px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="73"] { max-width: 73px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="74"] { max-width: 74px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="75"] { max-width: 75px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="76"] { max-width: 76px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="77"] { max-width: 77px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="78"] { max-width: 78px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="79"] { max-width: 79px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="80"] { max-width: 80px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="81"] { max-width: 81px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="82"] { max-width: 82px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="83"] { max-width: 83px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="84"] { max-width: 84px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="85"] { max-width: 85px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="86"] { max-width: 86px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="87"] { max-width: 87px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="88"] { max-width: 88px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="89"] { max-width: 89px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="90"] { max-width: 90px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="91"] { max-width: 91px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="92"] { max-width: 92px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="93"] { max-width: 93px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="94"] { max-width: 94px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="95"] { max-width: 95px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="96"] { max-width: 96px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="97"] { max-width: 97px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="98"] { max-width: 98px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="99"] { max-width: 99px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="100"] { max-width: 100px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="101"] { max-width: 101px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="102"] { max-width: 102px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="103"] { max-width: 103px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="104"] { max-width: 104px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="105"] { max-width: 105px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="106"] { max-width: 106px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="107"] { max-width: 107px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="108"] { max-width: 108px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="109"] { max-width: 109px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="110"] { max-width: 110px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="111"] { max-width: 111px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="112"] { max-width: 112px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="113"] { max-width: 113px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="114"] { max-width: 114px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="115"] { max-width: 115px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="116"] { max-width: 116px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="117"] { max-width: 117px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="118"] { max-width: 118px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="119"] { max-width: 119px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="120"] { max-width: 120px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="121"] { max-width: 121px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="122"] { max-width: 122px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="123"] { max-width: 123px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="124"] { max-width: 124px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="125"] { max-width: 125px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="126"] { max-width: 126px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="127"] { max-width: 127px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="128"] { max-width: 128px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="129"] { max-width: 129px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="130"] { max-width: 130px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="131"] { max-width: 131px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="132"] { max-width: 132px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="133"] { max-width: 133px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="134"] { max-width: 134px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="135"] { max-width: 135px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="136"] { max-width: 136px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="137"] { max-width: 137px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="138"] { max-width: 138px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="139"] { max-width: 139px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="140"] { max-width: 140px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="141"] { max-width: 141px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="142"] { max-width: 142px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="143"] { max-width: 143px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="144"] { max-width: 144px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="145"] { max-width: 145px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="146"] { max-width: 146px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="147"] { max-width: 147px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="148"] { max-width: 148px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="149"] { max-width: 149px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="150"] { max-width: 150px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="151"] { max-width: 151px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="152"] { max-width: 152px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="153"] { max-width: 153px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="154"] { max-width: 154px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="155"] { max-width: 155px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="156"] { max-width: 156px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="157"] { max-width: 157px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="158"] { max-width: 158px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="159"] { max-width: 159px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="160"] { max-width: 160px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="161"] { max-width: 161px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="162"] { max-width: 162px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="163"] { max-width: 163px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="164"] { max-width: 164px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="165"] { max-width: 165px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="166"] { max-width: 166px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="167"] { max-width: 167px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="168"] { max-width: 168px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="169"] { max-width: 169px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="170"] { max-width: 170px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="171"] { max-width: 171px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="172"] { max-width: 172px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="173"] { max-width: 173px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="174"] { max-width: 174px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="175"] { max-width: 175px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="176"] { max-width: 176px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="177"] { max-width: 177px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="178"] { max-width: 178px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="179"] { max-width: 179px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="180"] { max-width: 180px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="181"] { max-width: 181px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="182"] { max-width: 182px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="183"] { max-width: 183px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="184"] { max-width: 184px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="185"] { max-width: 185px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="186"] { max-width: 186px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="187"] { max-width: 187px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="188"] { max-width: 188px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="189"] { max-width: 189px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="190"] { max-width: 190px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="191"] { max-width: 191px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="192"] { max-width: 192px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="193"] { max-width: 193px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="194"] { max-width: 194px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="195"] { max-width: 195px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="196"] { max-width: 196px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="197"] { max-width: 197px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="198"] { max-width: 198px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="199"] { max-width: 199px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="200"] { max-width: 200px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="201"] { max-width: 201px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="202"] { max-width: 202px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="203"] { max-width: 203px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="204"] { max-width: 204px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="205"] { max-width: 205px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="206"] { max-width: 206px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="207"] { max-width: 207px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="208"] { max-width: 208px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="209"] { max-width: 209px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="210"] { max-width: 210px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="211"] { max-width: 211px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="212"] { max-width: 212px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="213"] { max-width: 213px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="214"] { max-width: 214px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="215"] { max-width: 215px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="216"] { max-width: 216px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="217"] { max-width: 217px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="218"] { max-width: 218px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="219"] { max-width: 219px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="220"] { max-width: 220px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="221"] { max-width: 221px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="222"] { max-width: 222px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="223"] { max-width: 223px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="224"] { max-width: 224px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="225"] { max-width: 225px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="226"] { max-width: 226px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="227"] { max-width: 227px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="228"] { max-width: 228px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="229"] { max-width: 229px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="230"] { max-width: 230px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="231"] { max-width: 231px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="232"] { max-width: 232px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="233"] { max-width: 233px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="234"] { max-width: 234px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="235"] { max-width: 235px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="236"] { max-width: 236px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="237"] { max-width: 237px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="238"] { max-width: 238px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="239"] { max-width: 239px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="240"] { max-width: 240px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="241"] { max-width: 241px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="242"] { max-width: 242px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="243"] { max-width: 243px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="244"] { max-width: 244px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="245"] { max-width: 245px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="246"] { max-width: 246px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="247"] { max-width: 247px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="248"] { max-width: 248px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="249"] { max-width: 249px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="250"] { max-width: 250px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="251"] { max-width: 251px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="252"] { max-width: 252px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="253"] { max-width: 253px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="254"] { max-width: 254px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="255"] { max-width: 255px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="256"] { max-width: 256px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="257"] { max-width: 257px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="258"] { max-width: 258px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="259"] { max-width: 259px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="260"] { max-width: 260px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="261"] { max-width: 261px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="262"] { max-width: 262px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="263"] { max-width: 263px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="264"] { max-width: 264px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="265"] { max-width: 265px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="266"] { max-width: 266px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="267"] { max-width: 267px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="268"] { max-width: 268px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="269"] { max-width: 269px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="270"] { max-width: 270px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="271"] { max-width: 271px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="272"] { max-width: 272px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="273"] { max-width: 273px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="274"] { max-width: 274px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="275"] { max-width: 275px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="276"] { max-width: 276px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="277"] { max-width: 277px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="278"] { max-width: 278px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="279"] { max-width: 279px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="280"] { max-width: 280px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="281"] { max-width: 281px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="282"] { max-width: 282px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="283"] { max-width: 283px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="284"] { max-width: 284px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="285"] { max-width: 285px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="286"] { max-width: 286px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="287"] { max-width: 287px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="288"] { max-width: 288px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="289"] { max-width: 289px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="290"] { max-width: 290px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="291"] { max-width: 291px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="292"] { max-width: 292px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="293"] { max-width: 293px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="294"] { max-width: 294px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="295"] { max-width: 295px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="296"] { max-width: 296px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="297"] { max-width: 297px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="298"] { max-width: 298px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="299"] { max-width: 299px; } | |
html.simpl table.Bs .gs > div:not(.gE) img[width="300"] { max-width: 300px; } | |
`); | |
// applyCss(` | |
// /* Move pagination to allow for wider search */ | |
// html.simpl | |
// div.nH.aqK > div.Cr.aqJ { | |
// margin-left: 35% | |
// } | |
// html.simpl #gb form { | |
// float: right; | |
// width: 30%; | |
// max-width: none; | |
// margin-right: 8px; | |
// position: relative; | |
// right: 0px; | |
// transition: width 0s; | |
// } | |
// html.simpl.quickSettings #gb form { | |
// width: 66%; | |
// } | |
// html.simpl { | |
// --action-bar-width: 69%; | |
// } | |
// `); | |
// https://raw.githubusercontent.com/leggett/simplify/master/gmail/script.js | |
/* ================================================== | |
* SIMPLIFY GMAIL v1.7.17 | |
* By Michael Leggett: leggett.org | |
* Copyright (c) 2020 Michael Hart Leggett | |
* Repo: github.com/leggett/simplify/blob/master/gmail/ | |
* License: github.com/leggett/simplify/blob/master/gmail/LICENSE.md | |
* More info: simpl.fyi | |
*/ | |
// == SIMPL ===================================================== | |
// Add simpl style to html tag | |
const htmlEl = document.documentElement; | |
htmlEl.classList.add("simpl"); | |
// Toggles custom style and returns latest state | |
function toggleSimpl() { | |
return htmlEl.classList.toggle("simpl"); | |
} | |
// == SIMPLIFY SETTINGS ===================================================== | |
// Initialize debug as off | |
let simplifyDebug = true; | |
// Load Simplify Settings | |
let simplSettings = {}; | |
// Apply setting | |
function applySettings(settings) { | |
if (simplifyDebug) console.log("Apply settings"); | |
/* | |
TODO: something is breaking here | |
*/ | |
for (let key in settings) { | |
if (simplifyDebug) console.log("Applying setting: " + key); | |
switch (key) { | |
case "hideAddons": | |
simplSettings.hideAddons = settings[key]; | |
if (simplSettings.hideAddons) { | |
htmlEl.classList.add("hideAddons"); | |
} else { | |
htmlEl.classList.remove("hideAddons"); | |
} | |
break; | |
case "minimizeSearch": | |
simplSettings.minimizeSearch = settings[key]; | |
if (simplSettings.minimizeSearch) { | |
htmlEl.classList.add("hideSearch"); | |
} else { | |
htmlEl.classList.remove("hideSearch"); | |
} | |
break; | |
case "kbsMenu": | |
simplSettings.kbsMenu = settings[key]; | |
break; | |
case "kbsToggle": | |
simplSettings.kbsToggle = settings[key]; | |
break; | |
case "kbsEscape": | |
simplSettings.kbsEscape = settings[key]; | |
break; | |
case "dateGrouping": | |
simplSettings.dateGrouping = settings[key]; | |
if (simplSettings.dateGrouping) { | |
observeThreadlist(); | |
} else { | |
threadlistObserver.disconnect(); | |
} | |
break; | |
case "hideUnreads": | |
simplSettings.hideUnreads = settings[key]; | |
if (simplSettings.hideUnreads) { | |
htmlEl.classList.add("hideUnreads"); | |
} else { | |
htmlEl.classList.remove("hideUnreads"); | |
} | |
break; | |
case "bundleCategories": | |
simplSettings.bundleCategories = settings[key]; | |
break; | |
case "debug": | |
simplSettings.debug = settings[key]; | |
/* This is applied too late to really work... | |
* maybe you change the setting and restart the app? | |
* or I can use localStorage? | |
if (simplSettings.debug) { | |
simplifyDebug = true; | |
} else { | |
simplifyDebug = false; | |
} | |
*/ | |
break; | |
default: | |
console.log("No case for applying setting: " + key); | |
break; | |
} | |
} | |
if (simplifyDebug) console.log("Apply settings: " + JSON.stringify(settings)); | |
} | |
// == IN-GMAIL SIMPLIFY NOTIFICATIONS ====================================== | |
//const optionsUrl = chrome.extension.getURL("options.html"); | |
function showNotification(msg, actions, hideAfter) { | |
let notificationBox = document.getElementById("simplNotification"); | |
if (notificationBox) { | |
// If notification already exists, just show it again | |
notificationBox.style.display = "block"; | |
} else { | |
// Create notification bubble, attach to body | |
let notificationEl = document.createElement("div"); | |
notificationEl.id = "simplNotification"; | |
document.body.appendChild(notificationEl); | |
notificationBox = document.getElementById("simplNotification"); | |
} | |
// Add content to notification div | |
notificationBox.textContent = msg; | |
// Add primary action to notification div | |
if (actions == "settingsLink") { | |
notificationBox.innerHTML += | |
'<br><button id="openSettings">Open Simplify settings</button>'; | |
// TODO: Why do I have to delay this so the button is in the DOM and I can add the function? | |
setTimeout(function () { | |
document | |
.querySelector("#simplNotification #openSettings") | |
.addEventListener( | |
"click", | |
function () { | |
console.log(optionsUrl); | |
window.open(optionsUrl, "_blank"); | |
notificationBox.style.display = "none"; | |
clearTimeout(autoCloseNotification); | |
}, | |
false | |
); | |
}, 100); | |
} else if (actions == "inboxGmailSettings") { | |
notificationBox.innerHTML += | |
'<br><button id="gmailSettings">Open Gmail settings</button>'; | |
// TODO: Why do I have to delay this so the button is in the DOM and I can add the function? | |
setTimeout(function () { | |
document | |
.querySelector("#simplNotification #gmailSettings") | |
.addEventListener( | |
"click", | |
function () { | |
location.hash = "settings/inbox"; | |
notificationBox.style.display = "none"; | |
clearTimeout(autoCloseNotification); | |
}, | |
false | |
); | |
}, 100); | |
} | |
// Add close notification action to notification div | |
notificationBox.innerHTML += | |
'<button class="secondary" id="closeNotification">Close</button>'; | |
document | |
.querySelector("#simplNotification #closeNotification") | |
.addEventListener( | |
"click", | |
function () { | |
notificationBox.style.display = "none"; | |
clearTimeout(autoCloseNotification); | |
simplSettings.kbsNotified = true; | |
}, | |
false | |
); | |
// Auto hide this notification in 30 seconds | |
let autoCloseNotification = setTimeout(function () { | |
notificationBox.style.display = "none"; | |
}, hideAfter * 1000); | |
} | |
/* == INIT SAVED STATES ================================================= | |
* If someone is signed into multiple accounts, the localStorage | |
* variables will overwrite one another unless we associate them | |
* with an account. The user number in the URL is the only | |
* identifying thing we have access to at the start of page load. | |
* | |
* This will continue to match the username so long as you don't | |
* sign out and then back into a different account first. After | |
* the page is totally loaded, we will check for this case and | |
* reset the local variables if the username associated with | |
* the userId in the URL doesn't match the username associated | |
* with the userId in localStorage. | |
*/ | |
const isDelegate = location.pathname.indexOf("/mail/b/") >= 0; | |
const isPopout = location.href.indexOf("view=btop") >= 0; | |
const userPos = location.pathname.indexOf("/u/"); | |
const uPath = isDelegate | |
? "b" + location.pathname.substring(userPos + 3, userPos + 4) | |
: location.pathname.substring(userPos + 3, userPos + 4); | |
let simplify = {}; | |
const defaultParam = { | |
username: "", | |
previewPane: null, | |
noSplitPane: null, | |
readingPaneWidth: "var(--content-width)", | |
multipleInboxes: "", | |
theme: "", | |
navOpen: null, | |
density: "low", | |
textButtons: null, | |
rhsChat: null, | |
minimizeSearch: false, | |
addOns: null, | |
addOnsCount: 3, | |
otherExtensions: null, | |
chatClosed: null, | |
quickSettings: false, | |
elements: { | |
searchParent: ".gb_pe", | |
menuButton: ".gb_Dc.gb_Kc.gb_Lc > div:first-child", | |
menuContainer: ".gb_Dc.gb_Kc.gb_Lc", | |
backButton: ".gb_cc.gb_fc.gb_va", | |
supportButton: ".gb_Le.gb_Je", | |
accountButton: ".gb_x.gb_Ea.gb_f", | |
accountWrapper: false, | |
gsuiteLogo: false, | |
oneGoogleRing: false, | |
}, | |
}; | |
// Helper function to init or reset the localStorage variable | |
function resetLocalStorage(userNum) { | |
window.localStorage.clear(); | |
if (userNum) { | |
simplify[u] = defaultParam; | |
window.localStorage.simplify = JSON.stringify(simplify); | |
} else { | |
window.localStorage.simplify = JSON.stringify({ "0": defaultParam }); | |
} | |
} | |
// Initialize local storage if undefined | |
if (typeof window.localStorage.simplify === "undefined") { | |
resetLocalStorage(); | |
} | |
// Local copy of Simplify cached state parameters | |
simplify = JSON.parse(window.localStorage.simplify); | |
// Make sure Simplify cached state parameters are initialized for this account | |
if (typeof simplify[u] === "undefined") { | |
resetLocalStorage(u); | |
} | |
// Write to local and localStorage object | |
function updateParam(param, value) { | |
// Sometimes the value has already been written and we just need to update localStorage | |
if (typeof value !== "undefined") { | |
simplify[u][param] = value; | |
} | |
window.localStorage.simplify = JSON.stringify(simplify); | |
} | |
// Hash string | |
function hashCode(s) { | |
return s.split("").reduce(function (a, b) { | |
a = (a << 5) - a + b.charCodeAt(0); | |
return a & a; | |
}, 0); | |
} | |
/* Make sure local variables are for the right account | |
* TODO: for now, when it doesn't match, I just localStorage.clear() | |
* but there might be a better way, maybe try and match the correct account? | |
*/ | |
let username = ""; | |
function checkLocalVar() { | |
const usernameStart = document.title.search(/([\w\.]+\@[\w\.\-]+)/); | |
if (usernameStart > 0) { | |
username = document.title.substring( | |
usernameStart, | |
document.title.lastIndexOf(" - ") | |
); | |
const userhash = hashCode(username); | |
if (simplifyDebug) console.log("Userhash: " + userhash); | |
if (simplify[u].username != userhash) { | |
if (simplifyDebug) console.log("Usernames do NOT match"); | |
resetLocalStorage(); | |
} | |
updateParam("username", userhash); | |
} | |
} | |
// Init Preview Pane or Multiple Inboxes | |
if (simplify[u].previewPane) { | |
if (simplifyDebug) console.log("Loading with reading pane"); | |
htmlEl.classList.add("readingPane"); | |
if (simplify[u].noSplitPane) { | |
htmlEl.classList.add("noSplitPane"); | |
} | |
// Multiple Inboxes doesn't work if you have Preview Pane enabled | |
updateParam("multipleInboxes", "none"); | |
} else { | |
// Multiple Inboxes only works if Preview Pane is disabled | |
if (simplify[u].multipleInboxes == "horizontal") { | |
if (simplifyDebug) | |
console.log("Loading with side-by-side multiple inboxes"); | |
htmlEl.classList.add("multiBoxHorz"); | |
htmlEl.classList.remove("multiBoxVert2", "noSplitPane", "readingPane"); | |
} else if (simplify[u].multipleInboxes == "vertical") { | |
if (simplifyDebug) | |
console.log("Loading with vertically stacked multiple inboxes"); | |
htmlEl.classList.add("multiBoxVert2", "noSplitPane", "readingPane"); | |
htmlEl.classList.remove("multiBoxHorz"); | |
} | |
} | |
// Init themes | |
if (simplify[u].theme == "light") { | |
if (simplifyDebug) console.log("Loading with light theme"); | |
htmlEl.classList.add("lightTheme"); | |
} else if (simplify[u].theme == "dark") { | |
if (simplifyDebug) console.log("Loading with dark theme"); | |
htmlEl.classList.add("darkTheme"); | |
} else if (simplify[u].theme == "medium") { | |
if (simplifyDebug) console.log("Loading with medium theme"); | |
htmlEl.classList.add("mediumTheme"); | |
} | |
// Init nav menu | |
if (simplify[u].navOpen) { | |
if (simplifyDebug) console.log("Loading with nav menu open"); | |
htmlEl.classList.add("navOpen"); | |
} else { | |
if (simplifyDebug) console.log("Loading with nav menu closed"); | |
htmlEl.classList.remove("navOpen"); | |
} | |
// Init quick settings | |
if (simplify[u].quickSettings) { | |
if (simplifyDebug) console.log("Loading with new quick settings menu"); | |
htmlEl.classList.add("quickSettings"); | |
} else { | |
if (simplifyDebug) console.log("Loading with nav menu closed"); | |
htmlEl.classList.remove("quickSettings"); | |
} | |
// Init density | |
if (simplify[u].density == "low") { | |
if (simplifyDebug) console.log("Loading with low density inbox"); | |
htmlEl.classList.add("lowDensityInbox"); | |
} else if (simplify[u].density == "high") { | |
if (simplifyDebug) console.log("Loading with high density inbox"); | |
htmlEl.classList.add("highDensityInbox"); | |
} | |
// Init text button labels | |
if (simplify[u].textButtons) { | |
if (simplifyDebug) console.log("Loading with text buttons"); | |
htmlEl.classList.add("textButtons"); | |
} | |
// Init right side chat | |
if (simplify[u].rhsChat) { | |
if (simplifyDebug) console.log("Loading with right hand side chat"); | |
htmlEl.classList.add("rhsChat"); | |
} | |
// Hide Search box by default | |
if (simplify[u].minimizeSearch == null) { | |
// Only default to hiding search if the window is smaller than 1441px wide | |
if (window.innerWidth < 1441) { | |
updateParam("minimizeSearch", true); | |
} else { | |
updateParam("minimizeSearch", false); | |
} | |
} | |
if (simplify[u].minimizeSearch || simplSettings.minimizeSearch) { | |
if (simplifyDebug) console.log("Loading with search hidden"); | |
htmlEl.classList.add("hideSearch"); | |
} | |
// Make space for add-ons pane if the add-ons pane was open last time | |
if (simplify[u].addOns) { | |
if (simplifyDebug) console.log("Loading with add-ons pane"); | |
htmlEl.classList.add("addOnsOpen"); | |
} | |
// Init 3rd party extensions | |
if (simplify[u].otherExtensions) { | |
if (simplifyDebug) console.log("Loading with 3rd party extensions"); | |
htmlEl.classList.add("otherExtensions"); | |
} | |
// Hide chat if it was last seen closed | |
if (simplify[u].chatClosed === undefined) { | |
simplify[u].chatClosed = false; | |
htmlEl.classList.remove("chatClosed"); | |
updateParam("chatClosed", false); | |
if (simplifyDebug) console.log("Initialized simplify.chatClosed"); | |
} else if (simplify[u].chatClosed) { | |
if (simplifyDebug) console.log("Loading with chat minimized"); | |
// Hide it while Gmail finishes loading | |
htmlEl.classList.add("chatClosed"); | |
} | |
// Add .popout if this is a popped out email | |
if (isPopout) { | |
htmlEl.classList.add("popout"); | |
htmlEl.classList.remove("readingPane"); | |
} | |
// == KEYBOARD SHORTCUTS ===================================================== | |
// Handle Simplify keyboard shortcuts | |
function handleKeyboardShortcut(event) { | |
// If Escape was pressed, close conversation or search | |
if (event.key === "Escape" && simplSettings.kbsEscape) { | |
// Only close if focus wasn't in an input or content editable div | |
if (!event.target.isContentEditable && event.target.tagName != "INPUT") { | |
if (simplifyDebug) | |
console.log("Pressed esc: check to see if in a conversation"); | |
if (inMsg) { | |
if (simplifyDebug) | |
console.log( | |
"Pressed esc: In a conversation, return to list view: " + | |
closeMsgUrl | |
); | |
location.hash = closeMsgUrl; | |
} else if (inSearch) { | |
if (simplifyDebug) | |
console.log( | |
"Pressed esc: In search, return to previous list view: " + | |
closeSearchUrl | |
); | |
location.hash = closeSearchUrl; | |
} else if (inSettings) { | |
if (simplifyDebug) | |
console.log( | |
"Pressed esc: In settings, return to previous list view: " + | |
closeSettingsUrl | |
); | |
location.hash = closeSettingsUrl; | |
} | |
// Return to Inbox if anywhere else (this might have unintended consequences) | |
else { | |
location.hash = "#inbox"; | |
if (simplifyDebug) | |
console.log( | |
"Pressed esc: Not in a conversation or search, go to Inbox" | |
); | |
} | |
} | |
} | |
// If Ctrl+M or Command+M was pressed, toggle nav menu open/closed | |
if ( | |
(event.ctrlKey && (event.key === "M" || event.key === "m")) || | |
(event.metaKey && event.key === "m") | |
) { | |
if (simplSettings.kbsMenu) { | |
document.querySelector(".aeN").classList.toggle("bhZ"); | |
toggleMenu(); | |
event.preventDefault(); | |
// If opening, focus the first element | |
if (!document.querySelector(".aeN").classList.contains("bhZ")) { | |
document.querySelector('div[role="navigation"] a:first-child').focus(); | |
} | |
} else if (!simplSettings.kbsNotified) { | |
if (htmlEl.classList.contains("navOpen")) { | |
showNotification( | |
"Trying to hide the main menu? Enable the keyboard shortcut in Simplify Settings.", | |
"settingsLink", | |
30 | |
); | |
} else { | |
showNotification( | |
"Trying to show the main menu? Enable the keyboard shortcut in Simplify Settings.", | |
"settingsLink", | |
30 | |
); | |
} | |
} | |
} | |
// If Ctrl+S or Command+S was pressed, toggle Simplify on/off | |
if ( | |
(event.ctrlKey && (event.key === "S" || event.key === "s")) || | |
(event.metaKey && event.key === "s") | |
) { | |
if (simplSettings.kbsToggle) { | |
toggleSimpl(); | |
event.preventDefault(); | |
} else if (!simplSettings.kbsNotified) { | |
if (htmlEl.classList.contains("simpl")) { | |
showNotification( | |
"Trying to disable Simplify? Enable the keyboard shortcut in Simplify Settings.", | |
"settingsLink", | |
30 | |
); | |
} else { | |
showNotification( | |
"Trying to enable Simplify? Enable the keyboard shortcut in Simplify Settings.", | |
"settingsLink", | |
30 | |
); | |
} | |
} | |
} | |
} | |
window.addEventListener("keydown", handleKeyboardShortcut, false); | |
// == URL HISTORY ===================================================== | |
/* | |
All known URL Hashes: | |
INBOX | |
#inbox | |
SYSTEM & USER FOLDERS | |
#starred | |
#snoozed | |
#sent | |
#outbox | |
#drafts | |
#imp | |
#chats | |
#scheduled | |
#all | |
#spam | |
#trash | |
#label | |
#category /social /updates /forums /promotions | |
SETTINGS | |
#settings | |
SEARCH | |
#search | |
category:primary | |
category:social | |
category:promotions | |
category:updates | |
category:forums | |
category:reservations | |
category:purchases | |
label:trips ? | |
#advanced-search | |
#create-filter | |
*/ | |
// Set up urlHashes to track and update for closing Search and leaving Settings | |
const regexMsg = /[A-Za-z]{28,}$/; | |
const regexSearch = /#search|#advanced-search|#create-filter/; | |
let inMsg = false, | |
inSearch = false, | |
inList = false, | |
inSettings = false, | |
inInbox = false; | |
let closeMsgUrl = "#inbox", | |
closeSearchUrl = "#inbox", | |
closeSettingsUrl = "#inbox"; | |
function checkView() { | |
// Update view state variables | |
inMsg = location.hash.search(regexMsg) > -1; | |
inList = location.hash.search(regexMsg) == -1; | |
inSearch = location.hash.search(regexSearch) == 0; | |
inSettings = location.hash.search(/#settings/) == 0; | |
inInbox = location.hash.search(/#inbox/) == 0; | |
// In search, settings, or inbox? | |
if (inSearch) htmlEl.classList.add("inSearch"); | |
else { | |
htmlEl.classList.remove("inSearch"); | |
closeSearchUrl = location.hash; | |
} | |
if (inSettings) htmlEl.classList.add("inSettings"); | |
else { | |
htmlEl.classList.remove("inSettings"); | |
closeSettingsUrl = location.hash; | |
} | |
if (inInbox) htmlEl.classList.add("inInbox"); | |
else htmlEl.classList.remove("inInbox"); | |
// In a list or message? | |
if (inList && !inSettings) { | |
// Record the last URL Hash seen before going into a message | |
closeMsgUrl = location.hash; | |
htmlEl.classList.add("inList"); | |
htmlEl.classList.remove("inMsg"); | |
} else if (inMsg) { | |
htmlEl.classList.add("inMsg"); | |
htmlEl.classList.remove("inList", "inInbox", "inSearch"); | |
} | |
} | |
// Initialize URL Hash variables on load | |
checkView(); | |
window.onhashchange = function () { | |
checkView(); | |
// if we were supposed to check the theme later, do it now | |
if (checkThemeLater) { | |
detectTheme(); | |
} | |
// Used to only run on detectReadingPaneLater == true | |
// Seems silly to check for this every time. Will do something smarter in v2 | |
if (inList) { | |
detectReadingPane(); | |
} | |
if (inInbox && detectMultipleInboxesLater) { | |
detectMultipleInboxes(); | |
} | |
// See if we need to date group the view | |
// todo maybe stop the observer and start a new one? | |
if (simplSettings.dateGrouping) { | |
threadlistObserver.disconnect(); | |
observeThreadlist(); | |
} | |
}; | |
/* == INIT STYLESHEET ================================================= | |
* Certain classnames seem to change often in Gmail. Where possible, use | |
* stable IDs, tags, and attribute selectors (e.g. #gb input[name="q"]). | |
* Other times, classnames don't change often. But for when we have to use | |
* a classname and it changes often, detect the classname (usually based on | |
* more stable children elements) and inject the style on load. | |
*/ | |
// Detect and cache classNames that often change so we can inject CSS | |
let detectClassNamesLoops = 0; | |
function detectClassNames() { | |
const searchForm = document.querySelector('form[role="search"]'); | |
if (searchForm) { | |
if (simplifyDebug) console.log("Detecting class names..."); | |
// Search parent | |
const searchParent = searchForm.parentElement.classList.value.trim(); | |
simplify[u].elements["searchParent"] = | |
"." + searchParent.replace(/ /g, "."); | |
// Main menu | |
const menuButton = document | |
.querySelector('#gb div path[d*="18h18v-2H3v2zm0"]') | |
.parentElement.parentElement.parentElement.classList.value.trim(); | |
simplify[u].elements["menuButton"] = | |
"." + menuButton.replace(/ /g, ".") + " > div:first-child"; | |
simplify[u].elements["menuContainer"] = "." + menuButton.replace(/ /g, "."); | |
// Back button | |
const backButton = document | |
.querySelector('#gb div[role="button"] path[d*="11H7.83l5.59-5.59L12"]') | |
.parentElement.parentElement.classList.value.trim(); | |
simplify[u].elements["backButton"] = "." + backButton.replace(/ /g, "."); | |
/* | |
// Support button (usually added about 2 seconds after page is loaded) | |
const supportButton = document.querySelector( | |
'#gb path[d*="18h2v-2h-2v2zm1-16C6.48"]' | |
); | |
if (simplifyDebug) { | |
console.log("Detecting class name for support path element:"); | |
// console.log(supportButton); | |
} | |
simplify[u].elements["supportButton"] = supportButton | |
? "." + | |
supportButton.parentElement.parentElement.parentElement.classList.value | |
.trim() | |
.replace(/ /g, ".") | |
: simplify[u].elements["supportButton"]; | |
*/ | |
// New Quick Settings | |
const quickSettings = document.querySelector( | |
"path[d*='M13.85 22.25h-3.7c-.74 0-1.36-']" | |
); | |
updateParam("quickSettings", quickSettings !== null); | |
// Only calling this here so you don't have to refresh Gmail twice the first time it is detected | |
if (simplify[u].quickSettings) { | |
htmlEl.classList.add("quickSettings"); | |
} | |
// Account switcher (profile pic/name) | |
const accountButton = document.querySelector( | |
`#gb a[aria-label*="${username}"], #gb a[href^="https://accounts.google.com/SignOutOptions"]` | |
); | |
simplify[u].elements["accountButton"] = accountButton | |
? "." + accountButton.classList.value.trim().replace(/ /g, ".") | |
: false; | |
// Account wrapper (for Gsuite accounts) | |
const accountWrapper = document.querySelector( | |
'#gb div[href^="https://accounts.google.com/SignOutOptions"]' | |
); | |
simplify[u].elements["accountWrapper"] = accountWrapper | |
? "." + accountWrapper.classList.value.trim().replace(/ /g, ".") | |
: false; | |
// Gsuite company logo | |
const gsuiteLogo = document.querySelector( | |
'#gb img[src^="https://www.google.com/a/"]' | |
); | |
simplify[u].elements["gsuiteLogo"] = gsuiteLogo | |
? "." + gsuiteLogo.parentElement.classList.value.trim().replace(/ /g, ".") | |
: false; | |
// oneGoogle Ring around profile photo | |
const oneGoogleRing = document.querySelector( | |
'#gb div path[fill="#F6AD01"]' | |
); | |
simplify[u].elements["oneGoogleRing"] = oneGoogleRing | |
? "." + | |
oneGoogleRing.parentElement.parentElement.classList.value | |
.trim() | |
.replace(/ /g, ".") | |
: false; | |
// Update the cached classnames in case any changed | |
updateParam(); | |
// Add styles again in case the classNames changed | |
addStyles(); | |
} else { | |
detectClassNamesLoops++; | |
if (simplifyDebug) | |
console.log("detectClassNames loop #" + detectClassNamesLoops); | |
// only try 10 times and then asume something is wrong | |
if (detectClassNamesLoops < 10) { | |
// Call init function again if the gear button field wasn't loaded yet | |
setTimeout(detectClassNames, 500); | |
} else { | |
if (simplifyDebug) console.log("Giving up on detecting class names"); | |
} | |
} | |
} | |
// Helper function to add CSS to Simplify Style Sheet | |
function addCSS(css, pos) { | |
let position = pos ? pos : simplifyStyles.cssRules.length; | |
simplifyStyles.insertRule(css, position); | |
if (simplifyDebug) | |
console.log("CSS added: " + simplifyStyles.cssRules[position].cssText); | |
} | |
// This is all CSS that I need to add dynamically as the classNames often change for these elements | |
// and I couldn't find a stable way to select the elements other than their classnames | |
function addStyles() { | |
// Remove right padding from action bar so search is always correctly placed | |
addCSS( | |
`html.simpl #gb ${simplify[u].elements.searchParent} { padding-right: 0px !important; }` | |
); | |
// Switch menu button for back button when in Settings | |
addCSS( | |
`html.simpl.inSettings #gb ${simplify[u].elements.menuButton} { display: none !important; }` | |
); | |
addCSS( | |
`html.simpl.inSettings #gb ${simplify[u].elements.backButton} { display: block !important; }` | |
); | |
// Hide the oneGoogle Ring if it is there | |
if (simplify[u].elements["oneGoogleRing"]) { | |
addCSS( | |
`html.simpl #gb ${simplify[u].elements.oneGoogleRing} { display: none !important; }` | |
); | |
} | |
/* | |
// Hide the support button if it is there | |
if (simplify[u].elements["supportButton"]) { | |
addCSS( | |
`html.simpl #gb ${simplify[u].elements.supportButton} { display: none !important; }` | |
); | |
} | |
*/ | |
// Move quick settings | |
/* | |
if (simplify[u].elements["quickSettings"]) { | |
addCSS( | |
`html.simpl #gb ${simplify[u].elements.quickSettings} { display: none !important; }` | |
); | |
} | |
*/ | |
// Restyle the profile name into an icon for delegated accounts | |
if (simplify[u].elements["accountButton"]) { | |
let delegatedAccountButtonCss = | |
"font-size:0px; width:32px; height:32px; margin:4px 6px 0 6px; line-height:26px; "; | |
delegatedAccountButtonCss += | |
"border-radius:18px; background-color:rgba(0,0,0,0.85); font-weight:bold; "; | |
delegatedAccountButtonCss += | |
"text-align:center; text-transform:uppercase; overflow:hidden;"; | |
addCSS( | |
`html.simpl.delegate #gb ${simplify[u].elements.accountButton} { ${delegatedAccountButtonCss} }` | |
); | |
addCSS( | |
`html.simpl.delegate #gb ${simplify[u].elements.accountButton}::first-letter { font-size: initial; color: white; }` | |
); | |
addCSS( | |
`html.simpl.delegate #gb ${simplify[u].elements.accountButton} span { display:none; }` | |
); | |
} | |
// Restyle profile pic itself | |
if (simplify[u].elements["accountWrapper"]) { | |
const accountWrapperCss = | |
"width:48px !important; margin-left:0px; border:none !important; background-color:transparent; box-shadow:none !important;"; | |
addCSS( | |
`html.simpl #gb ${simplify[u].elements.accountWrapper} { ${accountWrapperCss} }` | |
); | |
} | |
// Hide Gsuite company logo if it exists | |
if (simplify[u].elements["gsuiteLogo"]) { | |
addCSS( | |
`html.simpl #gb ${simplify[u].elements.gsuiteLogo} { display:none; }` | |
); | |
} | |
// Adjust size of menu button container | |
addCSS( | |
`html.simpl #gb ${simplify[u].elements.menuContainer} { min-width: 58px !important; padding-right: 0px; }` | |
); | |
// Add correct label for date cluster in inbox for two months ago | |
let now = new Date(); | |
let month2 = new Date(now.getFullYear(), now.getMonth() - 2, 1); | |
let monthNames = [ | |
"JANUARY", | |
"FEBRUARY", | |
"MARCH", | |
"APRIL", | |
"MAY", | |
"JUNE", | |
"JULY", | |
"AUGUST", | |
"SEPTEMBER", | |
"OCTOBER", | |
"NOVEMBER", | |
"DECEMBER", | |
]; | |
addCSS( | |
`html.simpl tr[date="month2"]::before { content: '${ | |
monthNames[month2.getMonth()] | |
}'; }` | |
); | |
} | |
// Add CSS based on cached selectors detected in previous loads | |
let simplifyStyles; | |
function initStyle() { | |
if (document.head) { | |
initStyleObserver.disconnect(); | |
// Create style sheet element and append to <HEAD> | |
let simplifyStyleEl = document.createElement("style"); | |
simplifyStyleEl.id = "simplifyStyle"; | |
document.head.appendChild(simplifyStyleEl); | |
// Setup global variable for style sheet | |
if (simplifyDebug) console.log("Style sheet added"); | |
simplifyStyles = simplifyStyleEl.sheet; | |
// Initialize readingPane width now that Style Sheet is setup | |
addCSS(`:root { --readingPane-width: ${simplify[u].readingPaneWidth}; }`); | |
if (simplifyDebug) | |
console.log("Just made room for search chips in Reading Pane"); | |
// Initialize addOns height now that Style Sheet is setup | |
addCSS( | |
`:root { --add-on-height: ${simplify[u].addOnsCount * 56}px !important; }` | |
); | |
if (simplifyDebug) | |
console.log("Just made room for " + simplify[u].addOnsCount + " add ons"); | |
// Add cached styles | |
addStyles(); | |
} | |
} | |
/* | |
// Figure out when an element is added to the DOM | |
let howLong = 0; | |
console.log('Looking for the Support button'); | |
function findSupport() { | |
let supportButton = document.querySelector('#gb path[d*="18h2v-2h-2v2zm1-16C6.48"]'); | |
if (supportButton) { | |
console.log(`Found support button in ${howLong}ms`); | |
} else { | |
if (howLong > 10000) { | |
console.log(`Giving up on finding Support button. Looked for ${howLong}ms`); | |
} else { | |
howLong += 50; | |
setTimeout(findSupport, 50); | |
} | |
} | |
} | |
findSupport(); | |
*/ | |
// == SEARCH FUNCTIONS ===================================================== | |
/* Focus search input */ | |
function toggleSearchFocus(onOff) { | |
// We are about to show Search if hideSearch is still on the html tag | |
if (onOff == "off" || htmlEl.classList.contains("hideSearch")) { | |
// Remove focus from search input or button | |
document.activeElement.blur(); | |
} else { | |
// Focus the search input | |
document.querySelector('header input[name="q"]').focus(); | |
} | |
} | |
// Setup search event listeners | |
let initSearchLoops = 0; | |
function initSearch() { | |
// See if Search form has be added to the dom yet | |
const searchForm = document.querySelector("#gb form"); | |
// Setup Search functions to show/hide Search at the | |
// right times if we have access to the search field | |
if (searchForm) { | |
// Focus search when you click anywhere on it | |
searchForm.addEventListener( | |
"click", | |
function (event) { | |
toggleSearchFocus(); | |
}, | |
false | |
); | |
// Add function to search button to toggle search open/closed | |
const searchIcon = document.querySelector( | |
'#gb form path[d^="M20.49,19l-5.73"]' | |
).parentElement; | |
searchIcon.addEventListener( | |
"click", | |
function (event) { | |
event.preventDefault(); | |
event.stopPropagation(); | |
htmlEl.classList.toggle("hideSearch"); | |
updateParam("minimizeSearch", htmlEl.classList.contains("hideSearch")); | |
toggleSearchFocus(); | |
}, | |
false | |
); | |
// Add functionality to search close button to close search and go back | |
const searchCloseIcon = document.querySelector( | |
'#gb form path[d~="6.41L17.59"]' | |
).parentElement; | |
// Hide search when you clear the search if it was previously hidden | |
searchCloseIcon.addEventListener( | |
"click", | |
function (event) { | |
event.preventDefault(); | |
event.stopPropagation(); | |
toggleSearchFocus("off"); | |
document.querySelector('header input[name="q"]').value = ""; | |
if (location.hash == closeSearchUrl) { | |
// Hide close button | |
const searchCloseButton = searchCloseIcon.parentElement; | |
const showCloesButtonClass = searchCloseButton.classList.value.split( | |
" " | |
)[1]; | |
searchCloseButton.classList.remove(showCloesButtonClass); | |
// Remove focus style from search input (always the 3rd classname) | |
const searchFormClass = searchForm.classList.value.split(" ")[2]; | |
searchForm.classList.remove(searchFormClass); | |
} else { | |
location.hash = closeSearchUrl; | |
} | |
if (simplify[u].minimizeSearch || simplSettings.minimizeSearch) { | |
htmlEl.classList.add("hideSearch"); | |
} | |
}, | |
false | |
); | |
} else { | |
initSearchLoops++; | |
if (simplifyDebug) console.log("initSearch loop #" + initSearchLoops); | |
// only try 4 times and then asume something is wrong | |
if (initSearchLoops < 5) { | |
// Call init function again if the gear button field wasn't loaded yet | |
setTimeout(initSearch, 500); | |
} | |
} | |
} | |
// Detect if search is focused and needs to be expanded | |
let initSearchFocusLoops = 0; | |
function initSearchFocus() { | |
// If the search field gets focus and hideSearch hasn't been applied, add it | |
const searchInput = document.querySelector('header input[name="q"]'); | |
if (searchInput) { | |
// Show search if the page is loaded is a search view | |
if (inSearch) { | |
htmlEl.classList.remove("hideSearch"); | |
} | |
// Show search if it is focused and hidden | |
searchInput.addEventListener( | |
"focus", | |
function () { | |
htmlEl.classList.remove("hideSearch"); | |
}, | |
false | |
); | |
// Remove the placeholder text in the search box | |
searchInput.placeholder = ""; | |
// Setup eventListeners for search input | |
searchInput.addEventListener("focus", () => { | |
// Add searchFocus from html element | |
htmlEl.classList.add("searchFocused"); | |
setTimeout(function () { | |
if (searchInput.value == "label:") { | |
searchInput.selectionStart = searchInput.selectionEnd = 10000; | |
} else { | |
searchInput.selectionStart = 0; | |
searchInput.selectionEnd = 10000; | |
} | |
}, 100); | |
}); | |
searchInput.addEventListener("blur", (e) => { | |
// Remove searchFocus from html element | |
htmlEl.classList.remove("searchFocused"); | |
// Hide search box if it loses focus, is empty, and was previously hidden | |
if (simplifyDebug) | |
console.log( | |
"Search for '%s' with [u]minimizeSearch set to %s and simplifySettings.minimizeSearch set to %s", | |
searchInput.value, | |
simplify[u].minimizeSearch, | |
simplSettings.minimizeSearch | |
); | |
if ( | |
(searchInput.value == "" || searchInput.value == null) && | |
(simplify[u].minimizeSearch || simplSettings.minimizeSearch) && | |
e.target.name != "q" && | |
e.target.gh != "sda" | |
) { | |
if (simplifyDebug) console.log("Hide search. Clicked on", e.target); | |
htmlEl.classList.add("hideSearch"); | |
} else { | |
if (simplifyDebug) | |
console.log("Don't close search. Clicked on", e.target); | |
} | |
}); | |
} else { | |
// If the search field can't be found, wait and try again | |
initSearchFocusLoops++; | |
if (simplifyDebug) | |
console.log("initSearchFocus loop #" + initSearchFocusLoops); | |
// Only try 10 times and then asume something is wrong | |
if (initSearchFocusLoops < 5) { | |
// Call init function again if the search input wasn't loaded yet | |
setTimeout(initSearchFocus, 500); | |
} | |
} | |
} | |
// == SETTINGS FUNCTIONS ===================================================== | |
// Setup settings event listeners | |
let initSettingsLoops = 0; | |
function initSettings() { | |
// See if settings gear has be added to the dom yet | |
let backButton = document.querySelector('#gb div[aria-label="Go back"] svg'); | |
if (!backButton) { | |
// aria-label doesn't work with non-english interfaces but .gb_1b changes often | |
backButton = document.querySelector( | |
'#gb div[role="button"] path[d*="11H7.83l5.59-5.59L12"]' | |
); | |
if (backButton) backButton = backButton.parentElement; | |
} | |
if (backButton) { | |
backButton.addEventListener( | |
"click", | |
function () { | |
if (inSettings) { | |
location.hash = closeSettingsUrl; | |
} | |
}, | |
false | |
); | |
} else { | |
initSettingsLoops++; | |
if (simplifyDebug) console.log("initSettings loop #" + initSettingsLoops); | |
// only try 5 times and then asume something is wrong | |
if (initSettingsLoops < 5) { | |
// Call init function again if the gear button field wasn't loaded yet | |
setTimeout(initSettings, 500); | |
} | |
} | |
} | |
// == DETECTION FUNCTIONS ===================================================== | |
// Detect if a dark theme is being used and change styles accordingly | |
let detectThemeLoops = 0; | |
let checkThemeLater = false; | |
let observingThemes = false; | |
function detectTheme() { | |
const msgCheckbox = document.querySelectorAll('div[gh="tl"] .xY > .T-Jo')[0]; | |
const conversation = document.querySelectorAll('table[role="presentation"]'); | |
if (simplifyDebug) console.log("Detecting theme..."); | |
if (msgCheckbox) { | |
const checkboxBg = window | |
.getComputedStyle(msgCheckbox, null) | |
.getPropertyValue("background-image"); | |
const menuButton = document.querySelector( | |
'#gb div path[d*="18h18v-2H3v2zm0"]' | |
); | |
const menuButtonBg = window | |
.getComputedStyle(menuButton, null) | |
.getPropertyValue("color"); | |
if (checkboxBg.indexOf("black") > -1) { | |
if (menuButtonBg.indexOf("255, 255, 255") > -1) { | |
// The checkbox is black which means the threadlist | |
// bg is light, BUT the app bar icons are light | |
htmlEl.classList.add("mediumTheme"); | |
htmlEl.classList.remove("lightTheme"); | |
htmlEl.classList.remove("darkTheme"); | |
updateParam("theme", "medium"); | |
} else { | |
htmlEl.classList.add("lightTheme"); | |
htmlEl.classList.remove("mediumTheme"); | |
htmlEl.classList.remove("darkTheme"); | |
updateParam("theme", "light"); | |
} | |
} else { | |
htmlEl.classList.add("darkTheme"); | |
htmlEl.classList.remove("lightTheme"); | |
htmlEl.classList.remove("mediumTheme"); | |
updateParam("theme", "dark"); | |
} | |
checkThemeLater = false; | |
if (!observingThemes) observeThemes(); | |
} else if (conversation.length == 0) { | |
// if we're not looking at a conversation, maybe the threadlist just hasn't loaded yet | |
detectThemeLoops++; | |
if (simplifyDebug) console.log("detectTheme loop #" + detectThemeLoops); | |
// only try 4 times and then asume you're in a thread | |
if (detectThemeLoops < 5) { | |
setTimeout(detectTheme, 500); | |
} | |
} else { | |
// We are looking at a conversation, check the theme when the view changes | |
checkThemeLater = true; | |
} | |
} | |
function observeThemes() { | |
/* BUG (sort of)... this only works when changing to/from/between themes | |
* with background images. It does NOT work when changing between flat color | |
* themes. This is b/c this only detects when attributes are changed inline or | |
* children nodes are added/removed. The switch from white to black themes | |
* changes the css in the head (inside one of many style tags) which then | |
* changes the styles. I don't see an inline change I can observe to trigger | |
* this observer. At least not yet. | |
*/ | |
const themeBg = document.querySelector(".yL .wl"); | |
if (themeBg) { | |
const themesObserverConfig = { | |
attributes: true, | |
attributeFilter: ["style"], | |
childList: true, | |
subtree: true, | |
}; | |
// Create an observer instance that calls the detectTheme function | |
// Annoying that I have to delay by 200ms... if I don't then | |
// it checks to see if anything changed before it had a chance to change | |
const themesObserver = new MutationObserver(function () { | |
setTimeout(detectTheme, 200); | |
}); | |
// Start observing the target node for configured mutations | |
themesObserver.observe(themeBg, themesObserverConfig); | |
observingThemes = true; | |
if (simplifyDebug) console.log("Adding mutation observer for themes"); | |
} else { | |
if (simplifyDebug) | |
console.log("Failed to add mutation observer for themes"); | |
} | |
} | |
// Detect the interface density so we can adjust the line height on items | |
let detectDensityLoops = 0; | |
function detectDensity() { | |
const navItem = document.querySelector('div[role="navigation"] .TN'); | |
if (navItem) { | |
const navItemHeight = parseInt( | |
window.getComputedStyle(navItem, null).getPropertyValue("height") | |
); | |
if (simplifyDebug) | |
console.log( | |
"Detecting inbox density via nav item. Height is " + | |
navItemHeight + | |
"px" | |
); | |
if (navItemHeight <= 26) { | |
if (simplifyDebug) console.log("Detected high density"); | |
htmlEl.classList.remove("lowDensityInbox"); | |
htmlEl.classList.add("highDensityInbox"); | |
updateParam("density", "high"); | |
} else { | |
if (simplifyDebug) console.log("Detected low density"); | |
htmlEl.classList.add("lowDensityInbox"); | |
htmlEl.classList.remove("highDensityInbox"); | |
updateParam("density", "low"); | |
} | |
} else { | |
detectDensityLoops++; | |
if (simplifyDebug) console.log("detectDensity loop #" + detectDensityLoops); | |
// only try 4 times and then assume no reading pane | |
if (detectDensityLoops < 5) { | |
// Call init function again if nav item wasn't loaded yet | |
setTimeout(detectDensity, 500); | |
} else { | |
if (simplifyDebug) | |
console.log("Giving up on detecting interface density"); | |
} | |
} | |
} | |
// Detect if preview panes are enabled and being used | |
let detectReadingPaneLoops = 0; | |
let detectReadingPaneLater = false; | |
let readingPaneObserver; | |
function detectReadingPane() { | |
// Did Gmail load in a conversation in No Split Pane? If so, we can't | |
// detect if this is Reading Pane or not. Do it later when back in a list view. | |
if (inMsg) { | |
detectReadingPaneLater = true; | |
if (simplifyDebug) | |
console.log("Simplify: in conversation view: detect Reading Pane later"); | |
return; | |
} else { | |
detectReadingPaneLater = false; | |
if (simplifyDebug) | |
console.log("Simplify: in an inbox now, detecting Reading Pane"); | |
} | |
// Short term patch: Offline seems to mess with detecting Reading pane | |
const offlineActive = document.getElementsByClassName("bvE"); | |
if (offlineActive && detectReadingPaneLoops == 0) { | |
detectReadingPaneLoops++; | |
setTimeout(detectReadingPane, 2000); | |
} else { | |
// Detect reading pane when conversation view was loaded | |
const readingPaneMenu = document.querySelector('div[selector="nosplit"]'); | |
if (readingPaneMenu) { | |
// Detected Reading Pane | |
htmlEl.classList.add("readingPane"); | |
updateParam("previewPane", true); | |
// See if the Reading pane toggle is for toggling back on reading pane | |
// (vertical or horizontal) which means it is set to "No Split" | |
const noSplitToggle = document.querySelectorAll("div.apI, div.apK"); | |
if (noSplitToggle) { | |
if (noSplitToggle.length == 0) { | |
if (simplifyDebug) console.log("Reading pane detected and active"); | |
htmlEl.classList.remove("noSplitPane"); | |
updateParam("noSplitPane", false); | |
// Detect and set reading pane width | |
detectReadingPaneWidth(); | |
} else { | |
if (simplifyDebug) | |
console.log("Reading pane enabled but set to No Split"); | |
htmlEl.classList.add("noSplitPane"); | |
updateParam("noSplitPane", true); | |
} | |
} | |
/* Listen for readingPane mode toggle via mutation observer */ | |
// Options for the observer (which mutations to observe) | |
// TODO: when loading in a search, there are two split pane toggles and I'm only observing one | |
const readingPaneToggle = document.querySelector( | |
'div[gh="tm"] .apI, div[gh="tm"] .apK, div[gh="tm"] .apJ' | |
); | |
const readingPaneObserverConfig = { | |
attributes: true, | |
childList: false, | |
subtree: false, | |
}; | |
// Callback function to execute when mutations are observed | |
const readingPaneObserverCallback = function (mutationsList, observer) { | |
// Can I just do this for the first mutation? | |
let keepLooking = true; | |
for (let mutation of mutationsList) { | |
if ( | |
mutation.type == "attributes" && | |
mutation.attributeName == "class" && | |
keepLooking | |
) { | |
keepLooking = false; | |
if (simplifyDebug) | |
console.log("Reading pane mode toggled. Detecting new state..."); | |
if (mutation.target.attributes.class.value.indexOf("apJ") > -1) { | |
htmlEl.classList.remove("noSplitPane"); | |
updateParam("noSplitPane", false); | |
} else { | |
htmlEl.classList.add("noSplitPane"); | |
updateParam("noSplitPane", true); | |
} | |
setTimeout(detectReadingPaneWidth, 500); | |
} | |
} | |
}; | |
// Create an observer instance linked to the callback function | |
if (readingPaneObserver !== undefined) { | |
if (simplifyDebug) console.log(readingPaneObserver); | |
readingPaneObserver.disconnect(); | |
} | |
readingPaneObserver = new MutationObserver(readingPaneObserverCallback); | |
if (simplifyDebug) console.log(readingPaneObserver); | |
// Start observing the target node for configured mutations | |
if (simplifyDebug) | |
console.log( | |
"Adding mutation observer for Reading Pane", | |
readingPaneToggle | |
); | |
readingPaneObserver.observe(readingPaneToggle, readingPaneObserverConfig); | |
// Multiple Inboxes only works when Reading pane is disabled | |
updateParam("multipleInboxes", "none"); | |
htmlEl.classList.remove("multiBoxVert2"); | |
htmlEl.classList.remove("multiBoxHorz"); | |
} else { | |
detectReadingPaneLoops++; | |
if (simplifyDebug) | |
console.log("Detect preview pane loop #" + detectReadingPaneLoops); | |
// only try 10 times and then assume no reading pane | |
if (detectReadingPaneLoops < 10) { | |
// Call init function again if the gear button field wasn't loaded yet | |
setTimeout(detectReadingPane, 500); | |
} else { | |
if (simplifyDebug) console.log("Giving up on detecting reading pane"); | |
if (simplify[u].multipleInboxes != "vertical") { | |
htmlEl.classList.remove("readingPane"); | |
htmlEl.classList.remove("noSplitPane"); | |
} | |
updateParam("previewPane", false); | |
updateParam("noSplitPane", false); | |
} | |
} | |
} | |
} | |
// Helper to detect the reading pane width | |
let detectReadingPaneWidthLoops = 0; | |
function detectReadingPaneWidth() { | |
console.log("Detecting reading pane width for search refinements..."); | |
if (simplify[u].noSplitPane) { | |
if (simplifyDebug) console.log("No Split Pane: revert to full width"); | |
let readingPaneWidth = "--var(content-width)"; | |
addCSS(`:root { --readingPane-width: ${readingPaneWidth} !important; }`); | |
updateParam("readingPaneWidth", readingPaneWidth); | |
} else { | |
let leftPane = document.querySelector('div[gh="tl"] > .Nu:first-child'); | |
if (leftPane) { | |
let leftPaneWidth = window.getComputedStyle(leftPane).width; | |
if (leftPaneWidth == "auto") { | |
// Can't detect width yet: call this function again with a delay | |
detectReadingPaneWidthLoops++; | |
if (simplifyDebug) | |
console.log( | |
"Detect preview pane width loop #" + detectReadingPaneWidthLoops | |
); | |
if (detectReadingPaneWidthLoops < 10) { | |
// Call init function again if the gear button field wasn't loaded yet | |
setTimeout(detectReadingPaneWidth, 500); | |
} else { | |
if (simplifyDebug) | |
console.log("Giving up on detecting reading pane width"); | |
} | |
} else { | |
let leftPaneWidthInt = parseInt(leftPaneWidth); | |
let windowWidth = 0.9 * window.innerWidth; | |
// See if this is horizontal width | |
if (leftPaneWidthInt > windowWidth) { | |
console.log("Horizontal split", leftPaneWidthInt, windowWidth); | |
let readingPaneWidth = "calc(100vw - var(--left-offset))"; | |
addCSS( | |
`:root { --readingPane-width: ${readingPaneWidth} !important; }` | |
); | |
updateParam("readingPaneWidth", readingPaneWidth); | |
// TODO: I should probably detect vertical reading pane | |
// vs horizonal somewhere else and add a className | |
} else { | |
console.log("Vertical split"); | |
let readingPaneWidth = leftPaneWidthInt - 20 + "px"; | |
addCSS( | |
`:root { --readingPane-width: ${readingPaneWidth} !important; }` | |
); | |
updateParam("readingPaneWidth", readingPaneWidth); | |
} | |
} | |
} | |
} | |
} | |
// Determine number of add-ons and set the height of the add-ons pane accordingly | |
let detectNumberOfAddOnsLoops = 0; | |
function detectNumberOfAddOns() { | |
// Detect how many add-ons there are | |
const numberOfAddOns = | |
parseInt( | |
document.querySelectorAll( | |
'.bAw div.bse-bvF-I, .bAw div[role="tablist"] > div[role="tab"]' | |
).length | |
) - 2; | |
if (numberOfAddOns > 0) { | |
if (simplifyDebug) | |
console.log("There are " + numberOfAddOns + " add-ons now"); | |
if (numberOfAddOns > 3) { | |
addCSS(`:root { --add-on-height: ${numberOfAddOns * 56}px !important; }`); | |
updateParam("addOnsCount", numberOfAddOns); | |
} else { | |
updateParam("addOnsCount", 3); | |
} | |
} else { | |
detectNumberOfAddOnsLoops++; | |
if (simplifyDebug) | |
console.log("detectNumberOfAddOns loop #" + detectNumberOfAddOnsLoops); | |
// only try 4 times and then assume no add-on pane | |
if (detectNumberOfAddOnsLoops < 5) { | |
// Call init function again if the add-on pane wasn't loaded yet | |
setTimeout(detectNumberOfAddOns, 500); | |
} else { | |
if (simplifyDebug) | |
console.log("Giving up on detecting number of add-ons pane"); | |
} | |
} | |
} | |
// Detect Add-ons Pane | |
let detectAddOnsPaneLoops = 0; | |
function detectAddOns() { | |
const addOnsPane = document.querySelector(".bq9"); | |
if (addOnsPane) { | |
// .br3 is the className for hiding the add-ons pane | |
let addOnsHidden = addOnsPane.className.indexOf("br3") >= 0; | |
if (addOnsHidden) { | |
if (simplifyDebug) console.log("Add-on pane hidden on load"); | |
htmlEl.classList.remove("addOnsOpen"); | |
updateParam("addOns", false); | |
} else { | |
if (simplifyDebug) console.log("Add-on pane visible on load"); | |
htmlEl.classList.add("addOnsOpen"); | |
updateParam("addOns", true); | |
} | |
// Set the height of the add-ons tray based on number of add-ons | |
setTimeout(detectNumberOfAddOns, 5000); | |
// Options for the observer (which mutations to observe) | |
const addOnsObserverConfig = { | |
attributes: true, | |
childList: false, | |
subtree: false, | |
}; | |
// Callback function to execute when mutations are observed | |
// TODO: Can I do this without looping through all the mutations? | |
const addOnsObserverCallback = function (mutationsList, observer) { | |
for (let mutation of mutationsList) { | |
if ( | |
mutation.type == "attributes" && | |
mutation.attributeName == "class" | |
) { | |
if (simplifyDebug) | |
console.log( | |
"Add-on pane className set to: " + | |
mutation.target.attributes.class.value | |
); | |
if (mutation.target.attributes.class.value.indexOf("br3") > -1) { | |
htmlEl.classList.remove("addOnsOpen"); | |
updateParam("addOns", false); | |
} else { | |
htmlEl.classList.add("addOnsOpen"); | |
updateParam("addOns", true); | |
} | |
} | |
} | |
}; | |
// Create an observer instance linked to the callback function | |
const addOnsObserver = new MutationObserver(addOnsObserverCallback); | |
// Start observing the target node for configured mutations | |
if (simplifyDebug) console.log("Adding mutation observer for Add-ons Pane"); | |
addOnsObserver.observe(addOnsPane, addOnsObserverConfig); | |
} else { | |
detectAddOnsPaneLoops++; | |
if (simplifyDebug) | |
console.log("detectAddOns loop #" + detectAddOnsPaneLoops); | |
// only try 4 times and then assume no add-on pane | |
if (detectAddOnsPaneLoops < 10) { | |
// Call init function again if the add-on pane wasn't loaded yet | |
setTimeout(detectAddOns, 500); | |
} else { | |
if (simplifyDebug) console.log("Giving up on detecting add-ons pane"); | |
} | |
} | |
} | |
// Helper function to simulate clicking on an element | |
function simulateClick(el) { | |
const dispatchMouseEvent = function (targetEl, type) { | |
const event = new MouseEvent(type, { | |
view: window, | |
bubbles: true, | |
cancelable: true, | |
}); | |
targetEl.dispatchEvent(event); | |
}; | |
dispatchMouseEvent(el, "mouseover"); | |
dispatchMouseEvent(el, "mousedown"); | |
dispatchMouseEvent(el, "click"); | |
dispatchMouseEvent(el, "mouseup"); | |
dispatchMouseEvent(el, "mouseout"); | |
if (simplifyDebug) console.log("Just clicked on", el); | |
} | |
// Detect Right Side Chat (why hasn't Gmail killed this already?) | |
let detectRightSideChatLoops = 0; | |
function detectRightSideChat() { | |
const talkRoster = document.getElementById("talk_roster"); | |
if (talkRoster) { | |
const rosterSide = talkRoster.getAttribute("guidedhelpid"); | |
if (rosterSide == "right_roster") { | |
if (simplifyDebug) console.log("Right side chat found"); | |
htmlEl.classList.add("rhsChat"); | |
updateParam("rhsChat", true); | |
} else { | |
htmlEl.classList.remove("rhsChat"); | |
updateParam("rhsChat", false); | |
// Close chat roster if it was closed last time | |
if (simplify[u].chatClosed) { | |
// Remove the temporary band-aid | |
htmlEl.classList.remove("chatClosed"); | |
// Simulate clicking on the talk tab if it was supposed to be closed | |
const activeChatTab = document.querySelector( | |
'.aeN div[role="complementary"] div[gh="gt"] .J-KU-KO' | |
); | |
if (activeChatTab) simulateClick(activeChatTab); | |
} | |
/* Add event listener to save the minimized state of the chat roster */ | |
const rosterParent = document.querySelector( | |
'.aeN div[role="complementary"]' | |
); | |
if (simplifyDebug && rosterParent) console.log("Chat roster found"); | |
const rosterObserver = new MutationObserver((mutationsList, observer) => { | |
mutationsList.forEach((mutation) => { | |
if ( | |
mutation.target.attributes.style.value.search("height: 0px") === -1 | |
) { | |
// Roster open | |
updateParam("chatClosed", false); | |
if (simplifyDebug) console.log("Chat roster opened"); | |
} else { | |
// Roster minimized | |
updateParam("chatClosed", true); | |
if (simplifyDebug) console.log("Chat roster closed"); | |
} | |
}); | |
}); | |
rosterObserver.observe(rosterParent, { | |
attributes: true, | |
attributeFilter: ["style"], | |
childList: false, | |
subtree: false, | |
}); | |
} | |
} else { | |
detectRightSideChatLoops++; | |
if (simplifyDebug) | |
console.log("detectRhsChat loop #" + detectRightSideChatLoops); | |
// only try 10 times and then assume no add-on pane | |
if (detectRightSideChatLoops < 10) { | |
// Call init function again if the add-on pane wasn't loaded yet | |
setTimeout(detectRightSideChat, 500); | |
} else { | |
if (simplifyDebug) console.log("Giving up on detecting Talk roster"); | |
} | |
} | |
} | |
// Detect if using text or icon buttons | |
let detectButtonLabelLoops = 0; | |
function detectButtonLabel() { | |
const secondButton = document.querySelectorAll( | |
'div[gh="tm"] div[role="button"] > div' | |
)[2]; | |
if (secondButton) { | |
const textButtonLabel = secondButton.innerText; | |
if (textButtonLabel == "") { | |
// Using icon buttons | |
if (simplifyDebug) console.log("Icon button labels detected"); | |
updateParam("textButtons", false); | |
htmlEl.classList.remove("textButtons"); | |
} else { | |
// Using icon buttons | |
if (simplifyDebug) console.log("Text button labels detected"); | |
updateParam("textButtons", true); | |
htmlEl.classList.add("textButtons"); | |
} | |
} else { | |
detectButtonLabelLoops++; | |
if (detectButtonLabelLoops < 5) { | |
setTimeout(detectButtonLabel, 500); | |
if (simplifyDebug) | |
console.log("Detect button labels loop #" + detectButtonLabelLoops); | |
} | |
} | |
} | |
// Detect nav state | |
let detectMenuStateLoops = 0; | |
function detectMenuState() { | |
const menuButtonIcon = document.querySelector( | |
'#gb div path[d*="18h18v-2H3v2zm0"]' | |
); | |
if (menuButtonIcon) { | |
const menuButton = menuButtonIcon.parentElement.parentElement; | |
const navOpen = menuButton.getAttribute("aria-expanded"); | |
menuButton.addEventListener("click", toggleMenu, false); | |
if (navOpen == "true") { | |
if (simplifyDebug) console.log("Nav is open"); | |
updateParam("navOpen", true); | |
htmlEl.classList.add("navOpen"); | |
} else { | |
if (simplifyDebug) console.log("Nav is closed"); | |
updateParam("navOpen", false); | |
htmlEl.classList.remove("navOpen"); | |
} | |
} else { | |
detectMenuStateLoops++; | |
if (detectMenuStateLoops < 5) { | |
setTimeout(detectMenuState, 500); | |
if (simplifyDebug) | |
console.log("Detect nav state loop #" + detectMenuStateLoops); | |
} | |
} | |
} | |
// Helper function to toggle nav open/closed | |
function toggleMenu() { | |
const menuButton = document.querySelector( | |
`#gb ${simplify[u].elements.menuButton}` | |
); | |
if (simplify[u].navOpen) { | |
htmlEl.classList.remove("navOpen"); | |
menuButton.setAttribute("aria-expanded", "false"); | |
updateParam("navOpen", false); | |
if (simplifyDebug) | |
console.log( | |
"Toggle nav to hidden; simplify.navOpen = " + simplify[u].navOpen | |
); | |
} else { | |
htmlEl.classList.add("navOpen"); | |
menuButton.setAttribute("aria-expanded", "true"); | |
updateParam("navOpen", true); | |
if (simplifyDebug) | |
console.log( | |
"Toggle nav to shown; simplify.navOpen = " + simplify[u].navOpen | |
); | |
} | |
} | |
// Detect Multiple Inboxes | |
let detectMultipleInboxesLoops = 0; | |
let detectMultipleInboxesLater = false; | |
function detectMultipleInboxes() { | |
if (!inInbox) { | |
// If not in the inbox, detect later | |
detectMultipleInboxesLater = true; | |
return; | |
} else { | |
detectMultipleInboxesLater = false; | |
const inboxLoaded = document.querySelectorAll(".ae4").length > 0; | |
const threadList = document.querySelector('div[gh="tl"]'); | |
if (inboxLoaded && threadList) { | |
const multiBoxes = document.querySelectorAll( | |
'.ae4:not([role="tabpanel"])' | |
); | |
if (multiBoxes.length > 1) { | |
// Vertical or Horizontal setup? | |
let sectionWidth = parseInt( | |
window.getComputedStyle(multiBoxes[0]).width | |
); | |
let inboxWidth = parseInt(window.getComputedStyle(threadList).width); | |
if (simplifyDebug) | |
console.log( | |
"Multiple inboxes found", | |
inboxWidth, | |
sectionWidth, | |
multiBoxes.length, | |
multiBoxes | |
); | |
if (inboxWidth <= sectionWidth * 2) { | |
if (simplifyDebug) console.log("Multiple inboxes are vertical"); | |
// TODO: The vertically stacked multiple inboxes is the same as noSplitPane | |
htmlEl.classList.add("multiBoxVert2", "readingPane", "noSplitPane"); | |
htmlEl.classList.remove("multiBoxHorz"); | |
updateParam("multipleInboxes", "vertical"); | |
} else { | |
if (simplifyDebug) console.log("Multiple inboxes are side by side"); | |
htmlEl.classList.add("multiBoxHorz"); | |
htmlEl.classList.remove( | |
"multiBoxVert2", | |
"readingPane", | |
"noSplitPane" | |
); | |
updateParam("multipleInboxes", "horizontal"); | |
} | |
// Multiple Inboxes only works when Reading pane is disabled | |
// htmlEl.classList.remove('readingPane', 'noSplitPane'); | |
updateParam("previewPane", false); | |
updateParam("noSplitPane", false); | |
} else { | |
if (simplifyDebug) console.log("Multiple inboxes not found"); | |
updateParam("multipleInboxes", "none"); | |
htmlEl.classList.remove("multiBoxVert2"); | |
htmlEl.classList.remove("multiBoxHorz"); | |
} | |
} else { | |
detectMultipleInboxesLoops++; | |
if (detectMultipleInboxesLoops < 10) { | |
setTimeout(detectMultipleInboxes, 500); | |
if (simplifyDebug) | |
console.log( | |
"Detect multiple inboxes loop #" + detectMultipleInboxesLoops | |
); | |
} | |
} | |
} | |
} | |
/* Observer to toggle pagination controls | |
* Hide pagination controls if buttons are disabled in the default inbox: | |
* Default inbox .aeH > div[gh=tm] > .ar5 | |
* | |
* Ignore these cases: | |
* Priority Inbox .aeF > .Wm | |
* Split pane .aeF > div[gh=tm] > .ar5 | |
* MultiboxHorz .aeF > div[gh=tm] > .ar5 | |
* MultiboxVert .aeF > div[gh=tm] > .ar5 | |
*/ | |
function testPagination() { | |
const actionBar = document.querySelector("div.aeH"); | |
if (actionBar) { | |
const paginationDivs = document.querySelectorAll(".aeH div.ar5"); | |
paginationDivs.forEach(function (pagination) { | |
// How many messages in the list? | |
let msgCountDivs = pagination.querySelectorAll("span.ts"); | |
if (msgCountDivs.length == 3) { | |
let msgFirst = parseInt(msgCountDivs[0].innerText); | |
let msgLast = parseInt(msgCountDivs[1].innerText); | |
let msgCount = parseInt(msgCountDivs[2].innerText); | |
// Hide pagination control if the total count is less than 100 | |
if (msgFirst == 1 && msgLast == msgCount) { | |
pagination.style.display = "none"; | |
if (simplifyDebug) console.log("Hide pagination controls"); | |
} else { | |
pagination.style.display = "inline-block"; | |
if (simplifyDebug) console.log("Show pagination controls"); | |
} | |
} else { | |
if (simplifyDebug) console.log("Didn't find pagination controls"); | |
} | |
/* | |
const pageButtons = pagination.querySelectorAll( | |
'div[role="button"][aria-disabled="true"]' | |
); | |
if (pageButtons.length >= 2) { | |
pagination.style.display = 'none'; | |
} else { | |
pagination.style.display = 'inline-block'; | |
} | |
*/ | |
}); | |
} | |
} | |
function observePagination() { | |
const actionBar = document.querySelector("div.aeH"); | |
if (actionBar) { | |
// Options for the observer (which mutations to observe) | |
const paginationObserverConfig = { | |
attributes: true, | |
childList: true, | |
subtree: true, | |
}; | |
// Create an observer instance linked to the callback function | |
const paginationObserver = new MutationObserver(testPagination); | |
// Start observing the target node for configured mutations | |
if (simplifyDebug) | |
console.log("Adding mutation observer for Pagination controls"); | |
paginationObserver.observe(actionBar, paginationObserverConfig); | |
} | |
} | |
// Detect if this is a delegated account | |
function detectDelegate() { | |
if (location.pathname.substring(6, 7) == "b") { | |
htmlEl.classList.add("delegate"); | |
} | |
} | |
// Init App switcher event listeners | |
let initAppSwitcherLoops = 0; | |
function initAppSwitcher() { | |
const profileButton = document.querySelectorAll( | |
'#gb a[href^="https://accounts.google.com/SignOutOptions"], #gb a[aria-label^="Google Account: "]' | |
)[0]; | |
const appSwitcherWrapper = document.querySelector("#gbwa"); | |
const appBar = document.querySelector("#gb"); | |
if (profileButton && appSwitcherWrapper) { | |
profileButton.addEventListener( | |
"mouseenter", | |
function () { | |
htmlEl.classList.add("appSwitcher"); | |
}, | |
false | |
); | |
appBar.addEventListener( | |
"mouseleave", | |
function () { | |
htmlEl.classList.remove("appSwitcher"); | |
}, | |
false | |
); | |
} else { | |
initAppSwitcherLoops++; | |
if (initAppSwitcherLoops < 10) { | |
setTimeout(initAppSwitcher, 500); | |
if (simplifyDebug) | |
console.log("initAppSwitcher loop #" + initAppSwitcherLoops); | |
} | |
} | |
} | |
// Detect if there are other 3rd party extensions installed | |
// TODO: Figure out how to auto-dismiss the tray once open – as is, it breaks the app switcher | |
function detectOtherExtensions() { | |
const otherExtensionsList = { | |
"#gb .manage_menu": { width: 70, initial: 100 } /* Boomerang */, | |
"#gb .inboxsdk__appButton": { width: 56, initial: 114 } /* Streak */, | |
"#gb #mailtrack-menu-opener": { width: 44, initial: 120 } /* Mail track */, | |
"#gb .mixmax-appbar": { width: 56, initial: 100 } /* Mixmax */, | |
}; | |
const otherExtensions = document.querySelectorAll( | |
Object.keys(otherExtensionsList).toString() | |
); | |
// window.getComputedStyle(document.querySelector('#gb .inboxsdk__appButton'), null).getPropertyValue('width') | |
if (otherExtensions.length > 0) { | |
htmlEl.classList.add("otherExtensions"); | |
updateParam("otherExtensions", true); | |
if (simplifyDebug) console.log("Other extensions detected"); | |
// See if extension exists and if it does, set its right pos by width + padding | |
let extensionsWidth = 0; | |
Object.entries(otherExtensionsList).forEach(function (extension) { | |
if (simplifyDebug) | |
console.log(`Extensions - Looking for ${extension[0]}...`); | |
const extensionEl = document.querySelector(extension[0]); | |
if (extensionEl) { | |
if (extensionsWidth == 0) { | |
extensionsWidth = extension[1].initial; | |
} | |
extensionEl.style.setProperty("right", `${extensionsWidth}px`); | |
extensionsWidth += extension[1].width; | |
if (extension[0].search("mixmax") !== -1) { | |
htmlEl.classList.add("mixmax"); | |
} | |
if (simplifyDebug) | |
console.log(`Extensions - right position now: ${extensionsWidth}px`); | |
} else { | |
if (simplifyDebug) | |
console.log(`Extensions - Couldn't find ${extension}`); | |
} | |
}); | |
} else { | |
htmlEl.classList.remove("otherExtensions"); | |
updateParam("otherExtensions", false); | |
if (simplifyDebug) console.log("No extensions detected"); | |
} | |
// Detect Gmelius | |
// TODO: Make Gmelius better | |
/* | |
let Gmelius = document.querySelector('div[data-app-name="Gmelius"]'); | |
if (Gmelius) { | |
let nav = document.querySelector('div[role="navigation"]'); | |
nav.addEventListener('click', function(){ | |
alert("Clicked on nav"); | |
}); | |
let gmeliusNav = document.querySelector('div[role="navigation"] .inboxsdk__navMenu'); | |
gmeliusNav.addEventListener('click', function(){ alert("Clicked on Gmelius nav"); }); | |
let gmeliusNavItems = document.querySelectorAll('div[role="navigation"] .inboxsdk__navItem'); | |
for (let i = 0; i < gmeliusNavItems.length; i++) { | |
// console.log(i + '. ' + gmeliusNavItems[i].querySelector('.inboxsdk__navItem_name').innerText); | |
let itemName = gmeliusNavItems[i].querySelector('.inboxsdk__navItem_name').innerText; | |
gmeliusNavItems[i].addEventListener('click', function(){ | |
alert("Clicked on " + itemName); | |
document.querySelector('.ain').classList.remove('ain'); | |
this.classList.add('ain'); | |
}); | |
} | |
} | |
*/ | |
} | |
/* TODO: dynamic padding between pagination and actions | |
* Problem: Different settings like the inputs menu add extra buttons to the | |
* action bar and mis-align the pagination controls above 1441px screen resolution. | |
* | |
* Solution: Detect how many buttons are in the action bar and figure out how much | |
* padding there should be. Set a global css var | |
* | |
* A = Get width of wrapper around right side of action bar | |
window.getComputedStyle(document.querySelector('.aqJ')).getPropertyValue('width') | |
* B = Get width of pagination controls | |
window.getComputedStyle(document.querySelector('.ar5')).getPropertyValue('width') | |
* C = Get current right padding of pagination control | |
window.getComputedStyle(document.querySelector('.ar5')).getPropertyValue('padding-right') | |
* A - (B + C) is the width of just the right actions | |
* --- | |
* I could also possibly do a querySelectorAll on divs after the pagination control and loop | |
* through and count up their computed width to determine the --right-offset | |
*/ | |
/* | |
* TODO: package images | |
* You have to use chrome.runtime.getURL(string path) | |
* More info: https://developer.chrome.com/extensions/runtime#method-getURL | |
*/ | |
/* ========================================================================================== | |
Adding date gaps in the inbox between the following sections | |
Today | |
Yesterday | |
This month | |
<Month name> | |
<Month name year> | |
Earlier | |
---- | |
TODO: | |
- Make it more efficient (I'm calling insertDateGaps more often than I should) | |
*/ | |
// Date constants | |
const now = new Date(); | |
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); | |
const yesterday = new Date( | |
now.getFullYear(), | |
now.getMonth(), | |
now.getDate() - 1 | |
); | |
const month0 = new Date(now.getFullYear(), now.getMonth(), 1); | |
const month1 = new Date(now.getFullYear(), now.getMonth() - 1, 1); | |
const month2 = new Date(now.getFullYear(), now.getMonth() - 2, 1); | |
const month3 = new Date(now.getFullYear(), now.getMonth() - 3, 1); | |
let justRan = false; | |
// Insert date gaps | |
function insertDateGaps(mutationList, observer) { | |
// Check to see if we're in the inbox and it is empty | |
let threads = document.querySelectorAll('div[gh="tl"] div.Cp tbody tr') | |
.length; | |
let inInbox = location.hash.substring(1, 7) == "inbox" ? true : false; | |
if (threads == 0 && inInbox) { | |
// Show inbox zero | |
htmlEl.classList.add("inboxZero"); | |
} else { | |
htmlEl.classList.remove("inboxZero"); | |
/* | |
if (simplifyDebug) { | |
if (mutationList) { | |
console.log(mutationList); | |
} else { | |
console.log('No mutation list') | |
} | |
} | |
*/ | |
let lists = document.querySelectorAll('.UI table[role="grid"]'); | |
if (lists.length > 0) { | |
if (simplifyDebug) console.log("Inserting date gaps"); | |
let lastDate = "today"; | |
lists.forEach(function (list) { | |
let items = list.querySelectorAll(".zA"); | |
if (items.length > 0) { | |
items.forEach(function (item) { | |
// BUNDLE ITEMS BY LABEL (NOT DONE) | |
/* TODO: | |
* this breaks grouping by date, skip if item is display:none | |
* the remaining item should link to a search, not an email | |
*/ | |
// Only bundle items if we're in the Inbox | |
if (inInbox && simplSettings.bundleCategories) { | |
// Get the labels on the item | |
let labels = item.querySelectorAll(".av"); | |
if (labels.length > 0) { | |
let labelList = []; | |
labels.forEach(function (label) { | |
labelList.push(label.innerText); | |
}); | |
item.setAttribute("labels", labelList.toString()); | |
} | |
} | |
// Group by date | |
if (!item.querySelector(".byZ > div")) { | |
// Skip item if it was snoozed | |
let dateSpan = item.querySelector(".xW > span"); | |
if (dateSpan) { | |
let itemDate = new Date(dateSpan.title); | |
if (itemDate > today) { | |
item.setAttribute("date", "today"); | |
lastDate = "today"; | |
} else if (itemDate >= yesterday) { | |
item.setAttribute("date", "yesterday"); | |
lastDate = "yesterday"; | |
} else if (itemDate >= month0) { | |
item.setAttribute("date", "month0"); | |
lastDate = "month0"; | |
} else if (itemDate >= month1) { | |
item.setAttribute("date", "month1"); | |
lastDate = "month1"; | |
} else if (itemDate >= month2) { | |
item.setAttribute("date", "month2"); | |
lastDate = "month2"; | |
} else if (itemDate >= month3) { | |
item.setAttribute("date", "earlier"); | |
lastDate = "earlier"; | |
} | |
} | |
} else { | |
item.setAttribute("date", lastDate); | |
} | |
}); | |
} | |
}); | |
} | |
} | |
} | |
const threadlistObserver = new MutationObserver(insertDateGaps); | |
let observeThreadlistLoops = 1; | |
function observeThreadlist() { | |
// Start observing the target node for configured mutations | |
let threadlist = document.querySelector('div[gh="tl"]'); | |
if (threadlist) { | |
if (simplSettings.dateGrouping) { | |
insertDateGaps(); | |
threadlistObserver.observe(threadlist, { | |
attributes: false, | |
childList: true, | |
subtree: true, | |
}); | |
if (simplifyDebug) console.log("Adding mutation observer for threadlist"); | |
} | |
} else { | |
if (observeThreadlistLoops < 10) { | |
setTimeout(observeThreadlist, 500); | |
observeThreadlistLoops++; | |
if (simplifyDebug) | |
console.log("observeThreadlist attempt #" + observeThreadlistLoops); | |
} | |
} | |
} | |
observeThreadlist(); | |
/* | |
mutation observers: | |
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/MutationObserver | |
childlist: One or more children have been added to and/or removed from the tree; see mutation.addedNodes and mutation.removedNodes | |
attributes: An attribute value changed on the element in mutation.target; the attribute name is in mutation.attributeName and its previous value is in mutation.oldValue | |
subtree: Omit or set to false to observe only changes to the parent node. | |
*/ | |
/** ============================================================================ | |
* QUICK SETTINGS | |
*/ | |
const quickSettingsObserver = { | |
obs: null, | |
element: null, | |
tries: 0, | |
config: { | |
attributes: true, | |
attributeFilter: ["style"], | |
childList: false, | |
subtree: false, | |
}, | |
start() { | |
if (!simplify[u].quickSettings) { | |
if (simplifyDebug) | |
console.log( | |
"Quick Settings isn't enabled for this account. Not observing." | |
); | |
return; | |
} | |
// Only try so many times | |
if (this.tries > 30) { | |
if (simplifyDebug) console.log("Cound't find Quick Settings."); | |
this.tries = 0; | |
this.disconnect(); | |
return; | |
} | |
// Find element to observe (style tag with theme css in it) | |
this.element = document.querySelector('.bkK ~ .nH.nn[style*="min-width"]'); | |
if (!this.element) { | |
this.tries += 1; | |
setTimeout(this.start.bind(this), 100); | |
} else { | |
this.obs = new MutationObserver((mutations) => { | |
if (mutations.some((m) => parseInt(m.target.style.width) < 60)) { | |
if (simplifyDebug) console.log("Quick Settings closed"); | |
document.documentElement.classList.remove("quickSettingsOpen"); | |
} | |
if (mutations.some((m) => parseInt(m.target.style.width) > 290)) { | |
if (simplifyDebug) console.log("Quick Settings open"); | |
document.documentElement.classList.add("quickSettingsOpen"); | |
} | |
}); | |
this.observe(); | |
} | |
}, | |
observe() { | |
if (simplifyDebug) console.log("Starting quick settings observer"); | |
this.obs.observe(this.element, this.config); | |
}, | |
disconnect() { | |
if (this.obs !== null) { | |
this.obs.disconnect(); | |
this.obs = null; | |
this.tries = 0; | |
} | |
}, | |
}; | |
/* ========================================================================================== */ | |
// Initialize styles as soon as head is ready | |
const initStyleObserver = new MutationObserver(initStyle); | |
function observeHead() { | |
// Start observing the target node for configured mutations | |
initStyleObserver.observe(htmlEl, { | |
attributes: true, | |
childList: true, | |
subtree: true, | |
}); | |
if (simplifyDebug) | |
console.log( | |
"Adding mutation observer for head to initialize cached styles" | |
); | |
} | |
observeHead(); | |
// Initialize search as soon as DOM is ready | |
function initOnDomReady() { | |
initSearch(); | |
initSearchFocus(); | |
detectDelegate(); | |
} | |
// Initialize everything else when the page is ready | |
function initOnPageLoad() { | |
initSettings(); | |
// addSettingsGearListener(); | |
detectTheme(); | |
detectReadingPane(); | |
detectDensity(); | |
detectRightSideChat(); | |
detectMenuState(); | |
detectButtonLabel(); | |
detectMultipleInboxes(); | |
detectAddOns(); | |
initAppSwitcher(); | |
testPagination(); | |
observePagination(); | |
quickSettingsObserver.start(); | |
checkLocalVar(); | |
// 3rd party extensions take a few seconds to load | |
setTimeout(detectOtherExtensions, 5000); | |
// Some elements get loaded in after the page is done loading | |
setTimeout(detectClassNames, 7000); | |
} | |
// Only initialize everything if this isn't a popout | |
if (!isPopout) { | |
window.addEventListener("DOMContentLoaded", initOnDomReady, false); | |
window.addEventListener("load", initOnPageLoad, false); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment