Skip to content

Commit e54d162

Browse files
committed
refactor: code deduplication
Abstract the avatar fetching, caching, and error handling into a single function.
1 parent 49dedce commit e54d162

File tree

3 files changed

+51
-67
lines changed

3 files changed

+51
-67
lines changed

src/home/fetch-github/fetch-and-display-previews.ts

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import { Octokit } from "@octokit/rest";
2-
import { getGitHubAccessToken } from "../getters/get-github-access-token";
3-
import { getImageFromDB, saveImageToDB } from "../getters/get-indexed-db";
1+
import { getImageFromDB } from "../getters/get-indexed-db";
42
import { getLocalStore } from "../getters/get-local-store";
53
import { GitHubIssue } from "../github-types";
64
import { renderGitHubIssues } from "../rendering/render-github-issues";
75
import { Sorting } from "../sorting/generate-sorting-buttons";
86
import { sortIssuesController } from "../sorting/sort-issues-controller";
7+
import { fetchAvatar } from "./fetch-avatar";
98
import { organizationImageCache } from "./fetch-issues-full";
109
import { fetchIssuePreviews } from "./fetch-issues-preview";
1110

@@ -29,44 +28,7 @@ export async function fetchAndDisplayPreviews(sorting?: Sorting, options = { ord
2928
const match = issue.body.match(urlPattern);
3029
const orgName = match?.groups?.org;
3130
if (orgName) {
32-
// Check local cache first
33-
const cachedAvatar = organizationImageCache.find((entry) => entry[orgName] !== undefined);
34-
if (cachedAvatar) {
35-
return Promise.resolve();
36-
}
37-
38-
// If not in local cache, check IndexedDB
39-
const avatarBlob = await getImageFromDB({ dbName: "ImageDatabase", storeName: "ImageStore", orgName: `avatarUrl-${orgName}` });
40-
if (avatarBlob) {
41-
// If the avatar Blob is found in IndexedDB, add it to the cache
42-
organizationImageCache.push({ [orgName]: avatarBlob });
43-
return Promise.resolve();
44-
}
45-
46-
// If not in IndexedDB, fetch from network
47-
const octokit = new Octokit({ auth: getGitHubAccessToken() });
48-
return octokit.rest.orgs
49-
.get({ org: orgName })
50-
.then(async ({ data: { avatar_url: avatarUrl } }) => {
51-
if (avatarUrl) {
52-
// Fetch the image as a Blob and save it to IndexedDB
53-
await fetch(avatarUrl)
54-
.then((response) => response.blob())
55-
.then(async (blob) => {
56-
await saveImageToDB({
57-
dbName: "ImageDatabase",
58-
storeName: "ImageStore",
59-
keyName: "name",
60-
orgName: `avatarUrl-${orgName}`,
61-
avatarBlob: blob,
62-
});
63-
organizationImageCache.push({ [orgName]: blob });
64-
});
65-
}
66-
})
67-
.catch((error) => {
68-
console.error(`Failed to fetch avatar for organization ${orgName}: ${error}`);
69-
});
31+
return fetchAvatar(orgName);
7032
}
7133
return Promise.resolve();
7234
});

src/home/fetch-github/fetch-avatar.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Octokit } from "@octokit/rest";
2+
import { getGitHubAccessToken } from "../getters/get-github-access-token";
3+
import { getImageFromDB, saveImageToDB } from "../getters/get-indexed-db";
4+
import { organizationImageCache } from "./fetch-issues-full";
5+
6+
export async function fetchAvatar(orgName: string) {
7+
// Check local cache first
8+
const cachedAvatar = organizationImageCache.find((entry) => entry[orgName] !== undefined);
9+
if (cachedAvatar) {
10+
return Promise.resolve();
11+
}
12+
13+
// If not in local cache, check IndexedDB
14+
const avatarBlob = await getImageFromDB({ dbName: "ImageDatabase", storeName: "ImageStore", orgName: `avatarUrl-${orgName}` });
15+
if (avatarBlob) {
16+
// If the avatar Blob is found in IndexedDB, add it to the cache
17+
organizationImageCache.push({ [orgName]: avatarBlob });
18+
return Promise.resolve();
19+
}
20+
21+
// If not in IndexedDB, fetch from network
22+
const octokit = new Octokit({ auth: getGitHubAccessToken() });
23+
return octokit.rest.orgs
24+
.get({ org: orgName })
25+
.then(async ({ data: { avatar_url: avatarUrl } }) => {
26+
if (avatarUrl) {
27+
// Fetch the image as a Blob and save it to IndexedDB
28+
await fetch(avatarUrl)
29+
.then((response) => response.blob())
30+
.then(async (blob) => {
31+
await saveImageToDB({
32+
dbName: "ImageDatabase",
33+
storeName: "ImageStore",
34+
keyName: "name",
35+
orgName: `avatarUrl-${orgName}`,
36+
avatarBlob: blob,
37+
});
38+
organizationImageCache.push({ [orgName]: blob });
39+
});
40+
}
41+
})
42+
.catch((error) => {
43+
console.error(`Failed to fetch avatar for organization ${orgName}: ${error}`);
44+
});
45+
}

src/home/fetch-github/fetch-issues-full.ts

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Octokit } from "@octokit/rest";
22
import { getGitHubAccessToken } from "../getters/get-github-access-token";
3-
import { saveImageToDB } from "../getters/get-indexed-db";
43
import { getLocalStore } from "../getters/get-local-store";
54
import { GitHubIssue } from "../github-types";
5+
import { fetchAvatar } from "./fetch-avatar";
66
import { PreviewToFullMapping } from "./preview-to-full-mapping";
77

88
export const previewToFullMapping = new PreviewToFullMapping().getMapping();
@@ -40,34 +40,11 @@ export function fetchIssuesFull(previews: GitHubIssue[]) {
4040
localStorage.setItem("gitHubIssuesFull", JSON.stringify(Array.from(previewToFullMapping.entries())));
4141
return { full, issueElement };
4242
})
43-
.then(({ full }) => {
43+
.then(async ({ full }) => {
4444
const urlMatch = full.html_url.match(urlPattern);
4545
const orgName = urlMatch?.groups?.org;
46-
4746
if (orgName) {
48-
const orgCacheEntry = organizationImageCache.find((entry) => entry[orgName] !== undefined);
49-
if (orgCacheEntry) {
50-
return; // no redundant requests
51-
} else {
52-
organizationImageCache.push({ [orgName]: null });
53-
}
54-
return octokit.rest.orgs.get({ org: orgName }).then(({ data }) => {
55-
const avatarUrl = data.avatar_url;
56-
// Fetch the image as a Blob and save it to IndexedDB
57-
return fetch(avatarUrl)
58-
.then((response) => response.blob())
59-
.then(async (blob) => {
60-
await saveImageToDB({
61-
dbName: "ImageDatabase",
62-
storeName: "ImageStore",
63-
keyName: "name",
64-
orgName: `avatarUrl-${orgName}`,
65-
avatarBlob: blob,
66-
});
67-
organizationImageCache.push({ [orgName]: blob });
68-
return full;
69-
});
70-
});
47+
await fetchAvatar(orgName);
7148
}
7249
return full;
7350
});

0 commit comments

Comments
 (0)