Skip to content
Snippets Groups Projects
Unverified Commit 130a6fcf authored by Murtaza Patrawala's avatar Murtaza Patrawala Committed by GitHub
Browse files

Regression: Fix app icons breaking UI (#26278)

parent b7012da1
No related branches found
No related tags found
No related merge requests found
......@@ -18,20 +18,27 @@ const OmnichannelRoomIcon = new (class extends Emitter {
if (this.icons.has(`${appId}-${icon}`)) {
return `${appId}-${icon}`;
}
APIClient.get(`/apps/public/${appId}/get-sidebar-icon`, { icon }).then((response: any) => {
this.icons.set(
`${appId}-${icon}`,
DOMPurify.sanitize(response, {
FORBID_ATTR: ['id'],
NAMESPACE: 'http://www.w3.org/2000/svg',
USE_PROFILES: { svg: true, svgFilters: true },
})
.replace(`<svg`, `<symbol id="${appId}-${icon}"`)
.replace(`</svg>`, '</symbol>'),
);
this.emit('change');
this.emit(`${appId}-${icon}`);
});
// TODO: update the apps icons to send JSON instead of a string. This will allow us to use APIClient.get()
APIClient.send(`/apps/public/${appId}/get-sidebar-icon?icon=${icon}`, 'GET')
.then((response: any) => {
response.text().then((text: any) => {
this.icons.set(
`${appId}-${icon}`,
DOMPurify.sanitize(text, {
FORBID_ATTR: ['id'],
NAMESPACE: 'http://www.w3.org/2000/svg',
USE_PROFILES: { svg: true, svgFilters: true },
})
.replace(`<svg`, `<symbol id="${appId}-${icon}"`)
.replace(`</svg>`, '</symbol>'),
);
this.emit('change');
this.emit(`${appId}-${icon}`);
});
})
.catch((error: any) => {
console.error('error from get-sidebar-icon', error);
});
}
})();
......
......@@ -24,34 +24,55 @@ export const OmnichannelRoomIconProvider: FC = ({ children }) => {
return (
<OmnichannelRoomIconContext.Provider
value={useMemo(
() => ({
value={useMemo(() => {
const extractSnapshot = (app: string, iconName: string): AsyncState<string> => {
const icon = OmnichannelRoomIcon.get(app, iconName);
if (icon) {
return {
phase: AsyncStatePhase.RESOLVED,
value: icon,
error: undefined,
};
}
return {
phase: AsyncStatePhase.LOADING,
value: undefined,
error: undefined,
};
};
// We cache all the icons here, so that we can use them in the OmnichannelRoomIcon component
const snapshots = new Map<string, AsyncState<string>>();
return {
queryIcon: (
app: string,
iconName: string,
): [subscribe: (onStoreChange: () => void) => () => void, getSnapshot: () => AsyncState<string>] => [
(callback): (() => void) => OmnichannelRoomIcon.on(`${app}-${iconName}`, callback),
(callback): (() => void) =>
OmnichannelRoomIcon.on(`${app}-${iconName}`, () => {
snapshots.set(`${app}-${iconName}`, extractSnapshot(app, iconName));
// Then we call the callback (onStoreChange), signaling React to re-render
callback();
}),
// No problem here, because it's return value is a cached in the snapshots map on subsequent calls
(): AsyncState<string> => {
const icon = OmnichannelRoomIcon.get(app, iconName);
let snapshot = snapshots.get(`${app}-${iconName}`);
if (!icon) {
return {
phase: AsyncStatePhase.LOADING,
value: undefined,
error: undefined,
};
if (!snapshot) {
snapshot = extractSnapshot(app, iconName);
snapshots.set(`${app}-${iconName}`, snapshot);
}
return {
phase: AsyncStatePhase.RESOLVED,
value: icon,
error: undefined,
};
return snapshot;
},
],
}),
[],
)}
};
}, [])}
>
{createPortal(
<svg
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment