You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

58 lines
2.0 KiB

  1. 'use strict';
  2. import * as fs from 'fs';
  3. import { Uri } from 'vscode';
  4. import { GravatarDefaultStyle } from './config';
  5. import { Strings } from './system';
  6. import { ContactPresenceStatus } from './vsls/vsls';
  7. import { Container } from './container';
  8. const avatarCache = new Map<string, Uri>();
  9. const missingGravatarHash = '00000000000000000000000000000000';
  10. const presenceCache = new Map<ContactPresenceStatus, string>();
  11. const gitHubNoReplyAddressRegex = /^(?:(?<userId>\d+)\+)?(?<userName>[a-zA-Z\d-]{1,39})@users.noreply.github.com$/;
  12. export function clearAvatarCache() {
  13. avatarCache.clear();
  14. }
  15. function getAvatarUriFromGitHubNoReplyAddress(email: string | undefined, size: number = 16): Uri | undefined {
  16. if (email == null || email.length === 0) return undefined;
  17. const match = gitHubNoReplyAddressRegex.exec(email);
  18. if (match == null) return undefined;
  19. const [, userId, userName] = match;
  20. return Uri.parse(`https://avatars.githubusercontent.com/${userId ? `u/${userId}` : userName}?size=${size}`);
  21. }
  22. export function getAvatarUri(email: string | undefined, fallback: GravatarDefaultStyle, size: number = 16): Uri {
  23. const hash =
  24. email != null && email.length !== 0 ? Strings.md5(email.trim().toLowerCase(), 'hex') : missingGravatarHash;
  25. const key = `${hash}:${size}`;
  26. let avatar = avatarCache.get(key);
  27. if (avatar !== undefined) return avatar;
  28. avatar =
  29. getAvatarUriFromGitHubNoReplyAddress(email, size) ||
  30. Uri.parse(`https://www.gravatar.com/avatar/${hash}.jpg?s=${size}&d=${fallback}`);
  31. avatarCache.set(key, avatar);
  32. return avatar;
  33. }
  34. export function getPresenceDataUri(status: ContactPresenceStatus) {
  35. let dataUri = presenceCache.get(status);
  36. if (dataUri === undefined) {
  37. const contents = fs
  38. .readFileSync(Container.context.asAbsolutePath(`images/dark/icon-presence-${status}.svg`))
  39. .toString('base64');
  40. dataUri = encodeURI(`data:image/svg+xml;base64,${contents}`);
  41. presenceCache.set(status, dataUri);
  42. }
  43. return dataUri;
  44. }