Skip to content

Commit 14db336

Browse files
committed
fix(app): flash of fallback icon for projects
1 parent 2b9b98e commit 14db336

3 files changed

Lines changed: 44 additions & 2 deletions

File tree

packages/app/src/components/dialog-edit-project.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export function DialogEditProject(props: { project: LocalProject }) {
8585
icon: { color: store.color, override: store.iconUrl },
8686
commands: { start },
8787
})
88+
globalSync.project.icon(props.project.worktree, store.iconUrl || undefined)
8889
setStore("saving", false)
8990
dialog.close()
9091
return

packages/app/src/context/global-sync.tsx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ type State = {
6161
command: Command[]
6262
project: string
6363
projectMeta: ProjectMeta | undefined
64+
icon: string | undefined
6465
provider: ProviderListResponse
6566
config: Config
6667
path: Path
@@ -107,6 +108,12 @@ type MetaCache = {
107108
ready: Accessor<boolean>
108109
}
109110

111+
type IconCache = {
112+
store: Store<{ value: string | undefined }>
113+
setStore: SetStoreFunction<{ value: string | undefined }>
114+
ready: Accessor<boolean>
115+
}
116+
110117
type ChildOptions = {
111118
bootstrap?: boolean
112119
}
@@ -119,19 +126,21 @@ function createGlobalSync() {
119126
if (!owner) throw new Error("GlobalSync must be created within owner")
120127
const vcsCache = new Map<string, VcsCache>()
121128
const metaCache = new Map<string, MetaCache>()
129+
const iconCache = new Map<string, IconCache>()
122130

123131
const [projectCache, setProjectCache, , projectCacheReady] = persisted(
124132
Persist.global("globalSync.project", ["globalSync.project.v1"]),
125133
createStore({ value: [] as Project[] }),
126134
)
127135

128136
const sanitizeProject = (project: Project) => {
129-
if (!project.icon?.url) return project
137+
if (!project.icon?.url && !project.icon?.override) return project
130138
return {
131139
...project,
132140
icon: {
133141
...project.icon,
134142
url: undefined,
143+
override: undefined,
135144
},
136145
}
137146
}
@@ -207,10 +216,20 @@ function createGlobalSync() {
207216
if (!meta) throw new Error("Failed to create persisted project metadata")
208217
metaCache.set(directory, { store: meta[0], setStore: meta[1], ready: meta[3] })
209218

219+
const icon = runWithOwner(owner, () =>
220+
persisted(
221+
Persist.workspace(directory, "icon", ["icon.v1"]),
222+
createStore({ value: undefined as string | undefined }),
223+
),
224+
)
225+
if (!icon) throw new Error("Failed to create persisted project icon")
226+
iconCache.set(directory, { store: icon[0], setStore: icon[1], ready: icon[3] })
227+
210228
const init = () => {
211229
const child = createStore<State>({
212230
project: "",
213231
projectMeta: meta[0].value,
232+
icon: icon[0].value,
214233
provider: { all: [], connected: [], default: {} },
215234
config: {},
216235
path: { state: "", config: "", worktree: "", directory: "", home: "" },
@@ -237,6 +256,10 @@ function createGlobalSync() {
237256
createEffect(() => {
238257
child[1]("projectMeta", meta[0].value)
239258
})
259+
260+
createEffect(() => {
261+
child[1]("icon", icon[0].value)
262+
})
240263
}
241264

242265
runWithOwner(owner, init)
@@ -811,6 +834,15 @@ function createGlobalSync() {
811834
setStore("projectMeta", next)
812835
}
813836

837+
function projectIcon(directory: string, value: string | undefined) {
838+
const [store, setStore] = ensureChild(directory)
839+
const cached = iconCache.get(directory)
840+
if (!cached) return
841+
if (store.icon === value) return
842+
cached.setStore("value", value)
843+
setStore("icon", value)
844+
}
845+
814846
return {
815847
data: globalStore,
816848
set: setGlobalStore,
@@ -833,6 +865,7 @@ function createGlobalSync() {
833865
project: {
834866
loadSessions,
835867
meta: projectMeta,
868+
icon: projectIcon,
836869
},
837870
}
838871
}

packages/app/src/context/layout.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
235235
...project,
236236
icon: {
237237
url: metadata?.icon?.url,
238-
override: metadata?.icon?.override,
238+
override: metadata?.icon?.override ?? childStore.icon,
239239
color: metadata?.icon?.color,
240240
},
241241
}
@@ -306,6 +306,14 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
306306
const projects = enriched()
307307
if (projects.length === 0) return
308308

309+
if (globalSync.ready) {
310+
for (const project of projects) {
311+
if (!project.id) continue
312+
if (project.id === "global") continue
313+
globalSync.project.icon(project.worktree, project.icon?.override)
314+
}
315+
}
316+
309317
const used = new Set<string>()
310318
for (const project of projects) {
311319
const color = project.icon?.color ?? colors[project.worktree]

0 commit comments

Comments
 (0)