mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
[settings-sync] IJPL-188452: Use combobox for account selector dropdown
- Account selector now follows the design - Add checkbox indicating selected account - Add provider icon - Handle logging out from an active account (disable sync and switch to another account) (cherry picked from commit 7549862a1acb9e902a636e0e98c26b45275bb49b) IJ-CR-174183 GitOrigin-RevId: c8aa48ab8325db9070442b2b80fd115c9d26bff9
This commit is contained in:
committed by
intellij-monorepo-bot
parent
3806d403d2
commit
9737a5e6c2
@@ -60,7 +60,7 @@ enable.dialog.change=Change
|
||||
enable.sync.check.server.data.progress=Checking server data\u2026
|
||||
enable.sync.get.from.server.progress=Getting Settings from Server\u2026
|
||||
enable.sync.push.to.server.progress=Pushing Settings to Server\u2026
|
||||
enable.sync.add.account=Add Account
|
||||
enable.sync.add.account=Add Account\u2026
|
||||
enable.sync.choose.data.provider.title=Choose Provider
|
||||
enable.sync.choose.data.provider.text=Please select a provider that will store and process your data.
|
||||
# {0} - name of the provider - JetBrains or Google
|
||||
@@ -82,7 +82,7 @@ status.action.settings.sync.is.off=Off
|
||||
status.action.settings.sync.is.on=On
|
||||
status.action.settings.sync.failed=Failed
|
||||
status.action.settings.sync.pending.action=Action Required
|
||||
logout.link.text=Log out {0} Account
|
||||
logout.link.text=Log Out {0} Account\u2026
|
||||
# logout.dialog.title=Confirm Log Out
|
||||
# logout.dialog.message=Are you sure you want to log out?
|
||||
# logout.dialog.button=Log Out
|
||||
|
||||
@@ -6,7 +6,6 @@ package com.intellij.settingsSync.core.config
|
||||
import com.intellij.BundleBase
|
||||
import com.intellij.CommonBundle
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.ide.DataManager
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil
|
||||
import com.intellij.openapi.application.EDT
|
||||
@@ -20,14 +19,11 @@ import com.intellij.openapi.options.BoundConfigurable
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import com.intellij.openapi.options.ConfigurableProvider
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
import com.intellij.openapi.ui.DialogPanel
|
||||
import com.intellij.openapi.ui.DialogWrapper
|
||||
import com.intellij.openapi.ui.MessageDialogBuilder.Companion.yesNo
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.ui.popup.JBPopup
|
||||
import com.intellij.openapi.ui.popup.ListSeparator
|
||||
import com.intellij.openapi.ui.popup.PopupStep
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.IntellijInternalApi
|
||||
import com.intellij.openapi.util.text.HtmlBuilder
|
||||
@@ -45,29 +41,25 @@ import com.intellij.settingsSync.core.communicator.SettingsSyncUserData
|
||||
import com.intellij.settingsSync.core.communicator.getAvailableSyncProviders
|
||||
import com.intellij.settingsSync.core.config.SettingsSyncEnabler.State
|
||||
import com.intellij.settingsSync.core.statistics.SettingsSyncEventsStatistics
|
||||
import com.intellij.ui.RelativeFont
|
||||
import com.intellij.ui.components.DropDownLink
|
||||
import com.intellij.ui.MutableCollectionComboBoxModel
|
||||
import com.intellij.ui.SimpleTextAttributes
|
||||
import com.intellij.ui.components.JBHtmlPane
|
||||
import com.intellij.ui.components.JBRadioButton
|
||||
import com.intellij.ui.dsl.builder.*
|
||||
import com.intellij.ui.dsl.builder.components.DslLabel
|
||||
import com.intellij.ui.dsl.builder.components.DslLabelType
|
||||
import com.intellij.ui.dsl.listCellRenderer.listCellRenderer
|
||||
import com.intellij.ui.dsl.gridLayout.UnscaledGaps
|
||||
import com.intellij.ui.layout.ComponentPredicate
|
||||
import com.intellij.ui.layout.and
|
||||
import com.intellij.ui.layout.not
|
||||
import com.intellij.ui.layout.selected
|
||||
import com.intellij.ui.popup.list.ListPopupImpl
|
||||
import com.intellij.ui.scale.JBUIScale.scale
|
||||
import com.intellij.util.Consumer
|
||||
import com.intellij.util.asDisposable
|
||||
import com.intellij.util.IconUtil
|
||||
import com.intellij.util.text.DateFormatUtil
|
||||
import com.intellij.util.ui.JBFont
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.NamedColorUtil
|
||||
import com.intellij.util.ui.StartupUiUtil.labelFont
|
||||
import kotlinx.coroutines.*
|
||||
import java.awt.event.ItemEvent
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import java.util.concurrent.CancellationException
|
||||
@@ -85,18 +77,21 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
|
||||
private lateinit var configPanel: DialogPanel
|
||||
private lateinit var enableCheckbox: JCheckBox
|
||||
private lateinit var cellDropDownLink: Cell<DropDownLink<UserProviderHolder?>>
|
||||
private lateinit var userDropDownLink: DropDownLink<UserProviderHolder?>
|
||||
|
||||
private val userAccountsList = arrayListOf<UserProviderHolder>()
|
||||
private var userAccountsLogout: UserProviderHolder? = null
|
||||
private val userComboBoxModel = MutableCollectionComboBoxModel<UserProviderHolder>()
|
||||
private var userProviderHolder: UserProviderHolder? = currentUser()
|
||||
private lateinit var cellUserComboBox: Cell<ComboBox<UserProviderHolder>>
|
||||
|
||||
private lateinit var syncTypeLabel: JBHtmlPane
|
||||
private lateinit var syncConfigPanel: DialogPanel
|
||||
|
||||
|
||||
private val syncEnabler = SettingsSyncEnabler()
|
||||
private val enableSyncOption = AtomicProperty<InitSyncType>(InitSyncType.GET_FROM_SERVER)
|
||||
private val disableSyncOption = AtomicProperty<DisableSyncType>(DisableSyncType.DISABLE)
|
||||
private val remoteSettingsExist = AtomicBooleanProperty(false)
|
||||
private val wasUsedBefore = AtomicBooleanProperty(currentUser() != null)
|
||||
private val userAccountsList = arrayListOf<UserProviderHolder>()
|
||||
private val userAccountListIsNotEmpty = AtomicBooleanProperty(false)
|
||||
private val syncPanelHolder = SettingsSyncPanelHolder()
|
||||
private val hasMultipleProviders = AtomicBooleanProperty(RemoteCommunicatorHolder.getExternalProviders().isNotEmpty())
|
||||
@@ -120,13 +115,19 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
SettingsSyncEvents.getInstance().removeListener(this)
|
||||
}
|
||||
|
||||
private fun currentUserId() = SettingsSyncLocalSettings.getInstance().userId
|
||||
|
||||
private fun currentUser(): UserProviderHolder? {
|
||||
val userId = SettingsSyncLocalSettings.getInstance().userId ?: return null
|
||||
val userId = currentUserId() ?: return null
|
||||
val providerCode = SettingsSyncLocalSettings.getInstance().providerCode ?: return null
|
||||
val authService = RemoteCommunicatorHolder.getProvider(providerCode)?.authService ?: return null
|
||||
return authService.getAvailableUserAccounts().find {
|
||||
it.id == userId
|
||||
}?.toUserProviderHolder(authService.providerName)
|
||||
it.id == userId
|
||||
}?.toUserProviderHolder(authService.providerName)
|
||||
}
|
||||
|
||||
private fun selectedUser(): UserProviderHolder? {
|
||||
return userComboBoxModel.selectedItem as? UserProviderHolder
|
||||
}
|
||||
|
||||
override fun createPanel(): DialogPanel {
|
||||
@@ -136,8 +137,11 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
|
||||
configPanel = panel {
|
||||
updateUserAccountsList()
|
||||
val userProviderHolder: UserProviderHolder? = currentUser() ?: userAccountsList.firstOrNull { it != UserProviderHolder.addAccount }
|
||||
val authService = userProviderHolder?.let { RemoteCommunicatorHolder.getProvider(userProviderHolder.providerCode) } ?.authService
|
||||
validateCurrentUser()
|
||||
updateUserAccountLogout(userProviderHolder)
|
||||
userComboBoxModel.selectedItem = userProviderHolder
|
||||
updateUserComboBoxModel()
|
||||
val authService = currentUser()?.let { RemoteCommunicatorHolder.getProvider(it.providerCode) } ?.authService
|
||||
syncPanelHolder.crossSyncSupported.set(authService?.crossSyncSupported() ?: true)
|
||||
val infoRow = row {
|
||||
@Suppress("DialogTitleCapitalization")
|
||||
@@ -188,22 +192,57 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
enableButtonAction()
|
||||
}
|
||||
infoRow.visibleIf(enableCheckbox.selected.not())
|
||||
userDropDownLink = DropDownLink<UserProviderHolder?>(userProviderHolder) { link: DropDownLink<UserProviderHolder?>? -> showAccounts(link) }
|
||||
cellDropDownLink = cell(userDropDownLink).onChangedContext { component, context ->
|
||||
val event = context.event
|
||||
if (event is ItemEvent && event.item == UserProviderHolder.addAccount) {
|
||||
val syncTypeDialog = AddAccountDialog(configPanel)
|
||||
if (syncTypeDialog.showAndGet()) {
|
||||
val providerCode = syncTypeDialog.providerCode
|
||||
val provider = RemoteCommunicatorHolder.getProvider(providerCode) ?: return@onChangedContext
|
||||
component.selectedItem = null
|
||||
component.text = ""
|
||||
login(provider, syncConfigPanel)
|
||||
|
||||
val listCellRenderer = listCellRenderer<UserProviderHolder>("") {
|
||||
val holder = value
|
||||
var icon2Apply = IconUtil.getEmptyIcon(false)
|
||||
when {
|
||||
holder.userId == UserProviderHolder.LOGOUT_USER_ID -> {
|
||||
separator { text = "" }
|
||||
text(message("logout.link.text", holder.providerName)) {
|
||||
attributes = SimpleTextAttributes.LINK_PLAIN_ATTRIBUTES.derive(
|
||||
SimpleTextAttributes.STYLE_PLAIN,
|
||||
JBUI.CurrentTheme.Link.Foreground.ENABLED,
|
||||
null,
|
||||
null
|
||||
)
|
||||
font = JBFont.medium()
|
||||
}
|
||||
}
|
||||
holder == UserProviderHolder.ADD_ACCOUNT -> {
|
||||
icon(icon2Apply)
|
||||
separator { text = "" }
|
||||
text(holder.toString())
|
||||
}
|
||||
else -> {
|
||||
if (index == -1) {
|
||||
RemoteCommunicatorHolder.getProvider(holder.providerCode)?.authService?.icon?.let {
|
||||
icon2Apply = it
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (index == 0 || holder.providerCode != userAccountsList[index - 1].providerCode) {
|
||||
separator { text = holder.providerName }
|
||||
}
|
||||
}
|
||||
if (index >= 0 && holder == userComboBoxModel.selectedItem) {
|
||||
icon2Apply = AllIcons.Actions.Checked
|
||||
}
|
||||
icon(icon2Apply)
|
||||
text(holder.toString())
|
||||
}
|
||||
} else {
|
||||
component.text = component.selectedItem.toString()
|
||||
}
|
||||
}.comment("", MAX_LINE_LENGTH_NO_WRAP)
|
||||
}
|
||||
|
||||
cellUserComboBox = comboBox(userComboBoxModel, listCellRenderer)
|
||||
.resizableColumn().align(AlignX.FILL)
|
||||
.comment("", 50)
|
||||
cellUserComboBox.whenItemSelectedFromUi { item ->
|
||||
if (item != userProviderHolder) {
|
||||
tryChangeAccount(item)
|
||||
}
|
||||
}
|
||||
|
||||
}.visibleIf(userAccountListIsNotEmpty)
|
||||
|
||||
// settings to sync
|
||||
@@ -249,26 +288,28 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
wasUsedBefore.set(currentUser() != null)
|
||||
hasMultipleProviders.set(RemoteCommunicatorHolder.getExternalProviders().isNotEmpty())
|
||||
enableCheckbox.isSelected = SettingsSyncSettings.getInstance().syncEnabled
|
||||
if (currentUser() != null) {
|
||||
userDropDownLink.selectedItem = userAccountsList.firstOrNull { it.userId == SettingsSyncLocalSettings.getInstance().userId}
|
||||
userProviderHolder = if (currentUser() != null) {
|
||||
userAccountsList.firstOrNull { it.userId == currentUserId() }
|
||||
} else if (userAccountListIsNotEmpty.get()) {
|
||||
userDropDownLink.selectedItem = userAccountsList.firstOrNull { it != UserProviderHolder.addAccount }
|
||||
userAccountsList.firstOrNull { it != UserProviderHolder.ADD_ACCOUNT }
|
||||
} else {
|
||||
userDropDownLink.selectedItem = null
|
||||
null
|
||||
}
|
||||
userComboBoxModel.selectedItem = userProviderHolder
|
||||
syncStatusChanged()
|
||||
}
|
||||
.onIsModified {
|
||||
enableCheckbox.isSelected != SettingsSyncSettings.getInstance().syncEnabled
|
||||
|| syncConfigPanel.isModified()
|
||||
|| (SettingsSyncLocalSettings.getInstance().userId != null && userDropDownLink.selectedItem?.userId != SettingsSyncLocalSettings.getInstance().userId)
|
||||
|| (currentUserId() != null && selectedUser()?.userId != currentUserId())
|
||||
}
|
||||
.onApply {
|
||||
val selectedUser = selectedUser()
|
||||
with(SettingsSyncLocalSettings.getInstance()) {
|
||||
userId = userDropDownLink.selectedItem?.userId
|
||||
providerCode = userDropDownLink.selectedItem?.providerCode
|
||||
userId = selectedUser?.userId
|
||||
providerCode = selectedUser?.providerCode
|
||||
}
|
||||
cellDropDownLink.comment?.text = ""
|
||||
cellUserComboBox.comment?.text = ""
|
||||
if (enableCheckbox.isSelected) {
|
||||
syncConfigPanel.apply()
|
||||
}
|
||||
@@ -349,7 +390,7 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
return
|
||||
}
|
||||
runWithModalProgressBlocking(ModalTaskOwner.component(configPanel), message("enable.sync.check.server.data.progress")) {
|
||||
val (userId, userData, providerCode, providerName) = userDropDownLink.selectedItem ?: run {
|
||||
val (userId, _, providerCode, providerName) = selectedUser() ?: run {
|
||||
LOG.warn("No selected user")
|
||||
showErrorOnEDT(message("enable.dialog.error.no.user"))
|
||||
enableCheckbox.isSelected = false
|
||||
@@ -372,7 +413,7 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
syncConfigPanel.reset()
|
||||
triggerUpdateConfigurable()
|
||||
}
|
||||
cellDropDownLink.comment?.text = "<icon src='AllIcons.General.History'> " +
|
||||
cellUserComboBox.comment?.text = "<icon src='AllIcons.General.History'> " +
|
||||
message("sync.status.will.enable",
|
||||
CommonBundle.getApplyButtonText().replace(BundleBase.MNEMONIC_STRING, ""))
|
||||
} else {
|
||||
@@ -384,7 +425,7 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
val syncDisableOption = showDisableSyncDialog()
|
||||
if (syncDisableOption != DisableSyncType.DONT_DISABLE) {
|
||||
disableSyncOption.set(syncDisableOption)
|
||||
cellDropDownLink.comment?.text = message("sync.status.will.disable")
|
||||
cellUserComboBox.comment?.text = message("sync.status.will.disable")
|
||||
handleDisableSync()
|
||||
} else {
|
||||
enableCheckbox.isSelected = true
|
||||
@@ -395,7 +436,7 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
}
|
||||
|
||||
private fun showDisableSyncDialog(): DisableSyncType {
|
||||
val providerName = userDropDownLink.selectedItem?.providerName ?: ""
|
||||
val providerName = selectedUser()?.providerName ?: ""
|
||||
val intResult = if (SettingsSyncStatusTracker.getInstance().currentStatus is SettingsSyncStatusTracker.SyncStatus.ActionRequired) {
|
||||
Messages.showDialog(
|
||||
message("disable.dialog.text", providerName),
|
||||
@@ -504,134 +545,121 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
syncTypeLabel.text = html.toString()
|
||||
}
|
||||
|
||||
private fun showAccounts(link: DropDownLink<UserProviderHolder?>?): JBPopup {
|
||||
val accounts = object : BaseListPopupStep<UserProviderHolder>() {
|
||||
private var stepSelectedValue: UserProviderHolder? = null
|
||||
override fun onChosen(selectedValue: UserProviderHolder, finalChoice: Boolean): PopupStep<*>? {
|
||||
stepSelectedValue = selectedValue
|
||||
return FINAL_CHOICE
|
||||
}
|
||||
|
||||
override fun getTextFor(value: UserProviderHolder?): String {
|
||||
return if (value == UserProviderHolder.addAccount) {
|
||||
message("enable.sync.add.account")
|
||||
private fun tryChangeAccount(selectedValue: UserProviderHolder) {
|
||||
when {
|
||||
selectedValue == UserProviderHolder.ADD_ACCOUNT -> {
|
||||
if (SettingsSyncSettings.getInstance().syncEnabled && !disableCurrentSyncDialog()) {
|
||||
userComboBoxModel.selectedItem = userProviderHolder
|
||||
return
|
||||
}
|
||||
val syncTypeDialog = AddAccountDialog(configPanel)
|
||||
if (syncTypeDialog.showAndGet()) {
|
||||
val providerCode = syncTypeDialog.providerCode
|
||||
val provider = RemoteCommunicatorHolder.getProvider(providerCode) ?: return
|
||||
login(provider, syncConfigPanel)
|
||||
}
|
||||
else {
|
||||
value?.toString() ?: ""
|
||||
userComboBoxModel.selectedItem = userProviderHolder
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSeparatorAbove(value: UserProviderHolder?): ListSeparator? {
|
||||
return value?.separatorString?.let { ListSeparator(it) }
|
||||
}
|
||||
|
||||
override fun getFinalRunnable(): Runnable? {
|
||||
if (stepSelectedValue != null) {
|
||||
return Runnable { tryChangeAccount(stepSelectedValue!!) }
|
||||
selectedValue.userId == UserProviderHolder.LOGOUT_USER_ID -> {
|
||||
val logoutFunction = userProviderHolder?.let { user ->
|
||||
val provider = RemoteCommunicatorHolder.getProvider(user.providerCode)
|
||||
provider?.authService?.logoutFunction
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
init {
|
||||
init(null, userAccountsList, emptyList())
|
||||
defaultOptionIndex = userAccountsList.indexOf(userDropDownLink.selectedItem)
|
||||
}
|
||||
}
|
||||
|
||||
val currentProviderCode = link?.selectedItem?.providerCode
|
||||
|
||||
val project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(configPanel))
|
||||
val provider = currentProviderCode?.let { RemoteCommunicatorHolder.getProvider(it ) }
|
||||
val logoutFunction = provider?.authService?.logoutFunction
|
||||
val listPopup = object : ListPopupImpl(project, accounts) {
|
||||
|
||||
override fun setFooterComponent(c: JComponent?) {
|
||||
val thePopup = this
|
||||
if (logoutFunction == null) {
|
||||
return super.setFooterComponent(c)
|
||||
}
|
||||
super.setFooterComponent(DslLabel(DslLabelType.LABEL).apply {
|
||||
text = "<a>${message("logout.link.text", provider.authService.providerName ?: "")}</a>"
|
||||
|
||||
addHyperlinkListener {
|
||||
if (it.eventType == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
thePopup.cancel()
|
||||
coroutineScope.launch(ModalityState.current().asContextElement()) {
|
||||
withContext(Dispatchers.EDT) {
|
||||
logoutFunction(configPanel)
|
||||
}
|
||||
}
|
||||
if (logoutFunction != null) {
|
||||
coroutineScope.launch(ModalityState.current().asContextElement()) {
|
||||
withContext(Dispatchers.EDT) {
|
||||
logoutFunction(configPanel)
|
||||
configPanel.reset()
|
||||
}
|
||||
}
|
||||
|
||||
foreground = JBUI.CurrentTheme.Advertiser.foreground()
|
||||
background = JBUI.CurrentTheme.Advertiser.background()
|
||||
|
||||
setOpaque(true)
|
||||
setFont(RelativeFont.NORMAL.scale(JBUI.CurrentTheme.Advertiser.FONT_SIZE_OFFSET.get(), scale(11f)).derive(labelFont))
|
||||
setBorder(JBUI.CurrentTheme.Advertiser.border())
|
||||
})
|
||||
}
|
||||
}
|
||||
if (currentProviderCode != null && logoutFunction != null) {
|
||||
listPopup.setAdText(message("logout.link.text", currentProviderCode)) // doesn't matter, will be changed
|
||||
}
|
||||
|
||||
return listPopup
|
||||
}
|
||||
|
||||
private fun tryChangeAccount(selectedValue: UserProviderHolder) {
|
||||
if (selectedValue == UserProviderHolder.addAccount) {
|
||||
if (SettingsSyncSettings.getInstance().syncEnabled && !disableCurrentSyncDialog()) {
|
||||
return
|
||||
}
|
||||
val syncTypeDialog = AddAccountDialog(configPanel)
|
||||
if (syncTypeDialog.showAndGet()) {
|
||||
val providerCode = syncTypeDialog.providerCode
|
||||
val provider = RemoteCommunicatorHolder.getProvider(providerCode) ?: return
|
||||
login(provider, syncConfigPanel)
|
||||
}
|
||||
}
|
||||
else {
|
||||
val wasEnabled = SettingsSyncSettings.getInstance().syncEnabled
|
||||
if (enableCheckbox.isSelected) {
|
||||
if (wasEnabled) {
|
||||
if (!disableCurrentSyncDialog()) {
|
||||
return
|
||||
}
|
||||
userDropDownLink.selectedItem = selectedValue
|
||||
enableCheckbox.doClick()
|
||||
} else {
|
||||
userDropDownLink.selectedItem = selectedValue
|
||||
enableButtonAction()
|
||||
userComboBoxModel.selectedItem = userProviderHolder
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val wasEnabled = SettingsSyncSettings.getInstance().syncEnabled
|
||||
if (enableCheckbox.isSelected) {
|
||||
if (wasEnabled) {
|
||||
if (!disableCurrentSyncDialog()) {
|
||||
userComboBoxModel.selectedItem = userProviderHolder // setting old value
|
||||
return
|
||||
}
|
||||
enableCheckbox.doClick()
|
||||
}
|
||||
else {
|
||||
enableButtonAction()
|
||||
}
|
||||
}
|
||||
userProviderHolder = selectedValue
|
||||
if (updateUserAccountLogout(selectedValue)) {
|
||||
updateUserComboBoxModel()
|
||||
}
|
||||
} else {
|
||||
userDropDownLink.selectedItem = selectedValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun updateUserAccountsList() {
|
||||
userAccountsList.clear()
|
||||
private fun updateUserAccountsList(): Boolean {
|
||||
val newList = arrayListOf<UserProviderHolder>()
|
||||
val providersList = RemoteCommunicatorHolder.getAvailableProviders()
|
||||
providersList.forEach { communicator ->
|
||||
val authService = communicator.authService
|
||||
val providerName = authService.providerName
|
||||
authService.getAvailableUserAccounts().forEachIndexed { idx, account ->
|
||||
val separatorString = if (idx == 0)
|
||||
providerName
|
||||
else
|
||||
null
|
||||
userAccountsList.add(account.toUserProviderHolder(providerName, separatorString))
|
||||
}
|
||||
newList.addAll(authService.getAvailableUserAccounts().map { it.toUserProviderHolder(providerName) })
|
||||
}
|
||||
if (hasMultipleProviders.get()) {
|
||||
userAccountsList.add(UserProviderHolder.addAccount)
|
||||
newList.add(UserProviderHolder.ADD_ACCOUNT)
|
||||
}
|
||||
userAccountListIsNotEmpty.set(userAccountsList.any { it != UserProviderHolder.addAccount })
|
||||
if (newList != userAccountsList) {
|
||||
userAccountsList.clear()
|
||||
userAccountsList.addAll(newList)
|
||||
userAccountListIsNotEmpty.set(userAccountsList.any { it != UserProviderHolder.ADD_ACCOUNT })
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun updateUserAccountLogout(selectedUser: UserProviderHolder?): Boolean {
|
||||
val newUserAccountsLogout = selectedUser?.providerCode?.let {
|
||||
val provider = RemoteCommunicatorHolder.getProvider(it)
|
||||
provider?.authService?.logoutFunction?.let {
|
||||
UserProviderHolder.logout(provider.providerCode, provider.authService.providerName)
|
||||
}
|
||||
}
|
||||
if (newUserAccountsLogout != userAccountsLogout) {
|
||||
userAccountsLogout = newUserAccountsLogout
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun updateUserComboBoxModel() {
|
||||
val selectedUser = selectedUser()
|
||||
userComboBoxModel.update(userAccountsList + listOfNotNull(userAccountsLogout))
|
||||
userComboBoxModel.selectedItem = selectedUser
|
||||
}
|
||||
|
||||
private fun validateCurrentUser() {
|
||||
val currentUser = currentUser()
|
||||
if (currentUser in userAccountsList) {
|
||||
userProviderHolder = currentUser
|
||||
return
|
||||
}
|
||||
// logout from an active account could happen somewhere else, should switch users manually
|
||||
val newCurrentUser = userAccountsList.firstOrNull { it != UserProviderHolder.ADD_ACCOUNT }
|
||||
if (SettingsSyncSettings.getInstance().syncEnabled) {
|
||||
handleDisableSync()
|
||||
}
|
||||
with(SettingsSyncLocalSettings.getInstance()) {
|
||||
userId = newCurrentUser?.userId
|
||||
providerCode = newCurrentUser?.providerCode
|
||||
}
|
||||
userProviderHolder = newCurrentUser
|
||||
}
|
||||
|
||||
|
||||
private fun login(
|
||||
provider: SettingsSyncCommunicatorProvider,
|
||||
syncConfigPanel: DialogPanel,
|
||||
@@ -646,17 +674,25 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
val remoteCommunicator = RemoteCommunicatorHolder.createRemoteCommunicator(provider, userData.id, loginDisposable) ?: return@withContext
|
||||
if (checkServerState(syncPanelHolder, remoteCommunicator, provider.authService.crossSyncSupported())) {
|
||||
SettingsSyncEvents.getInstance().fireLoginStateChanged()
|
||||
userDropDownLink.selectedItem = UserProviderHolder(userData.id, userData, provider.authService.providerCode,
|
||||
provider.authService.providerName, null)
|
||||
val newHolder = UserProviderHolder(userData.id, userData, provider.authService.providerCode, provider.authService.providerName, null)
|
||||
userProviderHolder = newHolder
|
||||
userComboBoxModel.selectedItem = newHolder
|
||||
updateUserAccountLogout(newHolder)
|
||||
updateUserComboBoxModel()
|
||||
|
||||
enableCheckbox.isSelected = true
|
||||
wasUsedBefore.set(true)
|
||||
syncConfigPanel.reset()
|
||||
triggerUpdateConfigurable()
|
||||
} else {
|
||||
userComboBoxModel.selectedItem = userProviderHolder
|
||||
updateUserComboBoxModel()
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG.info("Received empty user data from login")
|
||||
userComboBoxModel.selectedItem = userProviderHolder
|
||||
}
|
||||
}
|
||||
catch (ex: CancellationException) {
|
||||
@@ -665,6 +701,7 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
}
|
||||
catch (ex: Throwable) {
|
||||
LOG.warn("Error during login", ex)
|
||||
userComboBoxModel.selectedItem = userProviderHolder
|
||||
}
|
||||
finally {
|
||||
Disposer.dispose(loginDisposable)
|
||||
@@ -677,16 +714,19 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
UserProviderHolder(id, this, providerCode, providerName, separatorString)
|
||||
|
||||
override fun syncStatusChanged() {
|
||||
if (!::cellDropDownLink.isInitialized)
|
||||
if (!::cellUserComboBox.isInitialized)
|
||||
return
|
||||
updateUserAccountsList()
|
||||
if (updateUserAccountsList()) {
|
||||
if (updateUserAccountLogout(selectedUser())) {
|
||||
updateUserComboBoxModel()
|
||||
}
|
||||
}
|
||||
refreshActionRequired()
|
||||
if (!enableCheckbox.isSelected) {
|
||||
if (lastRemoveRemoteDataError != null) {
|
||||
cellDropDownLink.comment?.text = "<icon src='AllIcons.General.Error'> " +
|
||||
message("disable.remove.data.failure", lastRemoveRemoteDataError!!)
|
||||
cellUserComboBox.comment?.text = "<icon src='AllIcons.General.Error'> " + message("disable.remove.data.failure", lastRemoveRemoteDataError!!)
|
||||
} else {
|
||||
cellDropDownLink.comment?.text = ""
|
||||
cellUserComboBox.comment?.text = ""
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -695,19 +735,18 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
if (currentStatus == SettingsSyncStatusTracker.SyncStatus.Success) {
|
||||
val lastSyncTime = SettingsSyncStatusTracker.getInstance().getLastSyncTime()
|
||||
if (lastSyncTime > 0) {
|
||||
cellDropDownLink.comment?.text = "<icon src='AllIcons.General.GreenCheckmark'> " + message("sync.status.last.sync.message", DateFormatUtil.formatPrettyDateTime(lastSyncTime))
|
||||
cellUserComboBox.comment?.text = "<icon src='AllIcons.General.GreenCheckmark'> " + message("sync.status.last.sync.message", DateFormatUtil.formatPrettyDateTime(lastSyncTime))
|
||||
}
|
||||
else {
|
||||
cellDropDownLink.comment?.text = message("sync.status.enabled")
|
||||
cellUserComboBox.comment?.text = message("sync.status.enabled")
|
||||
}
|
||||
}
|
||||
else if (currentStatus is SettingsSyncStatusTracker.SyncStatus.Error) {
|
||||
cellDropDownLink.comment?.text = message("sync.status.failed", currentStatus.errorMessage)
|
||||
cellUserComboBox.comment?.text = message("sync.status.failed", currentStatus.errorMessage)
|
||||
}
|
||||
}
|
||||
else {
|
||||
//statusLabel.icon = icons.SettingsSyncIcons.StatusNotRun
|
||||
cellDropDownLink.comment?.text = ""
|
||||
cellUserComboBox.comment?.text = ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -724,12 +763,12 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
}
|
||||
actionRequiredLabel.text = userActionRequired.message
|
||||
actionRequiredButton.text = userActionRequired.actionTitle
|
||||
cellDropDownLink.comment?.text = message("sync.status.action.required.comment",
|
||||
cellUserComboBox.comment?.text = message("sync.status.action.required.comment",
|
||||
userActionRequired.actionTitle,
|
||||
userActionRequired.actionDescription ?: userActionRequired.message)
|
||||
}
|
||||
else {
|
||||
cellDropDownLink.comment?.text = ""
|
||||
cellUserComboBox.comment?.text = ""
|
||||
actionRequiredAction = null
|
||||
actionRequiredLabel.text = ""
|
||||
actionRequiredButton.text = ""
|
||||
@@ -739,7 +778,7 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
private fun getPendingUserAction(): PendingUserAction? {
|
||||
if (!enableCheckbox.isSelected)
|
||||
return null
|
||||
return userDropDownLink.selectedItem?.let {
|
||||
return selectedUser()?.let {
|
||||
RemoteCommunicatorHolder.getProvider(it.providerCode)?.authService?.getPendingUserAction(it.userId)
|
||||
}
|
||||
}
|
||||
@@ -815,10 +854,14 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco
|
||||
val providerName: String,
|
||||
val separatorString: String?, // separator value, set only for the first account in the list
|
||||
) {
|
||||
companion object{
|
||||
val addAccount = UserProviderHolder(
|
||||
"<ADDACCOUNT>", SettingsSyncUserData("<ADDACCOUNT>", "", null, null), "",
|
||||
companion object {
|
||||
val ADD_ACCOUNT = UserProviderHolder(
|
||||
"<ADD_ACCOUNT>", SettingsSyncUserData("<ADD_ACCOUNT>", "", null, null, message("enable.sync.add.account")), "",
|
||||
"", "")
|
||||
const val LOGOUT_USER_ID = "<LOGOUT>"
|
||||
fun logout(providerCode: String, providerName: String) = UserProviderHolder(
|
||||
LOGOUT_USER_ID, SettingsSyncUserData(LOGOUT_USER_ID, providerCode, null, null, LOGOUT_USER_ID), providerCode,
|
||||
providerName, "")
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
Reference in New Issue
Block a user