Hangouts Design Theme for Google Chat Web

Use Google Chat Web with the old Hangouts Design Theme

当前为 2023-12-12 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Hangouts Design Theme for Google Chat Web
  3. // @name:de Hangouts Design Theme für Google Chat Web
  4. // @version 1.0.4
  5. // @description Use Google Chat Web with the old Hangouts Design Theme
  6. // @description:de Google Chat Web mit dem alten Hangouts-Design-Theme verwenden
  7. // @icon https://ssl.gstatic.com/ui/v1/icons/mail/images/favicon_chat_r2.ico
  8. // @author TalkLounge (https://github.com/TalkLounge)
  9. // @namespace https://github.com/TalkLounge/hangouts-design-theme-for-google-chat-web
  10. // @license MIT
  11. // @match https://mail.google.com/chat/*
  12. // @match https://chat.google.com/u/0/*
  13. // @require https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js
  14. // @grant GM.setValue
  15. // @grant GM.getValue
  16. // @grant GM.deleteValue
  17. // ==/UserScript==
  18.  
  19. (function ($, undefined) { // Safe jQuery import, Thanks to https://stackoverflow.com/a/29363547
  20. $(async function () {
  21. const BACKGROUNDS = [
  22. { // Bird
  23. src: "https://www.gstatic.com/chat/hangouts/bg/f466d78212377293b5b745200add730f-stclair.jpg",
  24. srcAlt: "",
  25. author: "Tim St. Clair",
  26. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/TimStClair.jpg",
  27. profileAlt: ""
  28. },
  29. { // Corn Field
  30. src: "https://www.gstatic.com/chat/hangouts/bg/8b5e7ba224b738d2230391a5a15802bb-davec.jpg",
  31. srcAlt: "",
  32. author: "Dave Cohen",
  33. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/DaveCohen.jpg",
  34. profileAlt: ""
  35. },
  36. { // Pink Flower with Bee
  37. src: "https://www.gstatic.com/chat/hangouts/bg/2f1c3d68387ec036b4e49469c3289dae-GregSpencerDude.jpg",
  38. srcAlt: "",
  39. author: "Greg Spencer",
  40. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/GregSpencer.jpg",
  41. profileAlt: ""
  42. },
  43. { // Green Plant with Dragonfly
  44. src: "https://www.gstatic.com/chat/hangouts/bg/1d1d6f6311e7950d18720796905a4cbd-AnushElangovan-02.jpg",
  45. srcAlt: "",
  46. author: "Anush Elangovan",
  47. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/AnushElangovan.jpg",
  48. profileAlt: ""
  49. },
  50. { // Mountains with Pink Sky
  51. src: "https://www.gstatic.com/chat/hangouts/bg/734d92065df4177a006d5438caa46ae1-AKrishnaswamy-01.jpg",
  52. srcAlt: "",
  53. author: "Aravind Krishnaswamy",
  54. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/AravindKrishnaswamy.jpg",
  55. profileAlt: ""
  56. },
  57. { // Sheep Flock with Dog
  58. src: "https://www.gstatic.com/chat/hangouts/bg/c08b5d898d4000793c509ed40f804e2a-Matiash-03.jpg",
  59. srcAlt: "",
  60. author: "Brian Matiash",
  61. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/BrianMatiash.jpg",
  62. profileAlt: ""
  63. },
  64. { // Tourist Spot: Moai
  65. src: "https://www.gstatic.com/chat/hangouts/bg/e4c50a95c0148bb14931a73c2ae80d35-AnushElangovan-01.jpg",
  66. srcAlt: "",
  67. author: "Anush Elangovan",
  68. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/AnushElangovan.jpg",
  69. profileAlt: ""
  70. },
  71. { // Lake with Dark Clouds
  72. src: "https://www.gstatic.com/chat/hangouts/bg/d737e8519d5e7d6e0fe5fec9e35b2e2c-echang.jpg",
  73. srcAlt: "",
  74. author: "Emily Chang",
  75. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/EmilyChang.jpg",
  76. profileAlt: ""
  77. },
  78. { // Orange Flower
  79. src: "https://www.gstatic.com/chat/hangouts/bg/74474c3fc567f4dd012954c96e58d8d6-ChristopherJohnson.jpg",
  80. srcAlt: "",
  81. author: "Christopher Johnson",
  82. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/ChristopherJohnson.jpg",
  83. profileAlt: ""
  84. },
  85. { // Mossy Tree with River
  86. src: "https://www.gstatic.com/chat/hangouts/bg/cbccbd84d54a52e3ba7b148f2711b629-Matiash-02.jpg",
  87. srcAlt: "",
  88. author: "Brian Matiash",
  89. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/BrianMatiash.jpg",
  90. profileAlt: ""
  91. },
  92. { // Two Lions
  93. src: "https://www.gstatic.com/chat/hangouts/bg/650ec88f5cc9e0c827fe6ac61117211d-VidyaNagarajan.jpg",
  94. srcAlt: "",
  95. author: "Vidya Nagarajan",
  96. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/VidyaNagarajan.jpg",
  97. profileAlt: ""
  98. },
  99. { // Nature Waterfall
  100. src: "https://www.gstatic.com/chat/hangouts/bg/bbafcf27dfe823a255e7fa549b5b6ba5-Matiash-01.jpg",
  101. srcAlt: "",
  102. author: "Brian Matiash",
  103. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/BrianMatiash.jpg",
  104. profileAlt: ""
  105. },
  106. { // Coast Line
  107. src: "https://www.gstatic.com/chat/hangouts/bg/a968e293d984aa05eee42df9a8d91dc2-AKrishnaswamy-03.jpg",
  108. srcAlt: "",
  109. author: "Aravind Krishnaswamy",
  110. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/AravindKrishnaswamy.jpg",
  111. profileAlt: ""
  112. },
  113. { // Snowy Valley
  114. src: "https://www.gstatic.com/chat/hangouts/bg/b4a063d93b237f1e21c1bd2ef77d2c45-PaulMoody.jpg",
  115. srcAlt: "",
  116. author: "Paul Moody",
  117. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/PaulMoody.jpg",
  118. profileAlt: ""
  119. },
  120. { // Three Light Aircrafts
  121. src: "https://www.gstatic.com/chat/hangouts/bg/47b6231b6b9171fefbdda2f4750f1fda-nbutko.jpg",
  122. srcAlt: "",
  123. author: "Nicholas Butko",
  124. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/NicholasButko.jpg",
  125. profileAlt: ""
  126. },
  127. { // Valley with big Lake
  128. src: "https://www.gstatic.com/chat/hangouts/bg/1cfdd2ae9f28d352d2853628cdb70659-TreyRatcliff.jpg",
  129. srcAlt: "",
  130. author: "Trey Ratcliff",
  131. profile: "https://www.gstatic.com/chat/hangouts/bg/photographer/TreyRatcliff.jpg",
  132. profileAlt: ""
  133. }
  134. ];
  135. const TRANSLATIONS = { en: "Photo by", de: "Foto von" };
  136. const LANG = navigator.language || navigator.userLanguage;
  137. const TRANSLATION = TRANSLATIONS[LANG] || TRANSLATIONS["en"];
  138. let intervalMain, intervalSidebarFrame;
  139.  
  140. function insertStyle(styles) {
  141. const html = `
  142. <style>
  143. ${styles.trim()}
  144. </style>
  145. `.trim();
  146.  
  147. const child = $.parseHTML(html);
  148. $("head").append(child);
  149. }
  150.  
  151. function insertHTML(parent, html) {
  152. html = html.replace(/>\s+</g, '><').trim(); // Clean up formatted html, Thanks to https://stackoverflow.com/a/27841683
  153. const child = $.parseHTML(html);
  154. $(parent).prepend(child);
  155. }
  156.  
  157. function insertBackground() {
  158. const ran = Math.floor(Math.random() * (BACKGROUNDS.length - 1));
  159.  
  160. insertHTML("body", `
  161. <div class="HDfGC-bg">
  162. <div class="HDfGC-bg-img"></div>
  163. <div class="HDfGC-bg-grad"></div>
  164. <div class="HDfGC-bg-author">
  165. <div class="HDfGC-bg-author-img"></div>
  166. <div class="HDfGC-bg-author-name-wrapper">
  167. <div class="HDfGC-bg-author-name">${TRANSLATION} ${BACKGROUNDS[ran].author}</div>
  168. </div>
  169. </div>
  170. </div>`);
  171.  
  172. insertStyle(`
  173. .HDfGC-bg {
  174. position: fixed;
  175. width: 100%;
  176. height: 100%
  177. }
  178.  
  179. .HDfGC-bg-img {
  180. background-image: url("${BACKGROUNDS[ran].src}");
  181. background-size: cover;
  182. height: 100%
  183. }
  184.  
  185. .HDfGC-bg-grad {
  186. background-image: -moz-linear-gradient(rgba(0,0,0,.4) 0%,rgba(0,0,0,.6) 75%,rgba(0,0,0,.8) 100%);
  187. background-image: linear-gradient(rgba(0,0,0,.4) 0%,rgba(0,0,0,.6) 75%,rgba(0,0,0,.8) 100%);
  188. position: absolute;
  189. top: 0;
  190. left: 0;
  191. bottom: 0;
  192. right: 0
  193. }
  194.  
  195. .HDfGC-bg-author {
  196. right: 1.3vw;
  197. bottom: 1.3vw;
  198. position: absolute
  199. }
  200.  
  201. .HDfGC-bg-author-img {
  202. background-image: url("${BACKGROUNDS[ran].profile}");
  203. background-size: cover;
  204. display: inline-block;
  205. height: 32px;
  206. vertical-align: middle;
  207. width: 32px;
  208. border-radius: 50%
  209. }
  210.  
  211. .HDfGC-bg-author-name-wrapper {
  212. font-size: 13px;
  213. color: white;
  214. display: inline-block;
  215. margin-left: 16px;
  216. vertical-align: middle;
  217. }
  218.  
  219. /* Background */
  220. .wl {
  221. background: inherit;
  222. }
  223.  
  224. /* Sidebar Icon */
  225. #Layer_1 {
  226. display: none;
  227. }
  228. `);
  229.  
  230. $('[role="complementary"]').css("display", "none");
  231. }
  232.  
  233. function invertColors() {
  234. insertStyle(`
  235. /* Navbar Icons */
  236. .gb_Ja svg, .gb_Nc svg, .gb_9c .gb_hd, .gb_Zc .gb_hd {
  237. color: #C8D2DF !important;
  238. }
  239.  
  240. /* Online Status */
  241. .Yb.bax.bCd {
  242. background: none;
  243. }
  244.  
  245. /* Online Status */
  246. .Yc.bax {
  247. color: white;
  248. }
  249. `);
  250.  
  251. $("a img").eq(0).attr("srcset", "https://ssl.gstatic.com/ui/v1/icons/mail/rfr/logo_chat_dark_2x.png 2x ,https://ssl.gstatic.com/ui/v1/icons/mail/rfr/logo_chat_dark_1x.png 1x")
  252. }
  253.  
  254. function changeDetails() {
  255. insertHTML(".nH.bkK", `
  256. <button class="HDfGC-x">
  257. <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
  258. <rect width="16" height="16" fill="none"></rect>
  259. <path fill-rule="evenodd" clip-rule="evenodd" d="M4.3584 3.15631L3.15632 4.35839L6.79792 8L3.15631 11.6416L4.35839 12.8437L8.00001 9.20208L11.6416 12.8437L12.8437 11.6416L9.20209 8L12.8437 4.35842L11.6416 3.15633L8.00001 6.79792L4.3584 3.15631Z" class="WIVxDf KuRlUd"></path>
  260. </svg>
  261. </button>`);
  262.  
  263. insertStyle(`
  264. .HDfGC-x {
  265. position: absolute;
  266. z-index: 1;
  267. right: 4.5rem;
  268. top: 2.5rem;
  269. background-color: initial;
  270. border: none;
  271. padding: 0px;
  272. cursor: pointer;
  273. }
  274.  
  275. .HDfGC-x svg {
  276. fill: black;
  277. }
  278.  
  279. /* Main */
  280. .nH.bkK {
  281. margin-left: 4vw;
  282. margin-top: 2.99vh;
  283. display: none;
  284. }
  285.  
  286. .nH.bkK > .nH {
  287. background-color: initial;
  288. }
  289.  
  290. /* Search Bar */
  291. #aso_search_form_anchor {
  292. background-color: initial;
  293. }
  294.  
  295. #aso_search_form_anchor input {
  296. color: white;
  297. }
  298.  
  299. #aso_search_form_anchor input::placeholder {
  300. color: #C8D2DF
  301. }
  302.  
  303. #aso_search_form_anchor input::-ms-input-placeholder {
  304. color: #C8D2DF
  305. }
  306.  
  307. /* Chats & Groups Nav */
  308. .aeN {
  309. max-width: none !important;
  310. }
  311.  
  312. /* New Chat Button */
  313. .T-I-KE {
  314. margin-top: 8px;
  315. }
  316. `);
  317.  
  318. $('[role="navigation"]').css("background-color", "white");
  319. $('[role="navigation"]').css("border-top-left-radius", "4px");
  320. $('[role="navigation"]').css("border-top-right-radius", "4px");
  321. $('[role="navigation"]').css("width", "20.83vw");
  322. $('[role="navigation"]').css("top", "3vh");
  323. $('[role="navigation"]').css("left", "3.5vw");
  324. }
  325.  
  326. function toggleMain(visible) {
  327. if (visible) {
  328. $(".nH.bkK").css("display", "block");
  329. } else {
  330. $(".nH.bkK").css("display", "none");
  331. }
  332. }
  333.  
  334. function initMain() {
  335. if ($("#loading").is(":visible")) { // Stop when not completely loaded
  336. return;
  337. }
  338.  
  339. //console.log("initMain(): Run");
  340.  
  341. window.clearInterval(intervalMain);
  342. //console.log("initMain(): Cleared Interval");
  343.  
  344. insertBackground();
  345. invertColors();
  346. changeDetails();
  347.  
  348. // Make Main toggable
  349.  
  350. window.addEventListener("message", function (e) {
  351. if (typeof (e?.data?.toggleMain) != "undefined") {
  352. toggleMain(e?.data?.toggleMain);
  353. }
  354. });
  355.  
  356. $(".HDfGC-x").click(function (e) {
  357. toggleMain();
  358. });
  359.  
  360. $("#aso_search_form_anchor button").each(function () {
  361. $(this).click(function (e) {
  362. toggleMain(true);
  363. });
  364. });
  365.  
  366. $("#aso_search_form_anchor input").keyup(function (e) {
  367. toggleMain(true);
  368. });
  369.  
  370. // Set IFrame Chats Full Height
  371.  
  372. const observer = new MutationObserver(function (mutationList) {
  373. mutationList.forEach(function (mutation) {
  374. if (mutation.type == "attributes" && mutation.target.tagName == "IFRAME" && mutation.target.style?.height && parseInt(mutation.target.style.height) > 100 && mutation.target.style.height != "92.7vh") {
  375. $(mutation.target).css("width", "20.83vw");
  376. $(mutation.target).css("height", "92.7vh");
  377. $(mutation.target).parent().parent().parent().parent().css("width", "21.33vw");
  378. }
  379. });
  380. });
  381.  
  382. observer.observe(document.querySelector(".no"), {
  383. subtree: true,
  384. attributes: true
  385. });
  386.  
  387. $(".no").empty();
  388. }
  389.  
  390. function initSidebarFrame() {
  391. if (!$('[role="list"] [role="listitem"] div').length) { // Stop when not completely loaded
  392. return;
  393. }
  394.  
  395. //console.log("initFrame(): Run");
  396.  
  397. window.clearInterval(intervalSidebarFrame);
  398. //console.log("initFrame(): Cleared Interval");
  399.  
  400. $("#ucc-0").children().each(function () {
  401. $(this).click(function (e) {
  402. window.parent.postMessage({ "toggleMain": true }, "*");
  403. });
  404. });
  405.  
  406. window.setInterval(() => {
  407. $('[role="list"] [role="listitem"]').each(function () {
  408. if ($(this).attr("jsaction")) {
  409. $(this).removeAttr("jsaction");
  410. const elem = $(this).find('div[role="button"][jsaction]').get(0);
  411. $(this).find('[role="link"]').children().eq(0).click(function (e) {
  412. e.stopPropagation();
  413. elem.click();
  414. });
  415. }
  416. });
  417. }, 1000);
  418. }
  419.  
  420. // Start functions
  421. if (window.location.href.startsWith("https://mail.google.com/chat/u/0/") && window.top == window.self) { // Main Page
  422. if (! await GM.getValue("reload") || new Date().getTime() - await GM.getValue("reload") > 10 * 1000) { // Must be loaded without Cache otherwise the IFrames will not be injected
  423. await GM.setValue("reload", new Date().getTime());
  424. window.setTimeout(() => {
  425. $.ajax({
  426. url: window.location.href,
  427. headers: {
  428. "Pragma": "no-cache",
  429. "Expires": -1,
  430. "Cache-Control": "no-cache"
  431. }
  432. }).done(function () {
  433. window.location.reload(true);
  434. });
  435. }, 500);
  436. } else {
  437. await GM.deleteValue("reload");
  438. intervalMain = window.setInterval(initMain, 500);
  439. }
  440. } else if (window.location.href.startsWith("https://chat.google.com/u/0/frame") && window.top != window.self && window.location.href.indexOf("id=world") != -1) {
  441. intervalSidebarFrame = window.setInterval(initSidebarFrame, 500);
  442. }
  443. });
  444. })(window.jQuery.noConflict(true));