Skip to content

Commit 079f912

Browse files
committed
Add GitHub Ultimate Extension with caching, token management, and dark mode support and a lots of more features!
1 parent cdde804 commit 079f912

19 files changed

+1721
-0
lines changed

app.js

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import { fetchAllRepos } from './utils/repos/repoUtils.js';
2+
import { getTokens } from './utils/storage.js';
3+
import { displayPullRequests} from './utils/pulls.js';
4+
import { displayRepos } from './utils/repos/repo.js';
5+
import { displayIssues } from './utils/issues/issues.js';
6+
import { displayRecommendedIssues } from './utils/issues/recommendations.js';
7+
import { toggleDarkMode, initDarkMode } from './utils/theme.js';
8+
import { initStars } from './utils/stars.js';
9+
10+
export let repoCurrentPage = 1;
11+
export const repoItemsPerPage = 10;
12+
13+
function initAccordions() {
14+
document.querySelectorAll('.accordion-header').forEach(header => {
15+
header.addEventListener('click', () => {
16+
const targetId = header.getAttribute('data-target');
17+
const content = document.getElementById(targetId);
18+
19+
// Toggle open class
20+
header.classList.toggle('open');
21+
content.classList.toggle('open');
22+
});
23+
});
24+
}
25+
26+
document.addEventListener('DOMContentLoaded', async () => {
27+
const menuTrigger = document.getElementById('menuTrigger');
28+
const floatingMenu = document.querySelector('.floating-menu');
29+
const menuItems = document.querySelectorAll('.floating-menu-item');
30+
31+
if (menuTrigger && floatingMenu) {
32+
menuTrigger.addEventListener('mouseover', (e) => {
33+
e.preventDefault();
34+
e.stopPropagation();
35+
floatingMenu.classList.add('active');
36+
});
37+
38+
menuTrigger.addEventListener('mouseout', (e) => {
39+
e.preventDefault();
40+
e.stopPropagation();
41+
floatingMenu.classList.remove('active');
42+
});
43+
44+
// Prevent menu items from closing the menu when hovered
45+
menuItems.forEach(item => {
46+
item.addEventListener('mouseover', (e) => {
47+
e.stopPropagation();
48+
floatingMenu.classList.add('active');
49+
});
50+
51+
item.addEventListener('mouseout', (e) => {
52+
e.stopPropagation();
53+
floatingMenu.classList.remove('active');
54+
});
55+
});
56+
57+
// Close menu when mouse leaves the floating menu
58+
floatingMenu.addEventListener('mouseleave', (e) => {
59+
floatingMenu.classList.remove('active');
60+
});
61+
}
62+
63+
// Refresh all button functionality
64+
const refreshAllButton = document.getElementById('refreshAllButton');
65+
66+
refreshAllButton.addEventListener('click', async () => {
67+
refreshAllButton.disabled = true;
68+
try {
69+
await Promise.all([
70+
displayPullRequests(),
71+
displayIssues(),
72+
displayRepos(),
73+
displayRecommendedIssues()
74+
]);
75+
} finally {
76+
refreshAllButton.disabled = false;
77+
floatingMenu.classList.remove('active');
78+
}
79+
});
80+
// Initialize accordions
81+
initAccordions();
82+
83+
// Initialize new features
84+
initDarkMode();
85+
// Add dark mode toggle listener
86+
const darkModeToggle = document.getElementById('darkModeToggle');
87+
if (darkModeToggle) {
88+
darkModeToggle.addEventListener('click', toggleDarkMode);
89+
}
90+
await displayRepos();
91+
await displayPullRequests();
92+
await displayIssues();
93+
await initStars();
94+
95+
// Update floating menu initialization
96+
97+
// Add search event listeners
98+
const searchInput = document.getElementById('repoSearch');
99+
const searchType = document.getElementById('searchType');
100+
const refreshButton = document.getElementById('refreshButton');
101+
102+
if (refreshButton) {
103+
refreshButton.addEventListener('click', async () => {
104+
refreshButton.disabled = true;
105+
refreshButton.textContent = 'Refreshing...';
106+
try {
107+
await Promise.all([
108+
displayPullRequests(),
109+
displayIssues(),
110+
displayRepos()
111+
]);
112+
} finally {
113+
refreshButton.disabled = false;
114+
refreshButton.textContent = 'Refresh';
115+
}
116+
});
117+
}
118+
if (searchInput && searchType) {
119+
let debounceTimeout;
120+
searchInput.addEventListener('input', () => {
121+
clearTimeout(debounceTimeout);
122+
debounceTimeout = setTimeout(() => {
123+
repoCurrentPage = 1; // Reset to first page
124+
displayRepos();
125+
}, 300); // Debounce for 300ms
126+
});
127+
128+
searchType.addEventListener('change', () => {
129+
repoCurrentPage = 1; // Reset to first page
130+
displayRepos();
131+
});
132+
}
133+
});
134+
135+
const repoPrevPageButton = document.getElementById('repo_prevPage');
136+
if (repoPrevPageButton) {
137+
repoPrevPageButton.addEventListener('click', () => {
138+
if (repoCurrentPage > 1) {
139+
repoCurrentPage--;
140+
displayRepos();
141+
}
142+
});
143+
}
144+
145+
const repoNextPageButton = document.getElementById('repo_nextPage');
146+
if (repoNextPageButton) {
147+
repoNextPageButton.addEventListener('click', async () => {
148+
const tokens = await getTokens();
149+
const repos = await fetchAllRepos(tokens, 'all');
150+
const totalPages = Math.max(1, Math.ceil(repos.length / repoItemsPerPage));
151+
152+
if (repoCurrentPage < totalPages) {
153+
repoCurrentPage++;
154+
displayRepos();
155+
}
156+
});
157+
}

background.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// ...existing code...
2+
async function getUserData() {
3+
chrome.storage.local.get('githubTokens', async (result) => {
4+
const tokens = result.githubTokens || {};
5+
for (const token of Object.values(tokens)) {
6+
const response = await fetch('https://api.github.com/user', {
7+
headers: {
8+
'Authorization': `token ${token}`
9+
}
10+
});
11+
const data = await response.json();
12+
chrome.storage.local.set({ userData: data }, () => {
13+
console.log('User data saved.');
14+
});
15+
}
16+
});
17+
}
18+
19+
getUserData();
20+
chrome.action.onClicked.addListener(() => {
21+
chrome.tabs.create({ url: 'index.html' });
22+
});

images/icon128.png

2.6 KB
Loading

images/icon16.png

326 Bytes
Loading

images/icon48.png

695 Bytes
Loading

0 commit comments

Comments
 (0)