status-desktop/ui/main.qml

407 lines
11 KiB
QML
Raw Normal View History

2020-06-17 19:18:31 +00:00
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import Qt.labs.platform 1.1
import QtQml.StateMachine 1.14 as DSM
import Qt.labs.settings 1.0
import QtQuick.Window 2.12
import QtQml 2.13
2020-07-12 16:47:46 +00:00
import QtQuick.Window 2.0
import QtQuick.Controls.Universal 2.12
2020-07-12 16:47:46 +00:00
import "./onboarding"
import "./app"
import "./sounds"
import "./shared"
import "./imports"
ApplicationWindow {
property bool hasAccounts: !!loginModel.rowCount()
property bool removeMnemonicAfterLogin: false
property alias dragAndDrop: dragTarget
property bool popupOpened: false
Universal.theme: Universal.System
Settings {
id: globalSettings
category: "global"
fileName: profileModel.globalSettingsFile
property string locale: "en"
property int theme: 2
}
id: applicationWindow
minimumWidth: 900
2020-11-18 14:01:09 +00:00
minimumHeight: 600
width: 1232
height: 770
color: Style.current.background
title: {
// Set application settings
//% "Status Desktop"
Qt.application.name = qsTrId("status-desktop")
Qt.application.organization = "Status"
Qt.application.domain = "status.im"
return Qt.application.name
}
visible: true
2020-05-18 15:07:30 +00:00
Action {
shortcut: StandardKey.FullScreen
onTriggered: {
if (visibility === Window.FullScreen) {
showNormal()
} else {
showFullScreen()
}
}
}
Action {
shortcut: "Ctrl+M"
onTriggered: {
if (visibility === Window.Minimized) {
showNormal()
} else {
showMinimized()
}
}
}
2021-02-22 17:26:24 +00:00
Action {
shortcut: "Ctrl+W"
2021-04-20 20:15:16 +00:00
enabled: loader.item ? loader.item.currentView !== Utils.getAppSectionIndex(Constants.browser)
: true
2021-02-22 17:26:24 +00:00
onTriggered: {
applicationWindow.visible = false;
}
}
Action {
shortcut: "Ctrl+Q"
onTriggered: {
Qt.quit()
}
}
onClosing: {
2021-02-22 22:10:47 +00:00
if(loader.sourceComponent == app){
if(loader.item.appSettings.quitOnClose){
Qt.quit();
} else {
applicationWindow.visible = false;
close.accepted = false;
}
}
}
2020-07-12 16:47:46 +00:00
Component.onCompleted: {
Style.changeTheme(globalSettings.theme)
setX(Qt.application.screens[0].width / 2 - width / 2);
setY(Qt.application.screens[0].height / 2 - height / 2);
2020-07-12 16:47:46 +00:00
}
signal navigateTo(string path)
property bool currentlyHasANotification: false
onActiveChanged: {
if (active && currentlyHasANotification) {
currentlyHasANotification = false
// QML doesn't have a function to hide notifications, but this does the trick
systemTray.hide()
systemTray.show()
}
}
2020-05-18 15:07:30 +00:00
SystemTrayIcon {
id: systemTray
2020-05-18 15:07:30 +00:00
visible: true
icon.source: applicationWindow.Universal.theme === Universal.Dark ?
"shared/img/status-logo.svg" :
"shared/img/status-logo-light-theme.svg";
2020-05-18 15:07:30 +00:00
menu: Menu {
MenuItem {
visible: !applicationWindow.visible
text: qsTr("Open Status")
onTriggered: {
applicationWindow.visible = true;
applicationWindow.requestActivate();
}
}
MenuSeparator {
visible: !applicationWindow.visible
}
2020-05-18 15:07:30 +00:00
MenuItem {
//% "Quit"
text: qsTrId("quit")
2020-05-18 15:07:30 +00:00
onTriggered: Qt.quit()
}
}
onActivated: {
if (reason === SystemTrayIcon.Context) {
return
}
2020-05-18 15:07:30 +00:00
applicationWindow.show()
applicationWindow.raise()
applicationWindow.requestActivate()
}
}
DSM.StateMachine {
id: stateMachine
initialState: onboardingState
running: true
DSM.State {
id: onboardingState
initialState: hasAccounts ? stateLogin : keysMainState
DSM.State {
id: stateIntro
onEntered: loader.sourceComponent = intro
}
DSM.State {
id: keysMainState
onEntered: loader.sourceComponent = keysMain
DSM.SignalTransition {
targetState: genKeyState
signal: applicationWindow.navigateTo
guard: path === "GenKey"
}
}
DSM.State {
id: existingKeyState
onEntered: loader.sourceComponent = existingKey
DSM.SignalTransition {
targetState: appState
signal: onboardingModel.loginResponseChanged
guard: !error
}
}
DSM.State {
id: genKeyState
onEntered: loader.sourceComponent = genKey
DSM.SignalTransition {
targetState: appState
signal: onboardingModel.loginResponseChanged
guard: !error
}
}
DSM.State {
id: stateLogin
onEntered: loader.sourceComponent = login
DSM.SignalTransition {
targetState: appState
signal: loginModel.loginResponseChanged
guard: !error
}
DSM.SignalTransition {
targetState: genKeyState
signal: applicationWindow.navigateTo
guard: path === "GenKey"
}
}
2020-06-12 20:47:44 +00:00
DSM.SignalTransition {
targetState: hasAccounts ? stateLogin : stateIntro
2020-06-12 20:47:44 +00:00
signal: applicationWindow.navigateTo
guard: path === "InitialState"
}
DSM.SignalTransition {
targetState: existingKeyState
signal: applicationWindow.navigateTo
guard: path === "ExistingKey"
}
DSM.SignalTransition {
targetState: keysMainState
signal: applicationWindow.navigateTo
guard: path === "KeysMain"
}
DSM.FinalState {
id: onboardingDoneState
}
}
2020-09-22 15:12:48 +00:00
DSM.State {
id: appState
onEntered: loader.sourceComponent = app
DSM.SignalTransition {
targetState: stateLogin
signal: loginModel.onLoggedOut
}
}
}
Loader {
id: loader
2020-05-18 15:07:30 +00:00
anchors.fill: parent
2021-02-22 22:10:47 +00:00
property var appSettings
}
2020-05-18 15:07:30 +00:00
DropArea {
id: dragTarget
signal droppedOnValidScreen(var drop)
property alias droppedUrls: rptDraggedPreviews.model
readonly property int chatView: Utils.getAppSectionIndex(Constants.chat)
readonly property int timelineView: Utils.getAppSectionIndex(Constants.timeline)
property bool enabled: containsDrag && loader.item &&
(
// in chat view
(loader.item.currentView === chatView &&
(
// in a one-to-one chat
chatsModel.activeChannel.chatType === Constants.chatTypeOneToOne ||
// in a private group chat
chatsModel.activeChannel.chatType === Constants.chatTypePrivateGroupChat
)
) ||
// in timeline view
loader.item.currentView === timelineView
)
width: applicationWindow.width
height: applicationWindow.height
function cleanup() {
rptDraggedPreviews.model = []
}
onDropped: (drop) => {
if (enabled) {
droppedOnValidScreen(drop)
}
cleanup()
}
onEntered: {
// needed because drag.urls is not a normal js array
rptDraggedPreviews.model = drag.urls.filter(img => Utils.hasDragNDropImageExtension(img))
}
onPositionChanged: {
rptDraggedPreviews.x = drag.x
rptDraggedPreviews.y = drag.y
}
onExited: cleanup()
Rectangle {
id: dropRectangle
width: parent.width
height: parent.height
color: Style.current.transparent
opacity: 0.8
states: [
State {
when: dragTarget.enabled
PropertyChanges {
target: dropRectangle
color: Style.current.background
}
}
]
}
Repeater {
id: rptDraggedPreviews
Image {
source: modelData
width: 80
height: 80
sourceSize.width: 160
sourceSize.height: 160
fillMode: Image.PreserveAspectFit
x: index * 10 + rptDraggedPreviews.x
y: index * 10 + rptDraggedPreviews.y
z: 1
}
}
}
Component {
id: app
AppMain {}
}
Component {
id: intro
Intro {
btnGetStarted.onClicked: applicationWindow.navigateTo("KeysMain")
}
}
Component {
id: keysMain
KeysMain {
btnGenKey.onClicked: applicationWindow.navigateTo("GenKey")
btnExistingKey.onClicked: applicationWindow.navigateTo("ExistingKey")
}
}
Component {
id: existingKey
2020-06-12 20:47:44 +00:00
ExistingKey {
onClosed: function () {
removeMnemonicAfterLogin = false
if (hasAccounts) {
applicationWindow.navigateTo("InitialState")
} else {
applicationWindow.navigateTo("KeysMain")
}
2020-06-12 20:47:44 +00:00
}
}
}
Component {
id: genKey
GenKey {
2020-06-13 15:17:54 +00:00
onClosed: function () {
if (hasAccounts) {
applicationWindow.navigateTo("InitialState")
} else {
applicationWindow.navigateTo("KeysMain")
}
2020-06-13 15:17:54 +00:00
}
}
}
Component {
id: login
Login {
2020-06-12 20:47:44 +00:00
onGenKeyClicked: function () {
applicationWindow.navigateTo("GenKey")
}
onExistingKeyClicked: function () {
applicationWindow.navigateTo("ExistingKey")
}
}
}
NotificationWindow {
id: notificationWindow
}
}
/*##^##
Designer {
D{i:0;formeditorZoom:0.5}
}
##^##*/