91271bca6e5658924cae13be66213d26f3cea2ba
[idea/community.git] / plugins / space / src / main / kotlin / com / intellij / space / components / SpaceUserAvatarProvider.kt
1 // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.space.components
3
4 import circlet.client.api.englishFullName
5 import circlet.platform.client.ConnectionStatus
6 import com.intellij.openapi.Disposable
7 import com.intellij.openapi.components.Service
8 import com.intellij.openapi.components.service
9 import com.intellij.space.ui.SpaceAvatarUtils
10 import com.intellij.space.ui.SpaceAvatars
11 import com.intellij.space.ui.SpaceImageLoader
12 import kotlinx.coroutines.CancellationException
13 import libraries.coroutines.extra.LifetimeSource
14 import libraries.klogging.logger
15 import runtime.reactive.Property
16 import runtime.reactive.awaitFirst
17 import runtime.reactive.filter
18 import runtime.reactive.mapInit
19
20 @Service
21 class SpaceUserAvatarProvider : Disposable {
22   private val log = logger<SpaceUserAvatarProvider>()
23
24   private val lifetime: LifetimeSource = LifetimeSource()
25
26   private val avatarPlaceholders: SpaceAvatars = SpaceAvatars.MainIcon
27
28   val avatars: Property<SpaceAvatars> = lifetime.mapInit(SpaceWorkspaceComponent.getInstance().workspace, avatarPlaceholders) { ws ->
29     ws ?: return@mapInit avatarPlaceholders
30     val id = ws.me.value.username
31     val name = ws.me.value.englishFullName()
32
33     val avatarTID = ws.me.value.smallAvatar ?: return@mapInit SpaceAvatarUtils.generateAvatars(id, name)
34     val imageLoader = SpaceImageLoader.getInstance()
35
36     // await connected state before trying to load image.
37     ws.client.connectionStatus.filter { it is ConnectionStatus.Connected }.awaitFirst(ws.lifetime)
38
39     try {
40       log.info { "loading user avatar: $avatarTID" }
41       val loadedImage = imageLoader.loadImageAsync(avatarTID)?.await()
42       if (loadedImage == null) {
43         SpaceAvatarUtils.generateAvatars(id, name)
44       }
45       else {
46         SpaceAvatarUtils.createAvatars(loadedImage)
47       }
48     }
49     catch (th: CancellationException) {
50       throw th
51     }
52     catch (e: Exception) {
53       log.error { "user avatar not loaded: $e" }
54       avatarPlaceholders
55     }
56   }
57
58   override fun dispose() {
59     lifetime.terminate()
60   }
61
62   companion object {
63     fun getInstance(): SpaceUserAvatarProvider = service()
64   }
65 }
66