Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/org avatar rendering #4

Merged
merged 12 commits into from
Jan 24, 2024
Prev Previous commit
Next Next commit
refactor: code deduplication
Abstract the avatar fetching, caching, and error handling into a single function.
  • Loading branch information
0x4007 committed Jan 24, 2024
commit e54d162fc819725a4c902ebc9682a4e6ed9ae5aa
44 changes: 3 additions & 41 deletions src/home/fetch-github/fetch-and-display-previews.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Octokit } from "@octokit/rest";
import { getGitHubAccessToken } from "../getters/get-github-access-token";
import { getImageFromDB, saveImageToDB } from "../getters/get-indexed-db";
import { getImageFromDB } from "../getters/get-indexed-db";
import { getLocalStore } from "../getters/get-local-store";
import { GitHubIssue } from "../github-types";
import { renderGitHubIssues } from "../rendering/render-github-issues";
import { Sorting } from "../sorting/generate-sorting-buttons";
import { sortIssuesController } from "../sorting/sort-issues-controller";
import { fetchAvatar } from "./fetch-avatar";
import { organizationImageCache } from "./fetch-issues-full";
import { fetchIssuePreviews } from "./fetch-issues-preview";

@@ -29,44 +28,7 @@ export async function fetchAndDisplayPreviews(sorting?: Sorting, options = { ord
const match = issue.body.match(urlPattern);
const orgName = match?.groups?.org;
if (orgName) {
// Check local cache first
const cachedAvatar = organizationImageCache.find((entry) => entry[orgName] !== undefined);
if (cachedAvatar) {
return Promise.resolve();
}

// If not in local cache, check IndexedDB
const avatarBlob = await getImageFromDB({ dbName: "ImageDatabase", storeName: "ImageStore", orgName: `avatarUrl-${orgName}` });
if (avatarBlob) {
// If the avatar Blob is found in IndexedDB, add it to the cache
organizationImageCache.push({ [orgName]: avatarBlob });
return Promise.resolve();
}

// If not in IndexedDB, fetch from network
const octokit = new Octokit({ auth: getGitHubAccessToken() });
return octokit.rest.orgs
.get({ org: orgName })
.then(async ({ data: { avatar_url: avatarUrl } }) => {
if (avatarUrl) {
// Fetch the image as a Blob and save it to IndexedDB
await fetch(avatarUrl)
.then((response) => response.blob())
.then(async (blob) => {
await saveImageToDB({
dbName: "ImageDatabase",
storeName: "ImageStore",
keyName: "name",
orgName: `avatarUrl-${orgName}`,
avatarBlob: blob,
});
organizationImageCache.push({ [orgName]: blob });
});
}
})
.catch((error) => {
console.error(`Failed to fetch avatar for organization ${orgName}: ${error}`);
});
return fetchAvatar(orgName);
}
return Promise.resolve();
});
45 changes: 45 additions & 0 deletions src/home/fetch-github/fetch-avatar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Octokit } from "@octokit/rest";
import { getGitHubAccessToken } from "../getters/get-github-access-token";
import { getImageFromDB, saveImageToDB } from "../getters/get-indexed-db";
import { organizationImageCache } from "./fetch-issues-full";

export async function fetchAvatar(orgName: string) {
// Check local cache first
const cachedAvatar = organizationImageCache.find((entry) => entry[orgName] !== undefined);
if (cachedAvatar) {
return Promise.resolve();
}

// If not in local cache, check IndexedDB
const avatarBlob = await getImageFromDB({ dbName: "ImageDatabase", storeName: "ImageStore", orgName: `avatarUrl-${orgName}` });
if (avatarBlob) {
// If the avatar Blob is found in IndexedDB, add it to the cache
organizationImageCache.push({ [orgName]: avatarBlob });
return Promise.resolve();
}

// If not in IndexedDB, fetch from network
const octokit = new Octokit({ auth: getGitHubAccessToken() });
return octokit.rest.orgs
.get({ org: orgName })
.then(async ({ data: { avatar_url: avatarUrl } }) => {
if (avatarUrl) {
// Fetch the image as a Blob and save it to IndexedDB
await fetch(avatarUrl)
.then((response) => response.blob())
.then(async (blob) => {
await saveImageToDB({
dbName: "ImageDatabase",
storeName: "ImageStore",
keyName: "name",
orgName: `avatarUrl-${orgName}`,
avatarBlob: blob,
});
organizationImageCache.push({ [orgName]: blob });
});
}
})
.catch((error) => {
console.error(`Failed to fetch avatar for organization ${orgName}: ${error}`);
});
}
29 changes: 3 additions & 26 deletions src/home/fetch-github/fetch-issues-full.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Octokit } from "@octokit/rest";
import { getGitHubAccessToken } from "../getters/get-github-access-token";
import { saveImageToDB } from "../getters/get-indexed-db";
import { getLocalStore } from "../getters/get-local-store";
import { GitHubIssue } from "../github-types";
import { fetchAvatar } from "./fetch-avatar";
import { PreviewToFullMapping } from "./preview-to-full-mapping";

export const previewToFullMapping = new PreviewToFullMapping().getMapping();
@@ -40,34 +40,11 @@ export function fetchIssuesFull(previews: GitHubIssue[]) {
localStorage.setItem("gitHubIssuesFull", JSON.stringify(Array.from(previewToFullMapping.entries())));
return { full, issueElement };
})
.then(({ full }) => {
.then(async ({ full }) => {
const urlMatch = full.html_url.match(urlPattern);
const orgName = urlMatch?.groups?.org;

if (orgName) {
const orgCacheEntry = organizationImageCache.find((entry) => entry[orgName] !== undefined);
if (orgCacheEntry) {
return; // no redundant requests
} else {
organizationImageCache.push({ [orgName]: null });
}
return octokit.rest.orgs.get({ org: orgName }).then(({ data }) => {
const avatarUrl = data.avatar_url;
// Fetch the image as a Blob and save it to IndexedDB
return fetch(avatarUrl)
.then((response) => response.blob())
.then(async (blob) => {
await saveImageToDB({
dbName: "ImageDatabase",
storeName: "ImageStore",
keyName: "name",
orgName: `avatarUrl-${orgName}`,
avatarBlob: blob,
});
organizationImageCache.push({ [orgName]: blob });
return full;
});
});
await fetchAvatar(orgName);
}
return full;
});