Instantly share code, notes, and snippets.
Last activeMay 10, 2025 20:51
Save tinder-tannerbennett/7ab2091184dbad71f5387cca3960e65f to your computer and use it in GitHub Desktop.
Tampermonkey userscripts for github.com that I use for work
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| //@name pull/:id/files helpers (Approve PR) | |
| //@namespace http://tampermonkey.net/ | |
| //@version 1.0 | |
| //@description Automatically clicks the "Review Changes" and "Approve" buttons on key press (\) | |
| //@author Tanner Bennett | |
| //@match https://github.com/TinderApp/tinder_ios/pull/*/files | |
| //@icon https://www.google.com/s2/favicons?sz=64&domain=github.com | |
| //@grant none | |
| // ==/UserScript== | |
| (function(){ | |
| 'use strict'; | |
| functionclick(element){ | |
| if(element)element.click(); | |
| } | |
| document.addEventListener('keydown',function(event){ | |
| // Skip modifier keys | |
| if(event.ctrlKey||event.altKey||event.metaKey){ | |
| return; | |
| } | |
| // Abort if a text field is active | |
| if(event.target.tagName==='TEXTAREA'||event.target.tagName==='INPUT'){ | |
| return; | |
| } | |
| // Go to back to conversation | |
| if(event.key==='b'){ | |
| click(document.querySelector('a[href^="/TinderApp/tinder_ios/pull/"]')) | |
| } | |
| // Approve PR | |
| if(event.key==='\\'){ | |
| constbutton=document.getElementById('overlay-show-review-changes-modal'); | |
| if(button){ | |
| button.click(); | |
| constradio=document.getElementById('pull_request_review[event]_approve'); | |
| if(radio){ | |
| radio.click(); | |
| constbutton=document.querySelector('button.Button--primary.Button--small.Button.float-left'); | |
| if(button){ | |
| button.click(); | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| //@name pull/:id helpers | |
| //@namespace http://tampermonkey.net/ | |
| //@version 1.0 | |
| //@description Keyboard shortcuts for the GitHub PR page (pull/:id) | |
| //@author Tanner Bennett | |
| //@match https://github.com/TinderApp/tinder_ios/pull/* | |
| //@icon https://www.google.com/s2/favicons?sz=64&domain=github.com | |
| //@grant none | |
| // ==/UserScript== | |
| (function(){ | |
| 'use strict'; | |
| // A little jquery lite kinda API | |
| functionmatches(el,text){ | |
| returnel&&el.textContent.trim()===text; | |
| } | |
| function$(elOrSelector,selector){ | |
| lettarget=elOrSelector; | |
| // Case: only given a selector, use document | |
| if(typeofelOrSelector==='string'){ | |
| target=document; | |
| selector=elOrSelector; | |
| } | |
| // Case: given an object and a selector | |
| else{ | |
| selector=selector||''; | |
| } | |
| if(target.querySelector){ | |
| returntarget.querySelector(selector); | |
| } | |
| returnundefined; | |
| } | |
| functionfind(selector,where){ | |
| constlist=Array.from(document.querySelectorAll(selector)); | |
| returnwhere ?list.find(where) :list; | |
| } | |
| functionfindByText(selector,text){ | |
| returnfind(selector,el=>{ | |
| constinnerSpan=el.querySelector('span[data-component="text"]'); | |
| returnmatches(innerSpan,text); | |
| }); | |
| } | |
| functionfindByTextAll(selector,text){ | |
| returnArray.from(document.querySelectorAll(selector)).filter(el=>{ | |
| constinnerSpan=el.querySelector('span[data-component="text"]'); | |
| returninnerSpan&&innerSpan.textContent.trim()===text; | |
| }); | |
| } | |
| functiongh_buttonByInnerText(text){ | |
| returnfind('button span[data-component="text"]',btn=>matches(btn,text)); | |
| } | |
| functionclick(element){ | |
| if(element)element.click(); | |
| } | |
| functionscrollToEndOfPage(){ | |
| window.scrollTo(0,document.body.scrollHeight); | |
| } | |
| document.addEventListener('keydown',function(event){ | |
| // Skip modifier keys | |
| if(event.ctrlKey||event.altKey||event.metaKey){ | |
| return; | |
| } | |
| // Abort if a text field is active | |
| if(event.target.tagName==='TEXTAREA'||event.target.tagName==='INPUT'){ | |
| return; | |
| } | |
| // Ready for review / merge when ready | |
| // Press r repeatedly to hit each of the 3 buttons below | |
| if(event.key==='r'){ | |
| scrollToEndOfPage(); | |
| // Find the button by the inner text of the innermost span | |
| click(gh_buttonByInnerText('Ready for review')); | |
| click(gh_buttonByInnerText('Merge when ready')); | |
| click(gh_buttonByInnerText('Confirm merge when ready')); | |
| } | |
| // Go to changed files | |
| if(event.key==='f'){ | |
| click($('a[href$="/files"][href*="/pull/"]')) | |
| } | |
| // On shift + x, click "Close pull request" | |
| if(event.key==='X'){ | |
| scrollToEndOfPage(); | |
| click($('button[name="comment_and_close"]'));// Close pull request | |
| click(gh_buttonByInnerText('Delete branch')); | |
| } | |
| // Copy some text in this format: | |
| //@codeowner1 @codeowner2 | |
| // [PR title](PR URL) `+X -Y` | |
| if(event.key==='c'){ | |
| constprTitle=$('.js-issue-title.markdown-title'); | |
| constprUrl=window.location.href; | |
| constprDiffText=$('.diffstat').innerText.trim(); | |
| // Codeowners buttons look like this: | |
| /* <button name="button" type="button" id="codeowner-TinderApp/revenue-growth-ios" class="mr-2 btn-link muted-icon" aria-labelledby="tooltip-8cc9d586-5932-4bd5-9b62-4f9081d93b0e"> */ | |
| constcodeownersButtons=find('button[id^="codeowner-"]'); | |
| constcodeowners=Array.from(codeownersButtons).map(button=>{ | |
| constid=button.id; | |
| constcodeowner=id.split('TinderApp/')[1]; | |
| return`@${codeowner}`; | |
| }); | |
| // Copy to clipboard | |
| constmsg=`${codeowners.join(' ')}\n[${prTitle.innerText.trim()}](${prUrl}) \`${prDiffText}\``; | |
| navigator.clipboard.writeText(msg); | |
| console.log('Copied to clipboard:\n',msg); | |
| } | |
| }); | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| //@name SSO Helper | |
| //@namespace http://tampermonkey.net/ | |
| //@version 1.0 | |
| //@description Trigger the SSO 'Continue' button with any keypress | |
| //@author Tanner Bennett | |
| //@match https://github.com/TinderApp/tinder_ios/* | |
| //@icon https://www.google.com/s2/favicons?sz=64&domain=gotinder.com | |
| //@grant none | |
| // ==/UserScript== | |
| (function(){ | |
| 'use strict'; | |
| function$(elOrSelector,selector){ | |
| lettarget=elOrSelector; | |
| // Case: only given a selector, use document | |
| if(typeofelOrSelector==='string'){ | |
| target=document; | |
| selector=elOrSelector; | |
| } | |
| // Case: given an object and a selector | |
| else{ | |
| selector=selector||''; | |
| } | |
| if(target.querySelector){ | |
| returntarget.querySelector(selector); | |
| } | |
| returnundefined; | |
| } | |
| functionmatches(el,text){ | |
| returnel&&el.textContent.trim()===text; | |
| } | |
| functionfind(selector,where){ | |
| constlist=Array.from(document.querySelectorAll(selector)); | |
| returnwhere ?list.find(where) :list; | |
| } | |
| functiongh_buttonByInnerText(text){ | |
| returnfind('button',btn=>matches(btn,text)); | |
| } | |
| functionclick(element){ | |
| if(element)element.click(); | |
| } | |
| document.addEventListener('keydown',function(event){ | |
| // Skip modifier keys | |
| if(event.ctrlKey||event.altKey||event.metaKey){ | |
| return; | |
| } | |
| // Abort if a text field is active | |
| if(event.target.tagName==='TEXTAREA'||event.target.tagName==='INPUT'){ | |
| return; | |
| } | |
| // If we're on the SSO page, click continue on any key press | |
| if($('h1.sso-title')){ | |
| click(gh_buttonByInnerText('Continue')); | |
| } | |
| }); | |
| })(); |
Summary of Features
Continue with SSO Page
| Shortcut | Action |
|---|---|
| Any key | Presses the"Continue" button |
/pull/XXXXX
| Shortcut | Action |
|---|---|
| R | Click"Ready for review" (1) |
| R | Click"Merge when ready" (2) |
| R | Click"Confirm merge when ready" (3) |
| F | Navigate to the"Changed Files" tab |
| C | Copy a review request for#ios-code-review |
| shift + X | Click"Close pull request" (1) |
| shift + X | Click"Delete branch" (2) |
/pull/XXXXX/files
| Shortcut | Action |
|---|---|
| B | Navigate [B]ack to the"Conversation" tab |
| \ | Approve the pull request |
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment