Distraction free Gmail // inbox check detox

Designed for people who use to check their inbox too often. This script hides the Inbox and allows only 3 checks per day for 10 Minutes. Searching for emails and writing emails is possible all day.

  1. // ==UserScript==
  2. // @name Distraction free Gmail // inbox check detox
  3. // @namespace https://lukasferger.de
  4. // @version 2025-03-27
  5. // @description Designed for people who use to check their inbox too often. This script hides the Inbox and allows only 3 checks per day for 10 Minutes. Searching for emails and writing emails is possible all day.
  6. // @author Lukas
  7. // @license MIT means
  8. // @match https://mail.google.com/mail/*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=google.com
  10. // @grant none
  11. // @run-at document-start
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. // Konstanten
  18. const inboxSelector = 'div[role="main"]';
  19. const styleId = 'inbox-hide-style';
  20. const overlayId = 'flash-overlay';
  21. const maxViewsPerDay = 3;
  22. const viewDuration = 10 * 60 * 1000; // 10 Minuten
  23. const key = 'emailViews';
  24. var today = new Date().toISOString().split('T')[0];
  25.  
  26. // Zähler laden/speichern
  27. let views = JSON.parse(localStorage.getItem(key) || '{}');
  28. if (!views[today]) { views[today] = 0; }
  29. localStorage.setItem(key, JSON.stringify(views));
  30.  
  31. // Statusvariablen
  32. let manualViewActive = false; // Manuell aktivierte Ansicht (nur im aktuellen Tab)
  33. let timerId = null;
  34. let toggleButton = null;
  35.  
  36. // CSS zum Ausblenden der Inbox – hier ohne innerHTML
  37. function injectHideStyle() {
  38. if (!document.getElementById(styleId)) {
  39. const style = document.createElement('style');
  40. style.id = styleId;
  41. style.textContent = `${inboxSelector} { display: none !important; }`;
  42. document.documentElement.appendChild(style);
  43. }
  44. }
  45. function removeHideStyle() {
  46. const style = document.getElementById(styleId);
  47. if (style) { style.remove(); }
  48. }
  49.  
  50. // Overlay einfügen, um Flash während des Ladevorgangs zu verhindern
  51. function injectOverlay() {
  52. if (!document.getElementById(overlayId)) {
  53. const overlay = document.createElement('div');
  54. overlay.id = overlayId;
  55. overlay.style.position = 'fixed';
  56. overlay.style.top = '0';
  57. overlay.style.left = '0';
  58. overlay.style.width = '100%';
  59. overlay.style.height = '100%';
  60. overlay.style.backgroundColor = '#ffffff';
  61. overlay.style.zIndex = '10000';
  62. overlay.style.pointerEvents = 'none';
  63. document.documentElement.appendChild(overlay);
  64. }
  65. }
  66. // Overlay wird nach dem Laden entfernt – unabhängig vom Rest
  67. function removeOverlay() {
  68. const overlay = document.getElementById(overlayId);
  69. if (overlay) { overlay.remove(); }
  70. }
  71.  
  72. // Prüft, ob die aktuelle URL eine Suchseite ist
  73. function isSearchUrl() {
  74. return location.hash && location.hash.startsWith('#search');
  75. }
  76.  
  77. // Aktiviert den manuellen View – verbraucht einen View und startet den 10-Minuten-Timer
  78. function activateManualView() {
  79. today = new Date().toISOString().split('T')[0];
  80. if (views[today] >= maxViewsPerDay) {
  81. alert("Tageslimit erreicht.");
  82. return;
  83. }
  84. removeHideStyle();
  85. manualViewActive = true;
  86. views[today]++;
  87. localStorage.setItem(key, JSON.stringify(views));
  88. updateToggleButton();
  89. if (timerId) { clearTimeout(timerId); }
  90. timerId = setTimeout(() => {
  91. deactivateManualView();
  92. }, viewDuration);
  93. }
  94.  
  95. // Deaktiviert den manuellen View – Inbox wird ausgeblendet
  96. function deactivateManualView() {
  97. injectHideStyle();
  98. manualViewActive = false;
  99. updateToggleButton();
  100. if (timerId) { clearTimeout(timerId); timerId = null; }
  101. }
  102.  
  103. // Aktiviert den Suchmodus – Suchergebnisse sollen immer sichtbar sein, ohne View-Verbrauch
  104. function activateSearchView() {
  105. removeHideStyle();
  106. if (toggleButton) { toggleButton.style.display = 'none'; }
  107. }
  108.  
  109. // Aktualisiert den Toggle-Button: Auf Nicht-Suchseiten sichtbar, Text je nach Status
  110. function updateToggleButton() {
  111. if (!toggleButton) return;
  112. if (isSearchUrl()) {
  113. toggleButton.style.display = 'none';
  114. } else {
  115. toggleButton.style.display = 'block';
  116.  
  117. const remaining = maxViewsPerDay - views[today];
  118. toggleButton.innerText = manualViewActive ? 'Inbox ausblenden' : 'Inbox anzeigen (' + remaining + ')';
  119. }
  120. }
  121.  
  122. // Toggle-Button einrichten
  123. function addToggleButton() {
  124. const remaining = maxViewsPerDay - views[today];
  125.  
  126. toggleButton = document.createElement('button');
  127. toggleButton.innerText = 'Inbox anzeigen (' + remaining + ')';
  128. toggleButton.style.position = 'fixed';
  129. toggleButton.style.top = '10px';
  130. toggleButton.style.right = '10px';
  131. toggleButton.style.zIndex = '10001';
  132. toggleButton.style.padding = '8px';
  133. toggleButton.style.fontSize = '14px';
  134. toggleButton.style.backgroundColor = '#4285f4';
  135. toggleButton.style.color = 'white';
  136. toggleButton.style.border = 'none';
  137. toggleButton.style.borderRadius = '4px';
  138. toggleButton.style.cursor = 'pointer';
  139. toggleButton.onclick = () => {
  140. // Nur auf Nicht-Suchseiten
  141. if (manualViewActive) {
  142. deactivateManualView();
  143. } else {
  144. activateManualView();
  145. }
  146. };
  147. document.body.appendChild(toggleButton);
  148. updateToggleButton();
  149. }
  150.  
  151. // Bei Navigation: Wenn du in einer Suchseite landest, aktiviere Suchmodus.
  152. // Falls du in Nicht-Suchseiten navigierst, bleibt der manuelle View aktiv, wenn er bereits aktiviert wurde.
  153. window.addEventListener('hashchange', () => {
  154. if (isSearchUrl()) {
  155. activateSearchView();
  156. } else {
  157. // Wenn manueller View aktiv, beibehalten – ansonsten Inbox ausblenden
  158. if (!manualViewActive) {
  159. injectHideStyle();
  160. }
  161. updateToggleButton();
  162. }
  163. });
  164.  
  165. // Direkt beim Skriptstart: Inbox ausblenden und Overlay einfügen
  166. injectHideStyle();
  167. injectOverlay();
  168.  
  169. // Sobald die Seite fertig geladen ist, wird der Overlay entfernt (unabhängig vom Rest)
  170. window.addEventListener('load', () => {
  171. removeOverlay();
  172. addToggleButton();
  173. if (isSearchUrl()) {
  174. activateSearchView();
  175. } else {
  176. // Wenn kein manueller View aktiv ist, bleibt die Inbox ausgeblendet
  177. if (!manualViewActive) {
  178. injectHideStyle();
  179. }
  180. updateToggleButton();
  181. }
  182. });
  183. })();