IBM Verse - Auto-Select Next Email

load up next email when the current one is deleted

  1. // ==UserScript==
  2. // @name IBM Verse - Auto-Select Next Email
  3. // @namespace https://openuserjs.org/users/zachhardesty7
  4. // @author Zach Hardesty <zachhardesty7@users.noreply.github.com> (https://github.com/zachhardesty7)
  5. // @description load up next email when the current one is deleted
  6. // @copyright 2020, Zach Hardesty (https://zachhardesty.com/)
  7. // @license GPL-3.0-only; http://www.gnu.org/licenses/gpl-3.0.txt
  8. // @version 2.2.1
  9.  
  10. // @homepageURL https://github.com/zachhardesty7/tamper-monkey-scripts-collection/raw/master/verse-ibm-select-next-email.user.js
  11. // @homepageURL https://openuserjs.org/scripts/zachhardesty7/IBM_Verse_-_Auto-Select_Next_Email
  12. // @supportURL https://openuserjs.org/scripts/zachhardesty7/IBM_Verse_-_Auto-Select_Next_Email/issues
  13.  
  14.  
  15. // @include https://mail.notes.na.collabserv.com/verse*
  16. // @require https://greasyfork.org/scripts/419640-onelementready/code/onElementReady.js?version=887637
  17. // ==/UserScript==
  18. /* global onElementReady */
  19.  
  20. /**
  21. * the email that should be active after active email is deleted or archived
  22. *
  23. * @type {HTMLElement}
  24. */
  25. let nextEmail = null
  26.  
  27. /**
  28. * safely move to next email
  29. *
  30. * will trigger the click function to find the next email
  31. *
  32. * @param {string} description - message to log
  33. * @returns {(event: Event) => void} - function to be called
  34. */
  35. const clickNextEmail = (description) => (event) => {
  36. console.log(`clicked ${description}`)
  37. nextEmail && nextEmail.click()
  38. }
  39.  
  40. /**
  41. * @param {HTMLElement} el - input
  42. * @returns {boolean} whether or not the input is the last email
  43. */
  44. const isLastEmail = (el) =>
  45. !el.nextElementSibling || el.nextElementSibling.tagName === "SPAN"
  46.  
  47. window.addEventListener(
  48. "load",
  49. () => {
  50. // heading buttons
  51. onElementReady("button.action.pim-delete.icon", {}, (button) => {
  52. // trigger on click heading del
  53. button.addEventListener("click", clickNextEmail("header del"), {
  54. once: true,
  55. })
  56. })
  57.  
  58. onElementReady("li.seq-msg-row", { findOnce: true }, (clickedEmail) => {
  59. // trigger on click inline archive
  60. clickedEmail
  61. .querySelector("button.triage-action.remove")
  62. .addEventListener("click", clickNextEmail("inline archive"), {
  63. once: true,
  64. })
  65.  
  66. // trigger on click inline delete
  67. clickedEmail
  68. .querySelector("button.triage-action.delete")
  69. .addEventListener("click", clickNextEmail("inline del"), {
  70. once: true,
  71. })
  72.  
  73. // find next email
  74. // also triggered on calling `clickNextEmail`
  75. clickedEmail.addEventListener("click", (e) => {
  76. const targetEl = /** @type {HTMLElement} */ (e.target)
  77.  
  78. /** subtract out the invisible span element from the total sibling count */
  79. const emailCount = clickedEmail.parentElement.childElementCount - 1
  80.  
  81. // don't update if user clicked on an inline button icon
  82. // `clickNextEmail` handles to prevent double click
  83. if (targetEl.tagName === "svg" || targetEl.tagName === "rect") return
  84.  
  85. if (emailCount < 2) return
  86.  
  87. if (isLastEmail(clickedEmail))
  88. nextEmail = clickedEmail.previousElementSibling
  89. // when second-to-last is also first email
  90. else if (emailCount === 2) nextEmail = clickedEmail.nextElementSibling
  91. // when second-to-last and many emails visible
  92. else if (isLastEmail(clickedEmail.nextElementSibling))
  93. nextEmail = clickedEmail.previousElementSibling
  94. else nextEmail = clickedEmail.nextElementSibling
  95. })
  96. })
  97. },
  98. false
  99. )