feat(communities): inform about missing encryption key

closes: #15064
This commit is contained in:
Patryk Osmaczko 2024-06-28 18:29:18 +02:00 committed by osmaczko
parent ee37dc9e4b
commit b08eb128ad
12 changed files with 75 additions and 13 deletions

View File

@ -27,6 +27,7 @@ QtObject:
canView: bool canView: bool
canPostReactions: bool canPostReactions: bool
hideIfPermissionsNotMet: bool hideIfPermissionsNotMet: bool
missingEncryptionKey: bool
proc delete*(self: ChatDetails) = proc delete*(self: ChatDetails) =
self.QObject.delete self.QObject.delete
@ -56,6 +57,7 @@ QtObject:
canView: bool = true, canView: bool = true,
canPostReactions: bool = true, canPostReactions: bool = true,
hideIfPermissionsNotMet: bool, hideIfPermissionsNotMet: bool,
missingEncryptionKey: bool,
) = ) =
self.id = id self.id = id
self.`type` = `type` self.`type` = `type`
@ -79,6 +81,7 @@ QtObject:
self.canView = canView self.canView = canView
self.canPostReactions = canPostReactions self.canPostReactions = canPostReactions
self.hideIfPermissionsNotMet = hideIfPermissionsNotMet self.hideIfPermissionsNotMet = hideIfPermissionsNotMet
self.missingEncryptionKey = missingEncryptionKey
proc getId(self: ChatDetails): string {.slot.} = proc getId(self: ChatDetails): string {.slot.} =
return self.id return self.id
@ -297,3 +300,14 @@ QtObject:
proc setHideIfPermissionsNotMet*(self: ChatDetails, value: bool) = proc setHideIfPermissionsNotMet*(self: ChatDetails, value: bool) =
self.hideIfPermissionsNotMet = value self.hideIfPermissionsNotMet = value
self.hideIfPermissionsNotMetChanged() self.hideIfPermissionsNotMetChanged()
proc missingEncryptionKeyChanged(self: ChatDetails) {.signal.}
proc getMissingEncryptionKey(self: ChatDetails): bool {.slot.} =
return self.missingEncryptionKey
QtProperty[bool] missingEncryptionKey:
read = getMissingEncryptionKey
notify = missingEncryptionKeyChanged
proc setMissingEncryptionKey*(self: ChatDetails, value: bool) =
self.missingEncryptionKey = value
self.missingEncryptionKeyChanged()

View File

@ -97,7 +97,7 @@ method load*(self: Module, chatItem: chat_item.Item) =
chatItem.color, chatItem.description, chatItem.emoji, chatItem.hasUnreadMessages, chatItem.notificationsCount, chatItem.color, chatItem.description, chatItem.emoji, chatItem.hasUnreadMessages, chatItem.notificationsCount,
chatItem.highlight, chatItem.muted, chatItem.position, isUntrustworthy = trustStatus == TrustStatus.Untrustworthy, chatItem.highlight, chatItem.muted, chatItem.position, isUntrustworthy = trustStatus == TrustStatus.Untrustworthy,
isContact, chatItem.blocked, chatItem.canPost, chatItem.canView, chatItem.canPostReactions, isContact, chatItem.blocked, chatItem.canPost, chatItem.canView, chatItem.canPostReactions,
chatItem.hideIfPermissionsNotMet) chatItem.hideIfPermissionsNotMet, chatItem.missingEncryptionKey)
self.view.chatDetailsChanged() self.view.chatDetailsChanged()
@ -382,6 +382,7 @@ method onChatUpdated*(self: Module, chatItem: chat_item.Item) =
self.view.chatDetails.setCanView(chatItem.canView) self.view.chatDetails.setCanView(chatItem.canView)
self.view.chatDetails.setCanPostReactions(chatItem.canPostReactions) self.view.chatDetails.setCanPostReactions(chatItem.canPostReactions)
self.view.chatDetails.setHideIfPermissionsNotMet(chat_item.hideIfPermissionsNotMet) self.view.chatDetails.setHideIfPermissionsNotMet(chat_item.hideIfPermissionsNotMet)
self.view.chatDetails.setMissingEncryptionKey(chat_item.missingEncryptionKey)
self.messagesModule.updateChatFetchMoreMessages() self.messagesModule.updateChatFetchMoreMessages()
self.messagesModule.updateChatIdentifier() self.messagesModule.updateChatIdentifier()
@ -398,6 +399,7 @@ method onCommunityChannelEdited*(self: Module, chatDto: ChatDto) =
self.view.chatDetails.setHideIfPermissionsNotMet(chatDto.hideIfPermissionsNotMet) self.view.chatDetails.setHideIfPermissionsNotMet(chatDto.hideIfPermissionsNotMet)
self.view.chatDetails.setName(chatDto.name) self.view.chatDetails.setName(chatDto.name)
self.view.chatDetails.setIcon(chatDto.icon) self.view.chatDetails.setIcon(chatDto.icon)
self.view.chatDetails.setMissingEncryptionKey(chatDto.missingEncryptionKey)
self.messagesModule.updateChatFetchMoreMessages() self.messagesModule.updateChatFetchMoreMessages()
self.messagesModule.updateChatIdentifier() self.messagesModule.updateChatIdentifier()

View File

@ -40,6 +40,7 @@ type
canView: bool canView: bool
viewersCanPostReactions: bool viewersCanPostReactions: bool
hideIfPermissionsNotMet: bool hideIfPermissionsNotMet: bool
missingEncryptionKey: bool
proc initItem*( proc initItem*(
id, id,
@ -73,6 +74,7 @@ proc initItem*(
canPostReactions = true, canPostReactions = true,
viewersCanPostReactions = true, viewersCanPostReactions = true,
hideIfPermissionsNotMet: bool, hideIfPermissionsNotMet: bool,
missingEncryptionKey: bool
): Item = ): Item =
result = Item() result = Item()
result.id = id result.id = id
@ -107,6 +109,7 @@ proc initItem*(
result.canPostReactions = canPostReactions result.canPostReactions = canPostReactions
result.viewersCanPostReactions = viewersCanPostReactions result.viewersCanPostReactions = viewersCanPostReactions
result.hideIfPermissionsNotMet = hideIfPermissionsNotMet result.hideIfPermissionsNotMet = hideIfPermissionsNotMet
result.missingEncryptionKey = missingEncryptionKey
proc `$`*(self: Item): string = proc `$`*(self: Item): string =
result = fmt"""chat_section/Item( result = fmt"""chat_section/Item(
@ -358,3 +361,9 @@ proc `viewersCanPostReactions=`*(self: Item, value: bool) =
proc hideBecausePermissionsAreNotMet*(self: Item): bool = proc hideBecausePermissionsAreNotMet*(self: Item): bool =
self.hideIfPermissionsNotMet and not self.canPost and not self.canView self.hideIfPermissionsNotMet and not self.canPost and not self.canView
proc missingEncryptionKey*(self: Item): bool =
self.missingEncryptionKey
proc `missingEncryptionKey=`*(self: var Item, value: bool) =
self.missingEncryptionKey = value

View File

@ -42,6 +42,7 @@ type
HideIfPermissionsNotMet HideIfPermissionsNotMet
ShouldBeHiddenBecausePermissionsAreNotMet #this is a complex role which depends on other roles ShouldBeHiddenBecausePermissionsAreNotMet #this is a complex role which depends on other roles
#(MemberRole , HideIfPermissionsNotMet, canPost and canView) #(MemberRole , HideIfPermissionsNotMet, canPost and canView)
MissingEncryptionKey
QtObject: QtObject:
type type
@ -143,7 +144,8 @@ QtObject:
ModelRole.CanView.int:"canView", ModelRole.CanView.int:"canView",
ModelRole.CanPostReactions.int:"canPostReactions", ModelRole.CanPostReactions.int:"canPostReactions",
ModelRole.ViewersCanPostReactions.int:"viewersCanPostReactions", ModelRole.ViewersCanPostReactions.int:"viewersCanPostReactions",
ModelRole.ShouldBeHiddenBecausePermissionsAreNotMet.int:"shouldBeHiddenBecausePermissionsAreNotMet" ModelRole.ShouldBeHiddenBecausePermissionsAreNotMet.int:"shouldBeHiddenBecausePermissionsAreNotMet",
ModelRole.MissingEncryptionKey.int:"missingEncryptionKey",
}.toTable }.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant = method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -223,6 +225,8 @@ QtObject:
result = newQVariant(item.hideIfPermissionsNotMet) result = newQVariant(item.hideIfPermissionsNotMet)
of ModelRole.ShouldBeHiddenBecausePermissionsAreNotMet: of ModelRole.ShouldBeHiddenBecausePermissionsAreNotMet:
return newQVariant(self.itemShouldBeHiddenBecauseNotPermitted(item)) return newQVariant(self.itemShouldBeHiddenBecauseNotPermitted(item))
of ModelRole.MissingEncryptionKey:
return newQVariant(item.missingEncryptionKey)
proc getItemIdxById(items: seq[Item], id: string): int = proc getItemIdxById(items: seq[Item], id: string): int =
var idx = 0 var idx = 0
@ -724,3 +728,14 @@ QtObject:
let modelIndex = self.createIndex(index, 0, nil) let modelIndex = self.createIndex(index, 0, nil)
defer: modelIndex.delete defer: modelIndex.delete
self.dataChanged(modelIndex, modelIndex, @[ModelRole.Active.int, ModelRole.LoaderActive.int]) self.dataChanged(modelIndex, modelIndex, @[ModelRole.Active.int, ModelRole.LoaderActive.int])
proc updateMissingEncryptionKey*(self: Model, id: string, missingEncryptionKey: bool) =
let index = self.getItemIdxById(id)
if index == -1:
return
if self.items[index].missingEncryptionKey != missingEncryptionKey:
self.items[index].missingEncryptionKey = missingEncryptionKey
let modelIndex = self.createIndex(index, 0, nil)
defer: modelIndex.delete
self.dataChanged(modelIndex, modelIndex, @[ModelRole.MissingEncryptionKey.int])

View File

@ -275,6 +275,7 @@ proc addCategoryItem(self: Module, category: Category, memberRole: MemberRole, c
category.id, category.id,
category.position, category.position,
hideIfPermissionsNotMet = false, hideIfPermissionsNotMet = false,
missingEncryptionKey = false,
) )
if insertIntoModel: if insertIntoModel:
@ -530,7 +531,7 @@ method activeItemSet*(self: Module, itemId: string) =
if self.controller.isCommunity(): if self.controller.isCommunity():
let community = self.controller.getMyCommunity() let community = self.controller.getMyCommunity()
if not community.isPrivilegedUser: if not community.isPrivilegedUser:
if not chat_item.canView or not chat_item.canPost: if not chat_item.missingEncryptionKey and (not chat_item.canView or not chat_item.canPost):
# User doesn't have full access to this channel. Check permissions to know what is missing # User doesn't have full access to this channel. Check permissions to know what is missing
self.controller.asyncCheckChannelPermissions(mySectionId, activeChatId) self.controller.asyncCheckChannelPermissions(mySectionId, activeChatId)
@ -699,6 +700,7 @@ proc getChatItemFromChatDto(
var canPostReactions = true var canPostReactions = true
var hideIfPermissionsNotMet = false var hideIfPermissionsNotMet = false
var viewersCanPostReactions = true var viewersCanPostReactions = true
var missingEncryptionKey = false
if self.controller.isCommunity: if self.controller.isCommunity:
let communityChat = community.getCommunityChat(chatDto.id) let communityChat = community.getCommunityChat(chatDto.id)
# NOTE: workaround for new community chat, which is delivered in chatDto before the community will know about that # NOTE: workaround for new community chat, which is delivered in chatDto before the community will know about that
@ -710,12 +712,14 @@ proc getChatItemFromChatDto(
canPostReactions = communityChat.canPostReactions canPostReactions = communityChat.canPostReactions
hideIfPermissionsNotMet = communityChat.hideIfPermissionsNotMet hideIfPermissionsNotMet = communityChat.hideIfPermissionsNotMet
viewersCanPostReactions = communityChat.viewersCanPostReactions viewersCanPostReactions = communityChat.viewersCanPostReactions
missingEncryptionKey = communityChat.missingEncryptionKey
else: else:
canPost = chatDto.canPost canPost = chatDto.canPost
canView = chatDto.canView canView = chatDto.canView
canPostReactions = chatDto.canPostReactions canPostReactions = chatDto.canPostReactions
hideIfPermissionsNotMet = chatDto.hideIfPermissionsNotMet hideIfPermissionsNotMet = chatDto.hideIfPermissionsNotMet
viewersCanPostReactions = chatDto.viewersCanPostReactions viewersCanPostReactions = chatDto.viewersCanPostReactions
missingEncryptionKey = chatDto.missingEncryptionKey
result = chat_item.initItem( result = chat_item.initItem(
chatDto.id, chatDto.id,
@ -754,6 +758,7 @@ proc getChatItemFromChatDto(
canPostReactions = canPostReactions, canPostReactions = canPostReactions,
viewersCanPostReactions = viewersCanPostReactions, viewersCanPostReactions = viewersCanPostReactions,
hideIfPermissionsNotMet = hideIfPermissionsNotMet, hideIfPermissionsNotMet = hideIfPermissionsNotMet,
missingEncryptionKey = missingEncryptionKey
) )
proc addNewChat( proc addNewChat(
@ -1386,6 +1391,7 @@ method prepareEditCategoryModel*(self: Module, categoryId: string) =
c.position, c.position,
categoryId="", categoryId="",
hideIfPermissionsNotMet=false, hideIfPermissionsNotMet=false,
missingEncryptionKey=false,
) )
self.view.editCategoryChannelsModel().appendItem(chatItem) self.view.editCategoryChannelsModel().appendItem(chatItem)
let catChats = self.controller.getChats(communityId, categoryId) let catChats = self.controller.getChats(communityId, categoryId)
@ -1409,6 +1415,7 @@ method prepareEditCategoryModel*(self: Module, categoryId: string) =
c.position, c.position,
categoryId, categoryId,
hideIfPermissionsNotMet=false, hideIfPermissionsNotMet=false,
missingEncryptionKey=false,
) )
self.view.editCategoryChannelsModel().appendItem(chatItem, ignoreCategory = true) self.view.editCategoryChannelsModel().appendItem(chatItem, ignoreCategory = true)
@ -1473,6 +1480,7 @@ method addOrUpdateChat(self: Module,
self.changeCanPostValues(chat.id, result.canPost, result.canView, result.canPostReactions, result.viewersCanPostReactions) self.changeCanPostValues(chat.id, result.canPost, result.canView, result.canPostReactions, result.viewersCanPostReactions)
self.updatePermissionsRequiredOnChat(chat.id) self.updatePermissionsRequiredOnChat(chat.id)
self.updateChatLocked(chat.id) self.updateChatLocked(chat.id)
self.view.chatsModel().updateMissingEncryptionKey(chat.id, result.missingEncryptionKey)
if (chat.chatType == ChatType.PrivateGroupChat): if (chat.chatType == ChatType.PrivateGroupChat):
self.onGroupChatDetailsUpdated(chat.id, chat.name, chat.color, chat.icon) self.onGroupChatDetailsUpdated(chat.id, chat.name, chat.color, chat.icon)
elif (chat.chatType != ChatType.OneToOne): elif (chat.chatType != ChatType.OneToOne):

View File

@ -95,6 +95,7 @@ type ChatDto* = object
permissions*: Permission permissions*: Permission
hideIfPermissionsNotMet*: bool hideIfPermissionsNotMet*: bool
tokenGated*: bool tokenGated*: bool
missingEncryptionKey*: bool
type ClearedHistoryDto* = object type ClearedHistoryDto* = object
chatId*: string chatId*: string
@ -130,7 +131,9 @@ proc `$`*(self: ChatDto): string =
categoryId: {self.categoryId}, categoryId: {self.categoryId},
position: {self.position}, position: {self.position},
highlight: {self.highlight}, highlight: {self.highlight},
hideIfPermissionsNotMet: {self.hideIfPermissionsNotMet} hideIfPermissionsNotMet: {self.hideIfPermissionsNotMet},
tokenGated: {self.tokenGated},
missingEncryptionKey: {self.missingEncryptionKey}
)""" )"""
proc toCheckPermissionsResultDto*(jsonObj: JsonNode): CheckPermissionsResultDto = proc toCheckPermissionsResultDto*(jsonObj: JsonNode): CheckPermissionsResultDto =
@ -264,6 +267,7 @@ proc toChatDto*(jsonObj: JsonNode): ChatDto =
discard jsonObj.getProp("categoryID", result.categoryId) discard jsonObj.getProp("categoryID", result.categoryId)
discard jsonObj.getProp("hideIfPermissionsNotMet", result.hideIfPermissionsNotMet) discard jsonObj.getProp("hideIfPermissionsNotMet", result.hideIfPermissionsNotMet)
discard jsonObj.getProp("tokenGated", result.tokenGated) discard jsonObj.getProp("tokenGated", result.tokenGated)
discard jsonObj.getProp("missingEncryptionKey", result.missingEncryptionKey)
discard jsonObj.getProp("position", result.position) discard jsonObj.getProp("position", result.position)
discard jsonObj.getProp("communityId", result.communityId) discard jsonObj.getProp("communityId", result.communityId)
discard jsonObj.getProp("profile", result.profile) discard jsonObj.getProp("profile", result.profile)

View File

@ -649,7 +649,9 @@ QtObject:
chat.viewersCanPostReactions != prevChat.viewersCanPostReactions or chat.viewersCanPostReactions != prevChat.viewersCanPostReactions or
chat.canPost != prevChat.canPost or chat.canPost != prevChat.canPost or
chat.canView != prevChat.canView or chat.canView != prevChat.canView or
chat.hideIfPermissionsNotMet != prevChat.hideIfPermissionsNotMet: chat.hideIfPermissionsNotMet != prevChat.hideIfPermissionsNotMet or
chat.tokenGated != prevChat.tokenGated or
chat.missingEncryptionKey != prevChat.missingEncryptionKey:
var updatedChat = chat var updatedChat = chat
self.chatService.updateOrAddChat(updatedChat) # we have to update chats stored in the chat service. self.chatService.updateOrAddChat(updatedChat) # we have to update chats stored in the chat service.

View File

@ -51,6 +51,7 @@ StatusSectionLayout {
readonly property var chatContentModule: rootStore.currentChatContentModule() || null readonly property var chatContentModule: rootStore.currentChatContentModule() || null
readonly property bool canView: chatContentModule.chatDetails.canView readonly property bool canView: chatContentModule.chatDetails.canView
readonly property bool canPost: chatContentModule.chatDetails.canPost readonly property bool canPost: chatContentModule.chatDetails.canPost
readonly property bool missingEncryptionKey: chatContentModule.chatDetails.missingEncryptionKey
property bool hasViewOnlyPermissions: false property bool hasViewOnlyPermissions: false
property bool hasUnrestrictedViewOnlyPermission: false property bool hasUnrestrictedViewOnlyPermission: false
@ -243,9 +244,11 @@ StatusSectionLayout {
collectiblesModel: root.collectiblesModel collectiblesModel: root.collectiblesModel
requestToJoinState: root.requestToJoinState requestToJoinState: root.requestToJoinState
requiresRequest: !root.amIMember requiresRequest: !root.amIMember
requirementsMet: (canView && viewOnlyPermissionsModel.count > 0) || requirementsMet: root.missingEncryptionKey ||
(canPost && viewAndPostPermissionsModel.count > 0) (root.canView && viewOnlyPermissionsModel.count > 0) ||
(root.canPost && viewAndPostPermissionsModel.count > 0)
requirementsCheckPending: root.chatContentModule.permissionsCheckOngoing requirementsCheckPending: root.chatContentModule.permissionsCheckOngoing
missingEncryptionKey: root.missingEncryptionKey
onRequestToJoinClicked: root.requestToJoinClicked() onRequestToJoinClicked: root.requestToJoinClicked()
onInvitationPendingClicked: root.invitationPendingClicked() onInvitationPendingClicked: root.invitationPendingClicked()
} }

View File

@ -7,8 +7,6 @@ import StatusQ.Core.Theme 0.1
StatusBaseText { StatusBaseText {
id: root id: root
text: qsTr("Requirements check pending...")
color: Theme.palette.dangerColor1 color: Theme.palette.dangerColor1
SequentialAnimation { SequentialAnimation {

View File

@ -25,6 +25,7 @@ ColumnLayout {
property bool requirementsMet: true property bool requirementsMet: true
property bool requirementsCheckPending: false property bool requirementsCheckPending: false
property bool missingEncryptionKey: false
property var communityHoldingsModel property var communityHoldingsModel
property var viewOnlyHoldingsModel property var viewOnlyHoldingsModel
@ -145,6 +146,7 @@ ColumnLayout {
allChannelsAreHiddenBecauseNotPermitted: root.allChannelsAreHiddenBecauseNotPermitted allChannelsAreHiddenBecauseNotPermitted: root.allChannelsAreHiddenBecauseNotPermitted
requirementsMet: root.requirementsMet requirementsMet: root.requirementsMet
requirementsCheckPending: root.requirementsCheckPending requirementsCheckPending: root.requirementsCheckPending
missingEncryptionKey: root.missingEncryptionKey
requestToJoinState: root.requestToJoinState requestToJoinState: root.requestToJoinState
isJoinRequestRejected: root.isJoinRequestRejected isJoinRequestRejected: root.isJoinRequestRejected
requiresRequest: root.requiresRequest requiresRequest: root.requiresRequest

View File

@ -25,6 +25,7 @@ Control {
property bool requiresRequest: false property bool requiresRequest: false
property int requestToJoinState: Constants.RequestToJoinState.None property int requestToJoinState: Constants.RequestToJoinState.None
property bool isInvitationPending: root.requestToJoinState !== Constants.RequestToJoinState.None property bool isInvitationPending: root.requestToJoinState !== Constants.RequestToJoinState.None
property bool missingEncryptionKey: false
property bool isJoinRequestRejected: false property bool isJoinRequestRejected: false
property string communityName property string communityName
@ -50,7 +51,9 @@ Control {
readonly property string channelRequirementsNotMetText: qsTr("Channel requirements not met") readonly property string channelRequirementsNotMetText: qsTr("Channel requirements not met")
readonly property string channelMembershipRequestPendingText: qsTr("Channel Membership Request Pending...") readonly property string channelMembershipRequestPendingText: qsTr("Channel Membership Request Pending...")
readonly property string membershipRequestRejectedText: qsTr("Membership Request Rejected") readonly property string membershipRequestRejectedText: qsTr("Membership Request Rejected")
readonly property string allChannelsAreHiddenBecauseNotPermittedText: qsTr("Sorry, you don't hodl the necessary tokens to view or post in any of <b>%1</b> channels").arg(root.communityName) readonly property string allChannelsAreHiddenBecauseNotPermittedText: qsTr("Sorry, you don't hold the necessary tokens to view or post in any of <b>%1</b> channels").arg(root.communityName)
readonly property string requirementsCheckPendingText: qsTr("Requirements check pending...")
readonly property string missingEncryptionKeyText: qsTr("Encryption key has not arrived yet...")
readonly property bool onlyPrivateNotMetPermissions: (d.visiblePermissionsModel.count === 0) && root.communityHoldingsModel.count > 0 readonly property bool onlyPrivateNotMetPermissions: (d.visiblePermissionsModel.count === 0) && root.communityHoldingsModel.count > 0
@ -174,6 +177,7 @@ Control {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
visible: !root.showOnlyPanels visible: !root.showOnlyPanels
&& !root.requirementsCheckPending && !root.requirementsCheckPending
&& !root.missingEncryptionKey
&& (root.isJoinRequestRejected || !root.requirementsMet) && (root.isJoinRequestRejected || !root.requirementsMet)
&& !d.onlyPrivateNotMetPermissions && !d.onlyPrivateNotMetPermissions
&& !root.allChannelsAreHiddenBecauseNotPermitted && !root.allChannelsAreHiddenBecauseNotPermitted
@ -182,9 +186,10 @@ Control {
color: Theme.palette.dangerColor1 color: Theme.palette.dangerColor1
} }
RequirementsCheckPendingLoader { BlinkingText {
visible: root.requirementsCheckPending
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
visible: root.requirementsCheckPending || root.missingEncryptionKey
text: root.missingEncryptionKey ? d.missingEncryptionKeyText : d.requirementsCheckPendingText
} }
} }
} }

View File

@ -1,6 +1,7 @@
AirdropsSettingsPanel 1.0 AirdropsSettingsPanel.qml AirdropsSettingsPanel 1.0 AirdropsSettingsPanel.qml
BackUpCommuntyBannerPanel 1.0 BackUpCommuntyBannerPanel.qml BackUpCommuntyBannerPanel 1.0 BackUpCommuntyBannerPanel.qml
BannerPanel 1.0 BannerPanel.qml BannerPanel 1.0 BannerPanel.qml
BlinkingText 1.0 BlinkingText.qml
ChannelsAndCategoriesBannerPanel 1.0 ChannelsAndCategoriesBannerPanel.qml ChannelsAndCategoriesBannerPanel 1.0 ChannelsAndCategoriesBannerPanel.qml
ChatPermissionQualificationPanel 1.0 ChatPermissionQualificationPanel.qml ChatPermissionQualificationPanel 1.0 ChatPermissionQualificationPanel.qml
ColorPanel 1.0 ColorPanel.qml ColorPanel 1.0 ColorPanel.qml
@ -28,7 +29,6 @@ PrivilegedTokenArtworkPanel 1.0 PrivilegedTokenArtworkPanel.qml
ProfilePopupInviteFriendsPanel 1.0 ProfilePopupInviteFriendsPanel.qml ProfilePopupInviteFriendsPanel 1.0 ProfilePopupInviteFriendsPanel.qml
ProfilePopupInviteMessagePanel 1.0 ProfilePopupInviteMessagePanel.qml ProfilePopupInviteMessagePanel 1.0 ProfilePopupInviteMessagePanel.qml
ProfilePopupOverviewPanel 1.0 ProfilePopupOverviewPanel.qml ProfilePopupOverviewPanel 1.0 ProfilePopupOverviewPanel.qml
RequirementsCheckPendingLoader 1.0 RequirementsCheckPendingLoader.qml
SharedAddressesAccountSelector 1.0 SharedAddressesAccountSelector.qml SharedAddressesAccountSelector 1.0 SharedAddressesAccountSelector.qml
SharedAddressesPanel 1.0 SharedAddressesPanel.qml SharedAddressesPanel 1.0 SharedAddressesPanel.qml
SharedAddressesSigningPanel 1.0 SharedAddressesSigningPanel.qml SharedAddressesSigningPanel 1.0 SharedAddressesSigningPanel.qml