Skip to content

Instantly share code, notes, and snippets.

@bdalenoord
Last active July 20, 2020 14:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bdalenoord/a33346a1d7fcc500bf6312cabbecc78f to your computer and use it in GitHub Desktop.
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
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