MCPcopy
hub / github.com/21st-dev/1code / useProjectIcon

Function useProjectIcon

src/renderer/lib/hooks/use-project-icon.ts:67–124  ·  view source on GitHub ↗
(project: ProjectIconData | null | undefined)

Source from the content-addressed store, hash-verified

65 * - No icon: returns null
66 */
67export function useProjectIcon(project: ProjectIconData | null | undefined): UseProjectIconResult {
68 const [src, setSrc] = useState<string | null>(null)
69 const [isLoading, setIsLoading] = useState(false)
70 const [hasError, setHasError] = useState(false)
71
72 useEffect(() => {
73 if (!project) {
74 setSrc(null)
75 setIsLoading(false)
76 setHasError(false)
77 return
78 }
79
80 let cancelled = false
81
82 if (project.iconPath) {
83 // Local file icon — fetch and cache as blob URL
84 const cached = fileIconCache.get(project.id)
85 if (cached) {
86 setSrc(cached)
87 setIsLoading(false)
88 setHasError(false)
89 return
90 }
91
92 setIsLoading(true)
93 setHasError(false)
94
95 const fileUrl = `file://${project.iconPath}?t=${project.updatedAt}`
96 fetchFileIcon(project.id, fileUrl).then((blobUrl) => {
97 if (cancelled) return
98 if (blobUrl) {
99 setSrc(blobUrl)
100 setHasError(false)
101 } else {
102 setSrc(null)
103 setHasError(true)
104 }
105 setIsLoading(false)
106 })
107 } else if (project.gitOwner && project.gitProvider === "github") {
108 // GitHub avatar — return direct URL, <img> handles loading/caching
109 setSrc(`https://github.com/${project.gitOwner}.png?size=64`)
110 setIsLoading(false)
111 setHasError(false)
112 } else {
113 setSrc(null)
114 setIsLoading(false)
115 setHasError(false)
116 }
117
118 return () => {
119 cancelled = true
120 }
121 }, [project?.id, project?.iconPath, project?.updatedAt, project?.gitOwner, project?.gitProvider])
122
123 return { src, isLoading, hasError }
124}

Callers 2

ProjectIconFunction · 0.90
ProjectDetailFunction · 0.90

Calls 2

fetchFileIconFunction · 0.85
getMethod · 0.45

Tested by

no test coverage detected