2023-02-15 08:27:18 +00:00
import QtQuick 2.15
2020-06-17 19:18:31 +00:00
import QtQuick . Controls 2.13
import QtQuick . Layouts 1.13
2021-02-18 19:14:31 +00:00
import QtMultimedia 5.13
2022-03-03 22:50:53 +00:00
import Qt . labs . platform 1.1
2022-09-02 14:56:14 +00:00
import QtQml . Models 2.14
2023-02-27 12:11:51 +00:00
import QtQml 2.15
2022-03-03 22:50:53 +00:00
2022-03-08 18:49:33 +00:00
import AppLayouts . Wallet 1.0
import AppLayouts . Node 1.0
import AppLayouts . Browser 1.0
import AppLayouts . Chat 1.0
2022-05-13 15:27:26 +00:00
import AppLayouts . Chat . views 1.0
2022-03-08 18:49:33 +00:00
import AppLayouts . Profile 1.0
2023-06-23 06:17:04 +00:00
import AppLayouts . Communities 1.0
2021-09-28 15:04:06 +00:00
import utils 1.0
2021-10-27 21:27:49 +00:00
import shared 1.0
2022-03-17 16:15:38 +00:00
import shared . controls 1.0
2023-06-07 10:54:31 +00:00
import shared . controls . chat . menuItems 1.0
2021-10-27 21:27:49 +00:00
import shared . panels 1.0
import shared . popups 1.0
2022-09-13 10:03:25 +00:00
import shared . popups . keycard 1.0
2021-10-27 21:27:49 +00:00
import shared . status 1.0
2023-04-03 17:13:23 +00:00
import shared . stores 1.0
2020-05-11 21:24:08 +00:00
2021-06-11 12:17:23 +00:00
import StatusQ . Core . Theme 0.1
2021-10-21 23:34:35 +00:00
import StatusQ . Components 0.1
2021-06-11 12:17:23 +00:00
import StatusQ . Controls 0.1
import StatusQ . Layout 0.1
import StatusQ . Popups 0.1
2022-09-02 14:56:14 +00:00
import StatusQ . Popups . Dialog 0.1
2021-10-21 23:34:35 +00:00
import StatusQ . Core 0.1
2021-06-11 12:17:23 +00:00
2022-05-16 15:02:03 +00:00
import AppLayouts . Browser . stores 1.0 as BrowserStores
2022-03-08 18:49:33 +00:00
import AppLayouts . stores 1.0
2023-02-09 21:49:36 +00:00
import AppLayouts . Chat . stores 1.0 as ChatStores
2023-06-23 06:17:04 +00:00
import AppLayouts . Communities . stores 1.0
2022-03-03 22:50:53 +00:00
2023-04-17 08:31:32 +00:00
import mainui . activitycenter . stores 1.0
import mainui . activitycenter . popups 1.0
2022-11-28 11:32:29 +00:00
import SortFilterProxyModel 0.2
2022-10-06 15:47:55 +00:00
import "panels"
2022-07-12 08:56:47 +00:00
2021-06-17 18:41:11 +00:00
Item {
2020-09-15 19:47:13 +00:00
id: appMain
2020-05-11 21:24:08 +00:00
2021-09-15 11:40:07 +00:00
property alias appLayout: appLayout
2022-09-23 15:02:54 +00:00
property RootStore rootStore: RootStore { }
2023-02-09 21:49:36 +00:00
property var rootChatStore: ChatStores . RootStore {
contactsStore: appMain . rootStore . contactStore
2023-04-11 08:09:01 +00:00
communityTokensStore: appMain . communityTokensStore
2023-02-09 21:49:36 +00:00
emojiReactionsModel: appMain . rootStore . emojiReactionsModel
openCreateChat: createChatView . opened
2023-04-04 11:31:04 +00:00
networkConnectionStore: appMain . networkConnectionStore
2023-02-09 21:49:36 +00:00
}
2023-05-04 18:36:35 +00:00
property var createChatPropertiesStore: ChatStores . CreateChatPropertiesStore { }
2022-10-26 16:00:20 +00:00
property ActivityCenterStore activityCenterStore: ActivityCenterStore { }
2023-04-03 17:13:23 +00:00
property NetworkConnectionStore networkConnectionStore: NetworkConnectionStore { }
2023-04-11 08:09:01 +00:00
property CommunityTokensStore communityTokensStore: CommunityTokensStore { }
2023-04-28 10:35:18 +00:00
property CommunitiesStore communitiesStore: CommunitiesStore { }
2021-12-09 13:28:02 +00:00
// set from main.qml
property var sysPalette
2021-10-20 09:50:50 +00:00
2022-03-17 16:24:50 +00:00
Connections {
target: rootStore . mainModuleInst
2022-09-13 10:03:25 +00:00
2023-01-18 09:25:36 +00:00
function onDisplayUserProfile ( publicKey: string ) {
2023-02-07 14:21:32 +00:00
popups . openProfilePopup ( publicKey )
2023-01-18 09:25:36 +00:00
}
2022-09-13 10:03:25 +00:00
2023-01-18 09:25:36 +00:00
function onDisplayKeycardSharedModuleFlow ( ) {
2023-06-30 09:24:08 +00:00
keycardPopup . active = true
2022-09-13 10:03:25 +00:00
}
2023-01-18 09:25:36 +00:00
function onDestroyKeycardSharedModuleFlow ( ) {
2023-06-30 09:24:08 +00:00
keycardPopup . active = false
2022-09-13 10:03:25 +00:00
}
2022-10-18 09:06:18 +00:00
2023-01-18 09:25:36 +00:00
function onMailserverWorking ( ) {
2023-01-18 13:55:23 +00:00
mailserverConnectionBanner . hide ( )
}
2023-01-18 09:25:36 +00:00
function onMailserverNotWorking ( ) {
2023-01-18 10:36:28 +00:00
mailserverConnectionBanner . show ( )
2022-10-18 09:06:18 +00:00
}
2023-01-18 09:25:36 +00:00
function onActiveSectionChanged ( ) {
2022-10-18 09:06:18 +00:00
createChatView . opened = false
}
2023-01-12 19:06:18 +00:00
2023-01-18 09:25:36 +00:00
function onOpenActivityCenter ( ) {
2023-04-17 08:31:32 +00:00
d . openActivityCenterPopup ( )
}
2023-07-17 20:06:34 +00:00
function onShowToastAccountAdded ( name: string ) {
Global . displayToastMessage (
qsTr ( "\"%1\" successfuly added" ) . arg ( name ) ,
"" ,
"check-circle" ,
false ,
Constants . ephemeralNotificationType . success ,
""
)
}
function onShowToastKeypairRenamed ( oldName: string , newName: string ) {
Global . displayToastMessage (
qsTr ( "You successfully renamed your keypair\nfrom \"%1\" to \"%2\"" ) . arg ( oldName ) . arg ( newName ) ,
"" ,
"check-circle" ,
false ,
Constants . ephemeralNotificationType . success ,
""
)
}
2023-04-17 08:31:32 +00:00
}
QtObject {
id: d
property var activityCenterPopupObj: null
function openActivityCenterPopup ( ) {
if ( ! activityCenterPopupObj ) {
activityCenterPopupObj = activityCenterPopupComponent . createObject ( appMain )
}
if ( activityCenterPopupObj . opened ) {
activityCenterPopupObj . close ( )
} else {
activityCenterPopupObj . open ( )
}
2023-01-12 19:06:18 +00:00
}
2022-03-17 16:24:50 +00:00
}
2022-10-21 13:37:39 +00:00
Popups {
2023-02-07 14:21:32 +00:00
id: popups
popupParent: appMain
2022-10-21 13:37:39 +00:00
rootStore: appMain . rootStore
2023-04-28 10:35:18 +00:00
communitiesStore: appMain . communitiesStore
2023-06-26 11:44:56 +00:00
isDevBuild: ! production
2022-10-21 13:37:39 +00:00
}
2021-12-06 21:10:54 +00:00
Connections {
2023-02-07 14:21:32 +00:00
id: globalConns
2021-12-06 21:10:54 +00:00
target: Global
2023-02-07 14:21:32 +00:00
2023-01-18 09:25:36 +00:00
function onOpenLinkInBrowser ( link: string ) {
2023-01-10 13:19:02 +00:00
changeAppSectionBySectionId ( Constants . appSection . browser )
Qt . callLater ( ( ) = > browserLayoutContainer . item . openUrlInNewTab ( link ) ) ;
2021-12-06 21:10:54 +00:00
}
2022-10-18 09:06:18 +00:00
2023-01-18 09:25:36 +00:00
function onOpenCreateChatView ( ) {
2022-10-18 09:06:18 +00:00
createChatView . opened = true
}
2023-01-18 09:25:36 +00:00
function onCloseCreateChatView ( ) {
2022-10-18 09:06:18 +00:00
createChatView . opened = false
}
2023-02-07 14:21:32 +00:00
function onOpenActivityCenterPopupRequested ( ) {
2023-04-17 08:31:32 +00:00
d . openActivityCenterPopup ( )
2022-07-26 14:23:45 +00:00
}
2023-01-18 09:25:36 +00:00
function onDisplayToastMessage ( title: string , subTitle: string , icon: string , loading: bool , ephNotifType: int , url: string ) {
2023-02-07 14:21:32 +00:00
appMain . rootStore . mainModuleInst . displayEphemeralNotification ( title , subTitle , icon , loading , ephNotifType , url )
2022-12-14 14:40:50 +00:00
}
2023-01-18 09:25:36 +00:00
function onOpenLink ( link: string ) {
2023-07-21 23:08:44 +00:00
console . warn ( "opening external url without asking user" )
2022-12-14 14:40:50 +00:00
// Qt sometimes inserts random HTML tags; and this will break on invalid URL inside QDesktopServices::openUrl(link)
2023-02-07 14:21:32 +00:00
link = appMain . rootStore . plainText ( link )
2023-07-21 23:08:44 +00:00
2022-12-14 14:40:50 +00:00
if ( appMain . rootStore . showBrowserSelector ) {
2023-02-07 14:21:32 +00:00
popups . openChooseBrowserPopup ( link )
2022-12-14 14:40:50 +00:00
} else {
if ( appMain . rootStore . openLinksInStatus ) {
2023-02-07 14:21:32 +00:00
globalConns . onAppSectionBySectionTypeChanged ( Constants . appSection . browser )
globalConns . onOpenLinkInBrowser ( link )
2022-12-14 14:40:50 +00:00
} else {
2023-02-07 14:21:32 +00:00
Qt . openUrlExternally ( link )
2022-12-14 14:40:50 +00:00
}
}
}
2023-02-07 14:21:32 +00:00
function onPlaySendMessageSound ( ) {
sendMessageSound . stop ( )
sendMessageSound . play ( )
}
function onPlayNotificationSound ( ) {
notificationSound . stop ( )
notificationSound . play ( )
}
function onPlayErrorSound ( ) {
errorSound . stop ( )
errorSound . play ( )
}
2023-01-18 09:25:36 +00:00
function onSetNthEnabledSectionActive ( nthSection: int ) {
2022-12-14 14:40:50 +00:00
if ( ! appMain . rootStore . mainModuleInst )
return
appMain . rootStore . mainModuleInst . setNthEnabledSectionActive ( nthSection )
}
2023-01-18 09:25:36 +00:00
function onAppSectionBySectionTypeChanged ( sectionType: int , subsection: int ) {
2022-12-14 14:40:50 +00:00
if ( ! appMain . rootStore . mainModuleInst )
return
appMain . rootStore . mainModuleInst . setActiveSectionBySectionType ( sectionType )
if ( sectionType === Constants . appSection . profile ) {
Global . settingsSubsection = subsection ;
}
}
2023-02-28 15:00:10 +00:00
function onOpenSendModal ( address: string ) {
sendModal . open ( address )
}
function onSwitchToCommunity ( communityId: string ) {
2023-04-28 10:35:18 +00:00
appMain . communitiesStore . setActiveCommunity ( communityId )
2023-02-28 15:00:10 +00:00
}
2021-10-19 10:27:41 +00:00
}
2023-07-27 12:33:33 +00:00
Connections {
target: appMain . communitiesStore
function onImportingCommunityStateChanged ( communityId , state , errorMsg ) {
const community = appMain . communitiesStore . getCommunityDetailsAsJson ( communityId )
let title = ""
let subTitle = ""
let loading = false
let notificationType = Constants . ephemeralNotificationType . normal
let icon = ""
switch ( state )
{
case Constants.communityImported:
if ( community . isControlNode ) {
title = qsTr ( "This device is now the control node for the %1 Community" ) . arg ( community . name )
notificationType = Constants . ephemeralNotificationType . success
icon = "checkmark-circle"
} else {
title = qsTr ( "'%1' community imported" ) . arg ( community . name )
}
break
case Constants.communityImportingInProgress:
title = qsTr ( "Importing community is in progress" )
loading = true
break
case Constants.communityImportingError:
title = qsTr ( "Failed to import community '%1'" ) . arg ( community . name )
subTitle = errorMsg
break
default:
console . error ( "unknown state while importing community: %1" ) . arg ( state )
return
}
Global . displayToastMessage ( title ,
subTitle ,
icon ,
loading ,
notificationType ,
"" )
}
function onCommunityInfoAlreadyRequested ( ) {
Global . displayToastMessage ( qsTr ( "Community data not loaded yet." ) ,
qsTr ( "Please wait for the unfurl to show" ) ,
"" ,
true ,
Constants . ephemeralNotificationType . normal ,
"" )
}
function onCommunityPrivateKeyRemoved ( communityId ) {
const community = appMain . communitiesStore . getCommunityDetailsAsJson ( communityId )
Global . displayToastMessage ( qsTr ( "This device is no longer the control node for the %1 Community" ) . arg ( community . name ) ,
"" ,
"info" ,
false ,
Constants . ephemeralNotificationType . normal ,
"" )
}
}
2023-06-05 15:30:53 +00:00
Connections {
target: Global . applicationWindow
function onActiveChanged ( ) {
if ( Global . applicationWindow . active ) appMain . rootStore . windowActivated ( )
else appMain . rootStore . windowDeactivated ( )
}
}
2021-10-19 10:27:41 +00:00
function changeAppSectionBySectionId ( sectionId ) {
2022-10-18 09:06:18 +00:00
appMain . rootStore . mainModuleInst . setActiveSectionById ( sectionId )
2021-06-11 12:17:23 +00:00
}
2021-02-18 19:14:31 +00:00
Audio {
id: sendMessageSound
2021-12-08 21:20:43 +00:00
store: rootStore
2022-12-08 15:49:14 +00:00
source: "qrc:/imports/assets/audio/send_message.wav"
2021-02-18 19:14:31 +00:00
}
Audio {
id: notificationSound
2021-12-08 21:20:43 +00:00
store: rootStore
2022-12-08 15:49:14 +00:00
source: "qrc:/imports/assets/audio/notification.wav"
2022-01-11 23:16:17 +00:00
}
Audio {
id: errorSound
2022-12-08 15:49:14 +00:00
source: "qrc:/imports/assets/audio/error.mp3"
2022-01-11 23:16:17 +00:00
store: rootStore
2021-02-18 19:14:31 +00:00
}
2022-10-18 09:06:18 +00:00
Loader {
2021-11-10 08:09:31 +00:00
id: appSearch
2022-10-18 09:06:18 +00:00
active: false
asynchronous: true
function openSearchPopup ( ) {
if ( ! active )
active = true
item . openSearchPopup ( )
}
function closeSearchPopup ( ) {
if ( item )
item . closeSearchPopup ( )
2022-11-07 14:56:59 +00:00
2022-10-18 09:06:18 +00:00
active = false
}
sourceComponent: AppSearch {
store: appMain . rootStore . appSearchStore
2022-11-07 14:56:59 +00:00
onClosed: appSearch . active = false
2022-10-18 09:06:18 +00:00
}
2021-11-10 08:09:31 +00:00
}
2023-04-28 10:35:18 +00:00
Loader {
2022-03-07 14:56:05 +00:00
id: statusEmojiPopup
2023-04-28 10:35:18 +00:00
active: appMain . rootStore . mainModuleInst . sectionsLoaded
sourceComponent: StatusEmojiPopup {
width: 360
height: 440
}
2022-03-07 14:56:05 +00:00
}
2023-01-30 21:05:34 +00:00
Loader {
id: statusStickersPopupLoader
2023-03-16 19:05:05 +00:00
active: appMain . rootStore . mainModuleInst . sectionsLoaded
2023-01-30 21:05:34 +00:00
sourceComponent: StatusStickersPopup {
id: statusStickersPopup
2023-02-09 21:49:36 +00:00
store: appMain . rootChatStore
2023-01-30 21:05:34 +00:00
}
2022-11-14 20:21:00 +00:00
}
2022-08-09 15:08:39 +00:00
StatusMainLayout {
2021-09-15 11:40:07 +00:00
id: appLayout
2022-07-26 08:24:59 +00:00
anchors.fill: parent
2021-06-17 18:41:11 +00:00
2022-08-09 15:08:39 +00:00
leftPanel: StatusAppNavBar {
2022-11-28 11:32:29 +00:00
chatItemsModel: SortFilterProxyModel {
sourceModel: appMain . rootStore . mainModuleInst . sectionsModel
filters: [
ValueFilter {
roleName: "sectionType"
value: Constants . appSection . chat
} ,
ValueFilter {
roleName: "enabled"
value: true
}
]
2021-06-17 18:41:11 +00:00
}
2022-11-28 11:32:29 +00:00
chatItemDelegate: navbarButton
communityItemsModel: SortFilterProxyModel {
sourceModel: appMain . rootStore . mainModuleInst . sectionsModel
filters: [
ValueFilter {
roleName: "sectionType"
value: Constants . appSection . community
} ,
ValueFilter {
roleName: "enabled"
value: true
}
]
2021-10-19 10:27:41 +00:00
}
2022-11-28 11:32:29 +00:00
communityItemDelegate: StatusNavBarTabButton {
2022-08-11 12:24:49 +00:00
objectName: "CommunityNavBarButton"
2021-06-17 18:41:11 +00:00
anchors.horizontalCenter: parent . horizontalCenter
2021-10-19 10:27:41 +00:00
name: model . icon . length > 0 ? "" : model . name
icon.name: model . icon
icon.source: model . image
2022-10-12 15:22:23 +00:00
identicon.asset.color: ( hovered || identicon . highlighted || checked ) ? model.color : icon . color
2021-06-17 18:41:11 +00:00
tooltip.text: model . name
2021-10-19 10:27:41 +00:00
checked: model . active
badge.value: model . notificationsCount
badge.visible: model . hasNotification
2021-06-17 18:41:11 +00:00
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme . palette . statusBadge . borderColor
badge.border.width: 2
2021-10-19 10:27:41 +00:00
onClicked: {
changeAppSectionBySectionId ( model . id )
}
2021-06-17 18:41:11 +00:00
2023-01-10 13:19:02 +00:00
popupMenu: Component {
StatusMenu {
id: communityContextMenu
2023-06-07 10:54:31 +00:00
width: 180
2023-01-10 13:19:02 +00:00
property var chatCommunitySectionModule
2022-01-18 20:54:14 +00:00
2023-01-10 13:19:02 +00:00
openHandler: function ( ) {
// we cannot return QVariant if we pass another parameter in a function call
// that's why we're using it this way
appMain . rootStore . mainModuleInst . prepareCommunitySectionModuleForCommunityId ( model . id )
communityContextMenu . chatCommunitySectionModule = appMain . rootStore . mainModuleInst . getCommunitySectionModule ( )
}
2021-06-17 18:41:11 +00:00
2023-01-10 13:19:02 +00:00
StatusAction {
text: qsTr ( "Invite People" )
icon.name: "share-ios"
enabled: model . canManageUsers
onTriggered: {
2023-02-07 14:21:32 +00:00
popups . openInviteFriendsToCommunityPopup ( model ,
2023-01-10 13:19:02 +00:00
communityContextMenu . chatCommunitySectionModule ,
null )
}
2022-09-28 21:07:18 +00:00
}
2021-06-17 18:41:11 +00:00
2023-01-10 13:19:02 +00:00
StatusAction {
text: qsTr ( "View Community" )
icon.name: "group-chat"
2023-02-07 14:21:32 +00:00
onTriggered: popups . openCommunityProfilePopup ( appMain . rootStore , model , communityContextMenu . chatCommunitySectionModule )
2023-01-10 13:19:02 +00:00
}
2021-06-17 18:41:11 +00:00
2023-06-14 08:42:52 +00:00
StatusMenuSeparator { }
2023-06-07 10:54:31 +00:00
MuteChatMenuItem {
enabled: ! model . muted
title: qsTr ( "Mute Community" )
onMuteTriggered: {
communityContextMenu . chatCommunitySectionModule . setCommunityMuted ( interval )
communityContextMenu . close ( )
}
}
2023-04-11 16:48:32 +00:00
StatusAction {
2023-06-07 10:54:31 +00:00
enabled: model . muted
text: qsTr ( "Unmute Community" )
2023-06-21 20:37:51 +00:00
icon.name: "notification"
2023-04-11 16:48:32 +00:00
onTriggered: {
2023-06-07 10:54:31 +00:00
communityContextMenu . chatCommunitySectionModule . setCommunityMuted ( Constants . MutingVariations . Unmuted )
2023-04-11 16:48:32 +00:00
}
}
2023-06-14 08:42:52 +00:00
StatusMenuSeparator { visible: leaveCommunityMenuItem . enabled }
2021-06-17 18:41:11 +00:00
2023-01-10 13:19:02 +00:00
StatusAction {
2023-06-14 08:42:52 +00:00
id: leaveCommunityMenuItem
2023-06-19 14:16:35 +00:00
enabled: model . memberRole !== Constants . memberRole . owner
2023-06-14 08:42:52 +00:00
text: {
if ( model . spectated )
return qsTr ( "Close Community" )
return qsTr ( "Leave Community" )
}
icon.name: model . spectated ? "close-circle" : "arrow-left"
2023-01-10 13:19:02 +00:00
type: StatusAction . Type . Danger
2023-06-14 08:42:52 +00:00
onTriggered: model . spectated ? communityContextMenu . chatCommunitySectionModule . leaveCommunity ( )
: popups . openLeaveCommunityPopup ( model . name , model . id , model . outroMessage )
2023-01-10 13:19:02 +00:00
}
2021-06-17 18:41:11 +00:00
}
}
}
2022-11-28 11:32:29 +00:00
regularItemsModel: SortFilterProxyModel {
sourceModel: appMain . rootStore . mainModuleInst . sectionsModel
filters: [
RangeFilter {
roleName: "sectionType"
minimumValue: Constants . appSection . wallet
maximumValue: Constants . appSection . communitiesPortal
} ,
ValueFilter {
roleName: "enabled"
value: true
}
]
}
regularItemDelegate: navbarButton
delegateHeight: 40
profileComponent: StatusNavBarTabButton {
2021-06-17 18:41:11 +00:00
id: profileButton
2022-08-12 13:19:16 +00:00
objectName: "statusProfileNavBarTabButton"
2021-09-27 10:31:17 +00:00
property bool opened: false
2021-10-19 10:27:41 +00:00
2022-03-30 15:30:28 +00:00
name: appMain . rootStore . userProfileInst . name
2021-12-01 12:46:21 +00:00
icon.source: appMain . rootStore . userProfileInst . icon
2022-11-28 11:32:29 +00:00
implicitWidth: 32
implicitHeight: 32
2022-09-05 09:24:37 +00:00
identicon.asset.width: width
identicon.asset.height: height
2022-08-11 11:55:08 +00:00
identicon.asset.charactersLen: 2
identicon.asset.color: Utils . colorForPubkey ( appMain . rootStore . userProfileInst . pubKey )
2022-12-01 10:24:25 +00:00
identicon.ringSettings.ringSpecModel: Utils . getColorHashAsJson ( appMain . rootStore . userProfileInst . pubKey ,
2022-12-13 09:37:27 +00:00
appMain . rootStore . userProfileInst . preferredName )
2022-04-01 11:46:32 +00:00
2021-06-17 18:41:11 +00:00
badge.visible: true
2022-07-26 08:24:59 +00:00
badge . anchors {
left: undefined
top: undefined
right: profileButton . right
bottom: profileButton . bottom
margins: 0
rightMargin: - badge . border . width
bottomMargin: - badge . border . width
}
badge.implicitHeight: 12
badge.implicitWidth: 12
badge.border.width: 2
2021-06-17 18:41:11 +00:00
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme . palette . statusAppNavBar . backgroundColor
2022-06-10 09:01:31 +00:00
badge.color: {
switch ( appMain . rootStore . userProfileInst . currentUserStatus ) {
case Constants.currentUserStatus.automatic:
case Constants.currentUserStatus.alwaysOnline:
return Style . current . green ;
default:
return Style . current . midGrey ;
}
}
2022-07-26 08:24:59 +00:00
onClicked: userStatusContextMenu . opened ? userStatusContextMenu . close ( ) : userStatusContextMenu . open ( )
2021-06-17 18:41:11 +00:00
UserStatusContextMenu {
id: userStatusContextMenu
2022-07-04 10:47:29 +00:00
y: profileButton . y - userStatusContextMenu . height + profileButton . height
x: profileButton . x + profileButton . width + 5
2021-11-04 23:38:57 +00:00
store: appMain . rootStore
2021-06-17 18:41:11 +00:00
}
2022-11-28 11:32:29 +00:00
}
Component {
id: navbarButton
StatusNavBarTabButton {
id: navbar
objectName: model . name + "-navbar"
anchors.horizontalCenter: parent . horizontalCenter
name: model . icon . length > 0 ? "" : model . name
icon.name: model . icon
icon.source: model . image
2022-12-12 12:39:25 +00:00
tooltip.text: Utils . translatedSectionName ( model . sectionType , model . name )
2022-11-28 11:32:29 +00:00
checked: model . active
badge.value: model . notificationsCount
badge.visible: model . hasNotification
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme . palette . statusBadge . borderColor
badge.border.width: 2
onClicked: {
changeAppSectionBySectionId ( model . id )
}
}
2021-06-17 18:41:11 +00:00
}
2021-07-28 12:50:48 +00:00
}
2021-06-17 18:41:11 +00:00
2022-08-09 15:08:39 +00:00
rightPanel: ColumnLayout {
spacing: 0
2022-08-31 10:55:42 +00:00
objectName: "mainRightView"
2022-09-02 14:56:14 +00:00
ColumnLayout {
id: bannersLayout
2023-01-30 10:42:26 +00:00
enabled: ! localAppSettings . testEnvironment
visible: enabled
2022-09-02 14:56:14 +00:00
property var updateBanner: null
property var connectedBanner: null
2022-10-18 09:06:18 +00:00
readonly property bool isConnected: appMain . rootStore . mainModuleInst . isOnline
2022-09-02 14:56:14 +00:00
function processUpdateAvailable ( ) {
if ( ! updateBanner )
updateBanner = updateBannerComponent . createObject ( this )
2022-03-03 21:00:52 +00:00
}
2022-09-02 14:56:14 +00:00
function processConnected ( ) {
if ( ! connectedBanner )
connectedBanner = connectedBannerComponent . createObject ( this )
2021-10-19 10:27:41 +00:00
}
2022-03-17 16:15:38 +00:00
2022-09-02 14:56:14 +00:00
Layout.fillWidth: true
Layout.maximumHeight: implicitHeight
spacing: 1
onIsConnectedChanged: {
processConnected ( )
2023-01-11 14:06:31 +00:00
}
Component.onCompleted: {
if ( ! isConnected )
processConnected ( )
2022-03-17 16:15:38 +00:00
}
2022-09-02 14:56:14 +00:00
Connections {
target: rootStore . aboutModuleInst
2023-01-18 09:25:36 +00:00
function onAppVersionFetched ( available: bool , version: string , url: string ) {
2022-09-02 14:56:14 +00:00
rootStore . setLatestVersionInfo ( available , version , url ) ;
2023-06-12 17:54:19 +00:00
// TODO when we re-implement check for updates, uncomment this
// bannersLayout.processUpdateAvailable()
2022-09-02 14:56:14 +00:00
}
2022-03-17 16:15:38 +00:00
}
2022-09-02 14:56:14 +00:00
ModuleWarning {
id: testnetBanner
2022-09-29 14:30:25 +00:00
objectName: "testnetBanner"
2022-09-02 14:56:14 +00:00
Layout.fillWidth: true
2023-06-27 19:56:44 +00:00
text: qsTr ( "Testnet mode enabled. All balances, transactions and dApp interactions will be on testnets." )
2022-09-02 14:56:14 +00:00
buttonText: qsTr ( "Turn off" )
2023-06-27 19:56:44 +00:00
type: ModuleWarning . Warning
iconName: "warning"
2022-09-02 14:56:14 +00:00
active: appMain . rootStore . profileSectionStore . walletStore . areTestNetworksEnabled
2023-06-27 19:56:44 +00:00
onClicked: Global . openTestnetPopup ( )
onCloseClicked: Global . openTestnetPopup ( )
2022-03-17 16:15:38 +00:00
}
2022-09-02 14:56:14 +00:00
ModuleWarning {
id: secureYourSeedPhrase
2022-09-29 14:30:25 +00:00
objectName: "secureYourSeedPhraseBanner"
2022-09-02 14:56:14 +00:00
Layout.fillWidth: true
2022-09-14 19:05:44 +00:00
active: ! appMain . rootStore . profileSectionStore . profileStore . userDeclinedBackupBanner
2022-09-02 14:56:14 +00:00
&& ! appMain . rootStore . profileSectionStore . profileStore . privacyStore . mnemonicBackedUp
type: ModuleWarning . Danger
text: qsTr ( "Secure your seed phrase" )
buttonText: qsTr ( "Back up now" )
2023-02-07 14:21:32 +00:00
onClicked: popups . openBackUpSeedPopup ( )
2022-09-02 14:56:14 +00:00
onCloseClicked: {
appMain . rootStore . profileSectionStore . profileStore . userDeclinedBackupBanner = true
}
2022-03-17 16:15:38 +00:00
}
2021-12-17 17:42:12 +00:00
2022-09-15 07:31:38 +00:00
ModuleWarning {
Layout.fillWidth: true
2023-04-28 10:35:18 +00:00
readonly property int progress: appMain . communitiesStore . discordImportProgress
readonly property bool inProgress: ( progress > 0 && progress < 100 ) || appMain . communitiesStore . discordImportInProgress
2022-09-15 07:31:38 +00:00
readonly property bool finished: progress >= 100
2023-04-28 10:35:18 +00:00
readonly property bool cancelled: appMain . communitiesStore . discordImportCancelled
readonly property bool stopped: appMain . communitiesStore . discordImportProgressStopped
readonly property int errors: appMain . communitiesStore . discordImportErrorsCount
readonly property int warnings: appMain . communitiesStore . discordImportWarningsCount
readonly property string communityId: appMain . communitiesStore . discordImportCommunityId
readonly property string communityName: appMain . communitiesStore . discordImportCommunityName
2022-09-15 07:31:38 +00:00
active: ! cancelled && ( inProgress || finished || stopped )
type: errors ? ModuleWarning.Type.Danger : ModuleWarning . Type . Success
text: {
if ( finished || stopped ) {
if ( errors )
return qsTr ( "The import of ‘ %1’ from Discord to Status was stopped: <a href='#'>Critical issues found</a>" ) . arg ( communityName )
let result = qsTr ( "‘ %1’ was successfully imported from Discord to Status" ) . arg ( communityName ) + " <a href='#'>"
if ( warnings )
result += qsTr ( "Details (%1)" ) . arg ( qsTr ( "%n issue(s)" , "" , warnings ) )
else
result += qsTr ( "Details" )
result += "</a>"
return result
}
if ( inProgress ) {
let result = qsTr ( "Importing ‘ %1’ from Discord to Status" ) . arg ( communityName ) + " <a href='#'>"
if ( warnings )
result += qsTr ( "Check progress (%1)" ) . arg ( qsTr ( "%n issue(s)" , "" , warnings ) )
else
result += qsTr ( "Check progress" )
result += "</a>"
return result
}
2022-12-09 11:35:29 +00:00
return ""
2022-09-15 07:31:38 +00:00
}
2023-04-28 10:35:18 +00:00
onLinkActivated: popups . openDiscordImportProgressPopup ( )
2022-09-15 07:31:38 +00:00
progressValue: progress
closeBtnVisible: finished || stopped
buttonText: finished && ! errors ? qsTr ( "Visit your Community" ) : ""
onClicked: function ( ) {
2023-04-28 10:35:18 +00:00
appMain . communitiesStore . setActiveCommunity ( communityId )
2022-09-15 07:31:38 +00:00
}
onCloseClicked: {
hide ( ) ;
}
}
2022-12-01 15:10:51 +00:00
ModuleWarning {
id: downloadingArchivesBanner
Layout.fillWidth: true
2023-04-28 10:35:18 +00:00
active: appMain . communitiesStore . downloadingCommunityHistoryArchives
2022-12-01 15:10:51 +00:00
type: ModuleWarning . Danger
text: qsTr ( "Downloading message history archives, DO NOT CLOSE THE APP until this banner disappears." )
closeBtnVisible: false
}
2022-09-15 07:31:38 +00:00
2023-01-18 10:36:28 +00:00
ModuleWarning {
id: mailserverConnectionBanner
2023-01-18 16:37:36 +00:00
type: ModuleWarning . Warning
text: qsTr ( "Can not connect to store node. Retrying automatically" )
2023-01-18 10:36:28 +00:00
onCloseClicked: hide ( )
Layout.fillWidth: true
}
2022-09-02 14:56:14 +00:00
Component {
id: connectedBannerComponent
ModuleWarning {
2022-10-04 16:38:52 +00:00
id: connectedBanner
property bool isConnected: true
2022-09-02 14:56:14 +00:00
2022-09-29 14:30:25 +00:00
objectName: "connectionInfoBanner"
2022-09-02 14:56:14 +00:00
Layout.fillWidth: true
2023-03-01 20:59:08 +00:00
text: isConnected ? qsTr ( "You are back online" ) : qsTr ( "Internet connection lost. Reconnect to ensure everything is up to date." )
2022-09-02 14:56:14 +00:00
type: isConnected ? ModuleWarning.Success : ModuleWarning . Danger
function updateState ( ) {
if ( isConnected )
showFor ( )
else
show ( ) ;
}
Component.onCompleted: {
2022-10-04 16:38:52 +00:00
connectedBanner . isConnected = Qt . binding ( ( ) = > bannersLayout . isConnected ) ;
2022-09-02 14:56:14 +00:00
}
onIsConnectedChanged: {
updateState ( ) ;
}
onCloseClicked: {
hide ( ) ;
}
onHideFinished: {
destroy ( )
2023-01-30 10:42:26 +00:00
bannersLayout . connectedBanner = null
2022-09-02 14:56:14 +00:00
}
}
}
Component {
id: updateBannerComponent
ModuleWarning {
readonly property string version: appMain . rootStore . latestVersion
readonly property bool updateAvailable: appMain . rootStore . newVersionAvailable
2022-09-29 14:35:16 +00:00
objectName: "appVersionUpdateBanner"
2022-09-02 14:56:14 +00:00
Layout.fillWidth: true
type: ModuleWarning . Success
text: updateAvailable ? qsTr ( "A new version of Status (%1) is available" ) . arg ( version )
: qsTr ( "Your version is up to date" )
buttonText: updateAvailable ? qsTr ( "Update" )
: qsTr ( "Close" )
function updateState ( ) {
if ( updateAvailable )
show ( )
else
showFor ( 5000 )
}
Component.onCompleted: {
updateState ( )
}
onUpdateAvailableChanged: {
updateState ( ) ;
}
onClicked: {
if ( updateAvailable )
Global . openDownloadModal ( appMain . rootStore . newVersionAvailable ,
appMain . rootStore . latestVersion ,
appMain . rootStore . downloadURL )
else
close ( )
}
onCloseClicked: {
if ( updateAvailable )
appMain . rootStore . resetLastVersion ( ) ;
hide ( )
}
onHideFinished: {
destroy ( )
2023-01-30 10:42:26 +00:00
bannersLayout . updateBanner = null
2022-09-02 14:56:14 +00:00
}
}
}
2023-03-01 20:59:08 +00:00
ConnectionWarnings {
id: walletBlockchainConnectionBanner
objectName: "walletBlockchainConnectionBanner"
Layout.fillWidth: true
websiteDown: Constants . walletConnections . blockchains
2023-03-23 10:23:02 +00:00
withCache: networkConnectionStore . balanceCache
2023-04-03 17:13:23 +00:00
networkConnectionStore: appMain . networkConnectionStore
tooltipMessage: qsTr ( "Pocket Network (POKT) & Infura are currently both unavailable for %1. Balances for those chains are as of %2." ) . arg ( jointChainIdString ) . arg ( lastCheckedAt )
toastText: {
2023-03-01 20:59:08 +00:00
switch ( connectionState ) {
case Constants.ConnectionStatus.Success:
return qsTr ( "Pocket Network (POKT) connection successful" )
case Constants.ConnectionStatus.Failure:
if ( completelyDown ) {
if ( withCache )
2023-04-03 17:13:23 +00:00
return qsTr ( "POKT & Infura down. Token balances are as of %1." ) . arg ( lastCheckedAt )
2023-03-01 20:59:08 +00:00
else
2023-04-03 17:13:23 +00:00
return qsTr ( "POKT & Infura down. Token balances cannot be retrieved." )
2023-03-01 20:59:08 +00:00
}
else if ( chainIdsDown . length > 0 ) {
if ( chainIdsDown . length > 2 ) {
2023-04-03 17:13:23 +00:00
return qsTr ( "POKT & Infura down for <a href='#'>multiple chains </a>. Token balances for those chains cannot be retrieved." )
2023-03-01 20:59:08 +00:00
}
else if ( chainIdsDown . length === 1 ) {
2023-04-03 17:13:23 +00:00
return qsTr ( "POKT & Infura down for %1. %1 token balances are as of %2." ) . arg ( jointChainIdString ) . arg ( lastCheckedAt )
2023-03-01 20:59:08 +00:00
}
else {
2023-04-03 17:13:23 +00:00
return qsTr ( "POKT & Infura down for %1. %1 token balances cannot be retrieved." ) . arg ( jointChainIdString )
2023-03-01 20:59:08 +00:00
}
}
else
return ""
case Constants.ConnectionStatus.Retrying:
return qsTr ( "Retrying connection to Pocket Network (POKT)." )
default:
return ""
}
}
}
ConnectionWarnings {
id: walletCollectiblesConnectionBanner
objectName: "walletCollectiblesConnectionBanner"
Layout.fillWidth: true
websiteDown: Constants . walletConnections . collectibles
2023-03-23 10:23:02 +00:00
withCache: networkConnectionStore . collectiblesCache
2023-04-03 17:13:23 +00:00
networkConnectionStore: appMain . networkConnectionStore
toastText: {
2023-03-01 20:59:08 +00:00
switch ( connectionState ) {
case Constants.ConnectionStatus.Success:
return qsTr ( "Opensea connection successful" )
case Constants.ConnectionStatus.Failure:
if ( withCache ) {
2023-04-03 17:13:23 +00:00
return qsTr ( "Opensea down. Collectibles are as of %1." ) . arg ( lastCheckedAt )
2023-03-01 20:59:08 +00:00
}
else {
2023-04-03 17:13:23 +00:00
return qsTr ( "Opensea down." )
2023-03-01 20:59:08 +00:00
}
case Constants.ConnectionStatus.Retrying:
return qsTr ( "Retrying connection to Opensea..." )
default:
return ""
}
}
}
ConnectionWarnings {
id: walletMarketConnectionBanner
objectName: "walletMarketConnectionBanner"
Layout.fillWidth: true
websiteDown: Constants . walletConnections . market
2023-03-23 10:23:02 +00:00
withCache: networkConnectionStore . marketValuesCache
2023-04-03 17:13:23 +00:00
networkConnectionStore: appMain . networkConnectionStore
toastText: {
2023-03-01 20:59:08 +00:00
switch ( connectionState ) {
case Constants.ConnectionStatus.Success:
return qsTr ( "CryptoCompare and CoinGecko connection successful" )
case Constants.ConnectionStatus.Failure: {
if ( withCache ) {
2023-04-03 17:13:23 +00:00
return qsTr ( "CryptoCompare and CoinGecko down. Market values are as of %1." ) . arg ( lastCheckedAt )
2023-03-01 20:59:08 +00:00
}
else {
2023-04-03 17:13:23 +00:00
return qsTr ( "CryptoCompare and CoinGecko down. Market values cannot be retrieved." )
2023-03-01 20:59:08 +00:00
}
}
case Constants.ConnectionStatus.Retrying:
return qsTr ( "Retrying connection to CryptoCompare and CoinGecko..." )
2023-04-03 17:13:23 +00:00
default:
return ""
2023-03-01 20:59:08 +00:00
}
}
}
2022-09-02 14:56:14 +00:00
}
2022-07-12 08:56:47 +00:00
2022-05-13 15:27:26 +00:00
Item {
2022-06-23 15:28:30 +00:00
Layout.fillWidth: true
2021-12-17 17:42:12 +00:00
Layout.fillHeight: true
2022-05-13 15:27:26 +00:00
StackLayout {
id: appView
anchors.fill: parent
currentIndex: {
2022-10-18 09:06:18 +00:00
const activeSectionType = appMain . rootStore . mainModuleInst . activeSection . sectionType
if ( activeSectionType === Constants . appSection . chat )
2022-05-13 15:27:26 +00:00
return Constants . appViewStackIndex . chat
2022-10-18 09:06:18 +00:00
if ( activeSectionType === Constants . appSection . community ) {
2023-01-10 13:19:02 +00:00
for ( let i = this . children . length - 1 ; i >= 0 ; i -- ) {
2022-10-18 09:06:18 +00:00
var obj = this . children [ i ]
2023-01-10 13:19:02 +00:00
if ( obj && obj . sectionId && obj . sectionId === appMain . rootStore . mainModuleInst . activeSection . id ) {
2022-05-13 15:27:26 +00:00
return i
}
2021-12-17 17:42:12 +00:00
}
2022-05-13 15:27:26 +00:00
// Should never be here, correct index must be returned from the for loop above
2023-01-10 13:19:02 +00:00
console . error ( "Wrong section type:" , appMain . rootStore . mainModuleInst . activeSection . sectionType ,
"or section id: " , appMain . rootStore . mainModuleInst . activeSection . id )
2022-05-13 15:27:26 +00:00
return Constants . appViewStackIndex . community
}
2022-10-18 09:06:18 +00:00
if ( activeSectionType === Constants . appSection . communitiesPortal )
2022-05-13 15:27:26 +00:00
return Constants . appViewStackIndex . communitiesPortal
2022-10-18 09:06:18 +00:00
if ( activeSectionType === Constants . appSection . wallet )
2022-05-13 15:27:26 +00:00
return Constants . appViewStackIndex . wallet
2022-10-18 09:06:18 +00:00
if ( activeSectionType === Constants . appSection . browser )
2022-05-13 15:27:26 +00:00
return Constants . appViewStackIndex . browser
2022-10-18 09:06:18 +00:00
if ( activeSectionType === Constants . appSection . profile )
2022-05-13 15:27:26 +00:00
return Constants . appViewStackIndex . profile
2022-10-18 09:06:18 +00:00
if ( activeSectionType === Constants . appSection . node )
2022-05-13 15:27:26 +00:00
return Constants . appViewStackIndex . node
2021-12-17 17:42:12 +00:00
2022-05-13 15:27:26 +00:00
// We should never end up here
2022-10-18 09:06:18 +00:00
console . error ( "AppMain: Unknown section type" )
2021-11-01 20:10:50 +00:00
}
2021-10-19 10:27:41 +00:00
2022-05-13 15:27:26 +00:00
// NOTE:
// If we ever change stack layout component order we need to updade
// Constants.appViewStackIndex accordingly
2023-01-30 21:05:34 +00:00
Loader {
id: personalChatLayoutLoader
2023-02-07 14:21:32 +00:00
asynchronous: true
2023-04-17 20:45:17 +00:00
active: false
2023-01-30 21:05:34 +00:00
sourceComponent: {
if ( appMain . rootStore . mainModuleInst . chatsLoadingFailed ) {
return errorStateComponent
}
2023-03-16 19:05:05 +00:00
if ( appMain . rootStore . mainModuleInst . sectionsLoaded ) {
2023-01-30 21:05:34 +00:00
return personalChatLayoutComponent
}
return loadingStateComponent
}
2023-04-17 20:45:17 +00:00
// Do not unload section data from the memory in order not
// to reset scroll, not send text input and etc during the
// sections switching
Binding on active {
when: appView . currentIndex === Constants . appViewStackIndex . chat
value: true
restoreMode: Binding . RestoreNone
}
2023-06-07 11:37:44 +00:00
2023-01-30 21:05:34 +00:00
Component {
id: loadingStateComponent
Item {
anchors.fill: parent
Row {
anchors.centerIn: parent
spacing: 6
StatusBaseText {
2023-05-02 09:37:12 +00:00
anchors.verticalCenter: parent . verticalCenter
2023-03-16 19:05:05 +00:00
text: qsTr ( "Loading sections..." )
2023-01-30 21:05:34 +00:00
}
2023-04-28 10:35:18 +00:00
LoadingAnimation { anchors.verticalCenter: parent . verticalCenter }
2023-01-30 21:05:34 +00:00
}
}
}
2023-06-07 11:37:44 +00:00
2023-01-30 21:05:34 +00:00
Component {
id: errorStateComponent
Item {
anchors.fill: parent
StatusBaseText {
text: qsTr ( "Error loading chats, try closing the app and restarting" )
anchors.centerIn: parent
}
}
}
Component {
id: personalChatLayoutComponent
2021-06-17 18:41:11 +00:00
2023-01-30 21:05:34 +00:00
ChatLayout {
id: chatLayoutContainer
2021-12-17 17:42:12 +00:00
2023-02-27 12:11:51 +00:00
Binding {
target: rootDropAreaPanel
property: "enabled"
value: chatLayoutContainer . currentIndex === 0 // Meaning: Chats / channels view
when: visible
restoreMode: Binding . RestoreBindingOrValue
}
2023-02-09 21:49:36 +00:00
2023-03-17 18:58:07 +00:00
rootStore: ChatStores . RootStore {
contactsStore: appMain . rootStore . contactStore
2023-04-11 08:09:01 +00:00
communityTokensStore: appMain . communityTokensStore
2023-03-17 18:58:07 +00:00
emojiReactionsModel: appMain . rootStore . emojiReactionsModel
openCreateChat: createChatView . opened
chatCommunitySectionModule: appMain . rootStore . mainModuleInst . getChatSectionModule ( )
2023-04-04 11:31:04 +00:00
networkConnectionStore: appMain . networkConnectionStore
2023-03-17 18:58:07 +00:00
}
2023-05-04 18:36:35 +00:00
createChatPropertiesStore: appMain . createChatPropertiesStore
2023-04-28 10:35:18 +00:00
emojiPopup: statusEmojiPopup . item
2023-03-07 16:34:36 +00:00
stickersPopup: statusStickersPopupLoader . item
2021-12-21 09:26:13 +00:00
2023-03-07 16:34:36 +00:00
onProfileButtonClicked: {
2023-01-30 21:05:34 +00:00
Global . changeAppSectionBySectionType ( Constants . appSection . profile ) ;
}
2022-01-04 12:06:05 +00:00
2023-03-07 16:34:36 +00:00
onOpenAppSearch: {
2023-01-30 21:05:34 +00:00
appSearch . openSearchPopup ( )
}
}
2022-05-13 15:27:26 +00:00
}
2021-12-17 17:42:12 +00:00
}
2021-06-17 18:41:11 +00:00
2023-04-28 10:35:18 +00:00
Loader {
active: appView . currentIndex === Constants . appViewStackIndex . communitiesPortal
asynchronous: true
CommunitiesPortalLayout {
anchors.fill: parent
communitiesStore: appMain . communitiesStore
2023-06-16 18:38:32 +00:00
assetsModel: SortFilterProxyModel {
sourceModel: appMain . communitiesStore . communitiesModuleInst . tokenList
proxyRoles: ExpressionRole {
function tokenIcon ( symbol ) {
return Constants . tokenIcon ( symbol )
}
name: "iconSource"
expression: ! ! model . icon ? model.icon : tokenIcon ( model . symbol )
}
}
collectiblesModel: SortFilterProxyModel {
sourceModel: appMain . communitiesStore . communitiesModuleInst . collectiblesModel
proxyRoles: ExpressionRole {
function icon ( icon ) {
return ! ! icon ? icon : Style . png ( "tokens/DEFAULT-TOKEN" )
}
name: "iconSource"
expression: icon ( model . icon )
}
}
2023-04-28 10:35:18 +00:00
notificationCount: appMain . activityCenterStore . unreadNotificationsCount
hasUnseenNotifications: activityCenterStore . hasUnseenNotifications
}
2021-12-17 17:42:12 +00:00
}
2021-11-10 12:48:22 +00:00
2022-10-18 09:06:18 +00:00
Loader {
2023-01-10 13:19:02 +00:00
active: appView . currentIndex === Constants . appViewStackIndex . wallet
2022-10-18 09:06:18 +00:00
asynchronous: true
sourceComponent: WalletLayout {
store: appMain . rootStore
contactsStore: appMain . rootStore . profileSectionStore . contactsStore
2023-04-28 10:35:18 +00:00
emojiPopup: statusEmojiPopup . item
2022-10-17 10:17:25 +00:00
sendModalPopup: sendModal
2023-04-04 11:31:04 +00:00
networkConnectionStore: appMain . networkConnectionStore
2022-05-13 15:27:26 +00:00
}
2023-01-10 13:19:02 +00:00
onLoaded: item . showSigningPhrasePopup ( )
2022-05-13 15:27:26 +00:00
}
2022-05-23 13:11:30 +00:00
2022-05-13 15:27:26 +00:00
Loader {
id: browserLayoutContainer
2023-01-10 13:19:02 +00:00
active: appView . currentIndex === Constants . appViewStackIndex . browser
2022-10-18 09:06:18 +00:00
asynchronous: true
sourceComponent: BrowserLayout {
globalStore: appMain . rootStore
sendTransactionModal: sendModal
}
2022-05-13 15:27:26 +00:00
// Loaders do not have access to the context, so props need to be set
// Adding a "_" to avoid a binding loop
// Not Refactored Yet
// property var _chatsModel: chatsModel.messageView
// Not Refactored Yet
// property var _walletModel: walletModel
// Not Refactored Yet
// property var _utilsModel: utilsModel
2022-10-18 09:06:18 +00:00
// property var _web3Provider: BrowserStores.Web3ProviderStore.web3ProviderInst
2022-05-13 15:27:26 +00:00
}
2021-11-10 08:09:31 +00:00
2022-10-18 09:06:18 +00:00
Loader {
2023-01-10 13:19:02 +00:00
active: appView . currentIndex === Constants . appViewStackIndex . profile
2022-10-18 09:06:18 +00:00
asynchronous: true
sourceComponent: ProfileLayout {
store: appMain . rootStore . profileSectionStore
globalStore: appMain . rootStore
systemPalette: appMain . sysPalette
2023-04-28 10:35:18 +00:00
emojiPopup: statusEmojiPopup . item
2023-04-04 11:31:04 +00:00
networkConnectionStore: appMain . networkConnectionStore
2022-10-18 09:06:18 +00:00
}
2021-12-17 17:42:12 +00:00
}
2022-01-31 13:29:27 +00:00
2022-10-18 09:06:18 +00:00
Loader {
2023-01-10 13:19:02 +00:00
active: appView . currentIndex === Constants . appViewStackIndex . node
2022-10-18 09:06:18 +00:00
asynchronous: true
sourceComponent: NodeLayout { }
2022-05-13 15:27:26 +00:00
}
2021-06-17 18:41:11 +00:00
2022-05-13 15:27:26 +00:00
Repeater {
2023-04-17 20:45:17 +00:00
model: SortFilterProxyModel {
sourceModel: appMain . rootStore . mainModuleInst . sectionsModel
filters: ValueFilter {
roleName: "sectionType"
value: Constants . appSection . community
}
}
delegate: Loader {
id: communityLoader
readonly property string sectionId: model . id
Layout.fillWidth: true
Layout.alignment: Qt . AlignLeft | Qt . AlignTop
Layout.fillHeight: true
asynchronous: true
active: false
// Do not unload section data from the memory in order not
// to reset scroll, not send text input and etc during the
// sections switching
Binding on active {
when: sectionId === appMain . rootStore . mainModuleInst . activeSection . id
value: true
restoreMode: Binding . RestoreNone
}
sourceComponent: ChatLayout {
id: chatLayoutComponent
Binding {
target: rootDropAreaPanel
property: "enabled"
value: chatLayoutComponent . currentIndex === 0 // Meaning: Chats / channels view
when: visible
restoreMode: Binding . RestoreBindingOrValue
}
2023-06-21 20:37:51 +00:00
Connections {
target: Global
function onSwitchToCommunitySettings ( communityId: string ) {
if ( communityId !== model . id )
return
chatLayoutComponent . currentIndex = 1 // Settings
}
}
2023-04-17 20:45:17 +00:00
2023-04-28 10:35:18 +00:00
emojiPopup: statusEmojiPopup . item
2023-04-17 20:45:17 +00:00
stickersPopup: statusStickersPopupLoader . item
sectionItemModel: model
2023-07-24 11:31:31 +00:00
communitySettingsDisabled: production && appMain . rootStore . profileSectionStore . walletStore . areTestNetworksEnabled
2023-04-17 20:45:17 +00:00
rootStore: ChatStores . RootStore {
contactsStore: appMain . rootStore . contactStore
communityTokensStore: appMain . communityTokensStore
emojiReactionsModel: appMain . rootStore . emojiReactionsModel
openCreateChat: createChatView . opened
chatCommunitySectionModule: {
appMain . rootStore . mainModuleInst . prepareCommunitySectionModuleForCommunityId ( model . id )
return appMain . rootStore . mainModuleInst . getCommunitySectionModule ( )
2022-05-13 15:27:26 +00:00
}
}
2023-04-17 20:45:17 +00:00
onProfileButtonClicked: {
Global . changeAppSectionBySectionType ( Constants . appSection . profile ) ;
}
onOpenAppSearch: {
appSearch . openSearchPopup ( )
}
2022-05-13 15:27:26 +00:00
}
}
}
2021-12-17 17:42:12 +00:00
}
2021-06-17 18:41:11 +00:00
2022-10-18 09:06:18 +00:00
Loader {
2022-07-22 11:24:28 +00:00
id: createChatView
2022-05-13 15:27:26 +00:00
property bool opened: false
2023-03-16 19:05:05 +00:00
active: appMain . rootStore . mainModuleInst . sectionsLoaded && opened
2021-12-30 12:39:47 +00:00
2022-10-18 09:06:18 +00:00
asynchronous: true
2022-05-13 15:27:26 +00:00
anchors.top: parent . top
anchors.topMargin: 8
anchors.rightMargin: 8
anchors.bottom: parent . bottom
anchors.right: parent . right
2023-01-30 21:05:34 +00:00
width: active ?
parent . width - Constants . chatSectionLeftColumnWidth -
anchors . rightMargin - anchors.leftMargin : 0
2022-07-12 08:56:47 +00:00
2022-10-18 09:06:18 +00:00
sourceComponent: CreateChatView {
2023-03-17 18:58:07 +00:00
rootStore: ChatStores . RootStore {
contactsStore: appMain . rootStore . contactStore
2023-04-11 08:09:01 +00:00
communityTokensStore: appMain . communityTokensStore
2023-03-17 18:58:07 +00:00
emojiReactionsModel: appMain . rootStore . emojiReactionsModel
openCreateChat: createChatView . opened
chatCommunitySectionModule: appMain . rootStore . mainModuleInst . getChatSectionModule ( )
}
2023-05-04 18:36:35 +00:00
createChatPropertiesStore: appMain . createChatPropertiesStore
2023-04-28 10:35:18 +00:00
emojiPopup: statusEmojiPopup . item
2023-01-30 21:05:34 +00:00
stickersPopup: statusStickersPopupLoader . item
2022-06-01 14:49:57 +00:00
}
2022-05-17 14:09:22 +00:00
}
}
2022-06-01 14:49:57 +00:00
} // ColumnLayout
2021-06-17 18:41:11 +00:00
2022-07-26 14:23:45 +00:00
Component {
id: activityCenterPopupComponent
ActivityCenterPopup {
2022-11-04 14:23:33 +00:00
// TODO get screen size // Taken from old code top bar height was fixed there to 56
2023-04-17 08:31:32 +00:00
readonly property int _buttonSize : 56
2022-11-04 14:23:33 +00:00
x: parent . width - width - Style . current . smallPadding
y: parent . y + _buttonSize
height: appView . height - _buttonSize * 2
2023-03-22 18:05:31 +00:00
store: ChatStores . RootStore {
contactsStore: appMain . rootStore . contactStore
2023-04-11 08:09:01 +00:00
communityTokensStore: appMain . communityTokensStore
2023-03-22 18:05:31 +00:00
emojiReactionsModel: appMain . rootStore . emojiReactionsModel
openCreateChat: createChatView . opened
chatCommunitySectionModule: appMain . rootStore . mainModuleInst . getChatSectionModule ( )
}
2022-10-26 16:00:20 +00:00
activityCenterStore: appMain . activityCenterStore
2022-07-26 14:23:45 +00:00
}
}
2021-10-19 10:27:41 +00:00
// Add SendModal here as it is used by the Wallet as well as the Browser
2021-06-17 18:41:11 +00:00
Loader {
id: sendModal
active: false
2022-02-04 13:07:48 +00:00
2022-07-19 15:09:20 +00:00
function open ( address = "" ) {
2021-06-17 18:41:11 +00:00
this . active = true
2022-07-19 15:09:20 +00:00
this . item . addressText = address ;
2021-06-17 18:41:11 +00:00
this . item . open ( )
2020-11-03 10:29:56 +00:00
}
2021-06-17 18:41:11 +00:00
function closed ( ) {
// this.sourceComponent = undefined // kill an opened instance
this . active = false
2020-11-03 10:29:56 +00:00
}
2021-12-07 23:15:17 +00:00
property var selectedAccount
2022-11-23 17:58:22 +00:00
property bool isBridgeTx
2021-06-17 18:41:11 +00:00
sourceComponent: SendModal {
onClosed: {
sendModal . closed ( )
2022-11-23 17:58:22 +00:00
sendModal . isBridgeTx = false
2021-06-17 18:41:11 +00:00
}
2020-12-28 20:03:57 +00:00
}
2021-12-07 23:15:17 +00:00
onLoaded: {
2022-04-12 09:10:55 +00:00
if ( ! ! sendModal . selectedAccount ) {
2022-06-27 13:41:47 +00:00
item . selectedAccount = sendModal . selectedAccount
2021-12-07 23:15:17 +00:00
}
2022-11-23 17:58:22 +00:00
if ( isBridgeTx )
item . isBridgeTx = sendModal . isBridgeTx
2021-12-07 23:15:17 +00:00
}
2020-12-28 20:03:57 +00:00
}
2021-06-17 18:41:11 +00:00
Action {
shortcut: "Ctrl+1"
2022-09-28 10:50:15 +00:00
onTriggered: {
Global . setNthEnabledSectionActive ( 0 )
}
2020-12-28 20:03:57 +00:00
}
2021-06-17 18:41:11 +00:00
Action {
shortcut: "Ctrl+2"
2022-09-28 10:50:15 +00:00
onTriggered: {
Global . setNthEnabledSectionActive ( 1 )
}
2020-12-28 20:03:57 +00:00
}
2021-06-17 18:41:11 +00:00
Action {
shortcut: "Ctrl+3"
2022-09-28 10:50:15 +00:00
onTriggered: {
Global . setNthEnabledSectionActive ( 2 )
}
2021-06-17 18:41:11 +00:00
}
Action {
2022-09-28 10:50:15 +00:00
shortcut: "Ctrl+4"
onTriggered: {
Global . setNthEnabledSectionActive ( 3 )
}
2021-06-17 18:41:11 +00:00
}
2022-09-28 10:50:15 +00:00
Action {
shortcut: "Ctrl+5"
onTriggered: {
Global . setNthEnabledSectionActive ( 4 )
}
}
Action {
shortcut: "Ctrl+6"
onTriggered: {
Global . setNthEnabledSectionActive ( 5 )
}
}
Action {
shortcut: "Ctrl+7"
onTriggered: {
Global . setNthEnabledSectionActive ( 6 )
}
}
Action {
shortcut: "Ctrl+8"
onTriggered: {
Global . setNthEnabledSectionActive ( 7 )
}
}
Action {
shortcut: "Ctrl+9"
onTriggered: {
Global . setNthEnabledSectionActive ( 8 )
}
}
2021-06-17 18:41:11 +00:00
Action {
shortcut: "Ctrl+K"
onTriggered: {
2022-02-16 16:13:45 +00:00
// FIXME the focus is no longer on the AppMain when the popup is opened, so this does not work to close
2022-10-18 09:06:18 +00:00
if ( ! channelPickerLoader . active )
channelPickerLoader . active = true
if ( channelPickerLoader . item . opened ) {
channelPickerLoader . item . close ( )
channelPickerLoader . active = false
2021-06-17 18:41:11 +00:00
} else {
2022-10-18 09:06:18 +00:00
channelPickerLoader . item . open ( )
2021-06-17 18:41:11 +00:00
}
}
}
2022-02-16 16:13:45 +00:00
Action {
shortcut: "Ctrl+F"
onTriggered: {
// FIXME the focus is no longer on the AppMain when the popup is opened, so this does not work to close
2022-10-18 09:06:18 +00:00
if ( appSearch . active ) {
2022-02-16 16:13:45 +00:00
appSearch . closeSearchPopup ( )
} else {
appSearch . openSearchPopup ( )
}
}
}
2021-06-17 18:41:11 +00:00
2022-10-18 09:06:18 +00:00
Loader {
id: channelPickerLoader
active: false
asynchronous: true
sourceComponent: StatusSearchListPopup {
searchBoxPlaceholder: qsTr ( "Where do you want to go?" )
model: rootStore . chatSearchModel
delegate: StatusListItem {
property var modelData
property bool isCurrentItem: true
function filterAccepts ( searchText ) {
2022-12-07 15:14:48 +00:00
const lowerCaseSearchText = searchText . toLowerCase ( )
return title . toLowerCase ( ) . includes ( lowerCaseSearchText ) || label . toLowerCase ( ) . includes ( lowerCaseSearchText )
2022-10-18 09:06:18 +00:00
}
2022-02-04 13:07:48 +00:00
2022-10-18 09:06:18 +00:00
title: modelData ? modelData.name : ""
label: modelData ? modelData.sectionName : ""
highlighted: isCurrentItem
sensor.hoverEnabled: false
statusListItemIcon {
name: modelData ? modelData.name : ""
active: true
}
asset.width: 30
asset.height: 30
2023-06-14 20:18:03 +00:00
asset.color: modelData ? modelData . color ? modelData.color : Utils . colorForColorId ( modelData . colorId ) : ""
2022-10-18 09:06:18 +00:00
asset.name: modelData ? modelData.icon : ""
2023-06-14 20:18:03 +00:00
asset.charactersLen: 2
asset.letterSize: asset . _twoLettersSize
ringSettings.ringSpecModel: modelData ? modelData.colorHash : undefined
2022-02-04 13:07:48 +00:00
}
2022-10-18 09:06:18 +00:00
onAboutToShow: rootStore . rebuildChatSearchModel ( )
onSelected: {
rootStore . setActiveSectionChat ( modelData . sectionId , modelData . chatId )
close ( )
2022-02-04 13:07:48 +00:00
}
2022-01-24 17:59:59 +00:00
}
2020-12-28 20:03:57 +00:00
}
}
2021-09-23 11:59:29 +00:00
2022-07-14 11:03:36 +00:00
StatusListView {
2022-05-05 10:28:54 +00:00
id: toastArea
2022-10-20 12:58:56 +00:00
objectName: "ephemeralNotificationList"
2022-05-05 10:28:54 +00:00
anchors.right: parent . right
anchors.rightMargin: 8
anchors.bottom: parent . bottom
anchors.bottomMargin: 60
2022-08-22 12:56:28 +00:00
width: 343
height: Math . min ( parent . height - 120 , toastArea . contentHeight )
2022-05-05 10:28:54 +00:00
spacing: 8
verticalLayoutDirection: ListView . BottomToTop
model: appMain . rootStore . mainModuleInst . ephemeralNotificationModel
2023-05-03 08:37:19 +00:00
clip: false
2022-08-22 12:56:28 +00:00
2022-05-05 10:28:54 +00:00
delegate: StatusToastMessage {
primaryText: model . title
secondaryText: model . subTitle
icon.name: model . icon
loading: model . loading
type: model . ephNotifType
linkUrl: model . url
duration: model . durationInMs
2022-06-21 10:42:27 +00:00
onClicked: {
2022-09-29 13:45:34 +00:00
appMain . rootStore . mainModuleInst . ephemeralNotificationClicked ( model . timestamp )
2022-06-21 10:42:27 +00:00
this . open = false
}
2022-05-05 10:28:54 +00:00
onLinkActivated: {
2023-02-28 15:00:10 +00:00
if ( link . startsWith ( "#" ) ) // internal link to section
globalConns . onAppSectionBySectionTypeChanged ( link . substring ( 1 ) )
else
Global . openLink ( link )
2022-05-05 10:28:54 +00:00
}
2022-08-22 12:56:28 +00:00
2022-05-05 10:28:54 +00:00
onClose: {
2022-09-29 13:45:34 +00:00
appMain . rootStore . mainModuleInst . removeEphemeralNotification ( model . timestamp )
2022-05-05 10:28:54 +00:00
}
}
}
2021-09-23 11:59:29 +00:00
Component.onCompleted: {
2022-03-07 20:34:59 +00:00
const whitelist = appMain . rootStore . messagingStore . getLinkPreviewWhitelist ( )
2022-02-10 20:02:02 +00:00
try {
const whiteListedSites = JSON . parse ( whitelist )
let settingsUpdated = false
2021-11-18 19:34:03 +00:00
2022-02-10 20:02:02 +00:00
// Add Status links to whitelist
whiteListedSites . push ( { title: "Status" , address: Constants . deepLinkPrefix , imageSite: false } )
2023-05-23 20:01:39 +00:00
whiteListedSites . push ( { title: "Status" , address: Constants . externalStatusLink , imageSite: false } )
2022-02-10 20:02:02 +00:00
let settings = localAccountSensitiveSettings . whitelistedUnfurlingSites
2021-12-13 14:24:21 +00:00
2022-02-10 20:02:02 +00:00
if ( ! settings ) {
settings = { }
}
2021-12-13 14:24:21 +00:00
2023-04-28 10:35:18 +00:00
// Set Status links as true. We intercept those URLs so it is privacy-safe
2023-05-23 20:01:39 +00:00
if ( ! settings [ Constants . deepLinkPrefix ] || ! settings [ Constants . externalStatusLink ] ) {
2022-02-10 20:02:02 +00:00
settings [ Constants . deepLinkPrefix ] = true
2023-05-23 20:01:39 +00:00
settings [ Constants . externalStatusLink ] = true
2022-02-10 20:02:02 +00:00
settingsUpdated = true
}
const whitelistedHostnames = [ ]
// Add whitelisted sites in to app settings that are not already there
whiteListedSites . forEach ( site = > {
if ( ! settings . hasOwnProperty ( site . address ) ) {
settings [ site . address ] = false
settingsUpdated = true
}
whitelistedHostnames . push ( site . address )
} )
// Remove any whitelisted sites from app settings that don't exist in the
// whitelist from status-go
Object . keys ( settings ) . forEach ( settingsHostname = > {
if ( ! whitelistedHostnames . includes ( settingsHostname ) ) {
delete settings [ settingsHostname ]
settingsUpdated = true
}
} )
if ( settingsUpdated ) {
localAccountSensitiveSettings . whitelistedUnfurlingSites = settings
}
} catch ( e ) {
console . error ( 'Could not parse the whitelist for sites' , e )
}
2022-10-18 09:06:18 +00:00
Global . settingsLoaded ( )
2021-09-23 11:59:29 +00:00
}
2022-09-13 10:03:25 +00:00
2023-06-30 09:24:08 +00:00
Loader {
2022-09-13 10:03:25 +00:00
id: keycardPopup
2023-06-30 09:24:08 +00:00
active: false
sourceComponent: KeycardPopup {
2022-10-18 09:06:18 +00:00
sharedKeycardModule: appMain . rootStore . mainModuleInst . keycardSharedModule
2022-09-13 10:03:25 +00:00
}
2023-06-30 09:24:08 +00:00
onLoaded: {
keycardPopup . item . open ( )
}
2022-09-13 10:03:25 +00:00
}
2022-10-06 15:47:55 +00:00
DropAreaPanel {
2022-12-09 11:35:29 +00:00
id: rootDropAreaPanel
2023-02-27 12:11:51 +00:00
2022-10-06 15:47:55 +00:00
width: appMain . width
height: appMain . height
}
2023-06-14 19:06:13 +00:00
Loader {
id: userAgreementLoader
active: production && ! localAppSettings . testEnvironment
sourceComponent: UserAgreementPopup {
visible: appMain . visible
onClosed: userAgreementLoader . active = false
}
}
2020-05-11 21:24:08 +00:00
}