-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathgithub-my-issues.user.ts
More file actions
149 lines (122 loc) · 4.18 KB
/
Copy pathgithub-my-issues.user.ts
File metadata and controls
149 lines (122 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// ==UserScript==
// @name GitHub My Issues
// @description Add a contextual link to issues you've contributed to on GitHub
// @author chocolateboy
// @copyright chocolateboy
// @version 3.1.0
// @namespace https://github.com/chocolateboy/userscripts
// @license GPL
// @include https://github.com/
// @include https://github.com/*
// @require https://cdn.jsdelivr.net/npm/cash-dom@8.1.5/dist/cash.min.js
// @grant GM_addStyle
// ==/UserScript==
import { observe } from './lib/observer.js'
/*
* unique ID for the "My Issues" link element
*/
const ID = 'my-issues-link'
/*
* selector for the "Issues" link. we navigate up from this to its parent
* tab, which we clone the "My Issues" tab from and append to.
*/
const ISSUES_LINK = 'a[data-react-nav="issues-react"]'
/*
* text of the "My Issues" link
*/
const MY_ISSUES = 'My Issues'
/*
* selector for the added "My Issues" link. used to identify an existing link so
* it can be reused for SPA navigation
*/
const MY_ISSUES_LINK = `a#${ID}`
/*
* return true if we're on the "My Issues" page, false otherwise.
*/
const pageIsMyIssues = (issuesPath: string, myIssues: string): boolean => {
if (location.pathname === issuesPath) { // "Issues" or "My Issues"
const q = URL.parse(location.href)!.searchParams.get('q')
return !!q && q.trim().split(/\s+/).includes(myIssues)
}
return false
}
/*
* add/restore the "My Issues" link
*/
const addLink = () => {
const $issuesLink = $<HTMLAnchorElement>(`li > ${ISSUES_LINK}`)
if ($issuesLink.length !== 1) {
console.debug('no issues link:', $issuesLink.length)
return
}
const $issuesTab = $issuesLink.closest('li')
const self = $('meta[name="user-login"]').attr('content')
if (!self) {
console.debug('no logged-in user')
return
}
const [user, repo] = location.pathname.slice(1).split('/')
if (!(repo && user)) {
console.debug('no user/repo')
return
}
const myIssues = `involves:${self}`
const issuesPath = `/${user}/${repo}/issues`
let $myIssuesLink = $<HTMLAnchorElement>(`li > ${MY_ISSUES_LINK}`)
// create it if it doesn't exist yet/has been removed
if ($myIssuesLink.length === 0) {
console.debug('adding My Issues tab')
const $myIssuesTab = $issuesTab.clone()
const subqueries = [myIssues, 'sort:updated-desc']
if (user === self) { // own repo
// state:open archived:false involves:<self> ...
subqueries.unshift('state:open', 'archived:false')
}
const query = subqueries.join('+')
const href = `${issuesPath}?q=${escape(query)}`
$myIssuesLink = $myIssuesTab.find<HTMLAnchorElement>(`:scope ${ISSUES_LINK}`)
$myIssuesLink
.removeClass('deselected')
.attr({
id: ID,
role: 'tab',
href,
'aria-current': null,
'data-hotkey': 'g I',
'data-react-nav': null,
'data-selected-links': null,
'data-tab-item': 'my-issues',
})
$myIssuesLink.find(':scope [data-content="Issues"]').text(MY_ISSUES)
$myIssuesLink.find(':scope [data-component="counter"]').hide()
$issuesTab.after($myIssuesTab)
}
updateLink(issuesPath, myIssues, $issuesLink, $myIssuesLink)
}
/*
* update the "Issues" and "My Issues" tabs to reflect the current page
*/
const updateLink = (
issuesPath: string,
myIssues: string,
$issuesLink: JQuery<HTMLAnchorElement>,
$myIssuesLink: JQuery<HTMLAnchorElement>,
) => {
if (pageIsMyIssues(issuesPath, myIssues)) { // "MyIssues"
$myIssuesLink.attr('aria-selected', 'true')
$issuesLink.addClass('deselected')
} else { // any other page, e.g. "Issues", "Pull requests", etc.
$myIssuesLink.attr('aria-selected', 'false')
$issuesLink.removeClass('deselected')
}
}
GM_addStyle(`
.deselected::after {
background: transparent !important;
}
`)
observe(document.documentElement, () => {
if (document.querySelector('[partial-name="global-nav-bar"].loaded')) {
addLink()
}
})