amnezia-client/client/ui/qml/Pages2/PageHome.qml
lunardunno 059257fc58
Merge branch 'dev' into check_sudo_permissions (#1441)
* refactoring: improved the performance of secure_settings

* bugfix: fixed textFields on PageSetupWizardCredentials

* bugfix: fixed scrolling by keys on PageSettingsApiServerInfo

* chore: hide site links for ios (#1374)

* chore: fixed log output with split tunneling info

* chore: hide "open logs folder" button for mobule platforms

* chore: fixed again log output with split tunneling info

* chore: bump version

* Install apparmor (#1379)

Install apparmor

* chore: returned the backup page for androidTV

* Enable PFS for Windows IKEv2

* refactoring: moved api info pages from ServerInfo

* refactoring: moved gateway interaction functions to a separate class

* bugfix: fixed storeEndpoint parsing

* chore: returned links for mobile platforms

* Update VPN protocol descriptions

* Update VPN description texts

* feature: added pages for subscription settings feature

* feature: added page for export api native configs

* feature: added error handling and minor ui fixes

* refactor: update ios build configuration to use automatic code signing and prebuilt OpenVPNAdapter framework

* feat: remove OpenVPNAdapter submodule

* feat: remove ios openvpn script and associated cmake configuration

* Update README.md

* Update README_RU.md

* Update README.md

fix link

* feature: added share vpn key to subscription settings page

* bugfix: fixed possible crush on android

* add timeouts in ipc client init

* apply timeouts only for Windows

* apply format to file

* refactoring: simplified the validity check of the config before connection

- improved project structure

* bugfix: fixed visability of share drawer

* feature: added 409 error handling from server response

* chore: fixed android build

* chore: fixed qr code display

* Rewrite timeouts using waitForSource

* feature: added error messages handler

* feature: added issued configs info parsing

* feature: added functionality to revoke api configs

* chore: added links to instructions

* chore: fixed qr code with vpnkey processing

* chore: fixed native config post processing

* chore: added link to android tv instruction

* change node to IpcProcessTun2SocksReplica

* chore: minor ui fixes

* Update Windows OpenSSL  (#1426)

* Update Windows OpenSSL to 3.0.16 and add shared library for QSslSocket plugin

* chore: update link to submodule 3rd-prebuild

---------

Co-authored-by: vladimir.kuznetsov <nethiuswork@gmail.com>

* chore: added 404 handling for revoke configs

- added revoke before remove api server for premium v2

* chore: added log to see proxy decrypt errors

* chore: minor ui fix

* chore: bump version

* bugfix: fixed mobile controllers initialization (#1436)

* bugfix: fixed mobile controllers initialization

* chore: bump version

* Merge pull request #1440 from amnezia-vpn/feature/subscription-settings-page

feature/subscription settings page

---------

Co-authored-by: vladimir.kuznetsov <nethiuswork@gmail.com>
Co-authored-by: pokamest <pokamest@gmail.com>
Co-authored-by: Mykola Baibuz <mykola.baibuz@gmail.com>
Co-authored-by: Yaroslav Yashin <yaroslav.yashin@gmail.com>
Co-authored-by: KsZnak <ksu@amnezia.org>
Co-authored-by: Cyril Anisimov <CyAn84@gmail.com>
2025-03-01 16:08:52 +04:00

432 lines
16 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import SortFilterProxyModel 0.2
import PageEnum 1.0
import ProtocolEnum 1.0
import ContainerProps 1.0
import ContainersModelFilters 1.0
import Style 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
Connections {
objectName: "pageControllerConnections"
target: PageController
function onRestorePageHomeState(isContainerInstalled) {
drawer.openTriggered()
if (isContainerInstalled) {
containersDropDown.rootButtonClickedFunction()
}
}
}
Item {
objectName: "homeColumnItem"
anchors.fill: parent
anchors.bottomMargin: drawer.collapsedHeight
ColumnLayout {
objectName: "homeColumnLayout"
anchors.fill: parent
anchors.topMargin: 12
anchors.bottomMargin: 16
AdLabel {
id: adLabel
Layout.fillWidth: true
Layout.preferredHeight: adLabel.contentHeight
Layout.leftMargin: 16
Layout.rightMargin: 16
Layout.bottomMargin: 22
}
BasicButtonType {
id: loggingButton
objectName: "loggingButton"
property bool isLoggingEnabled: SettingsController.isLoggingEnabled
Layout.alignment: Qt.AlignHCenter
implicitHeight: 36
defaultColor: AmneziaStyle.color.transparent
hoveredColor: AmneziaStyle.color.translucentWhite
pressedColor: AmneziaStyle.color.sheerWhite
disabledColor: AmneziaStyle.color.mutedGray
textColor: AmneziaStyle.color.mutedGray
borderWidth: 0
visible: isLoggingEnabled ? true : false
text: qsTr("Logging enabled")
Keys.onEnterPressed: loggingButton.clicked()
Keys.onReturnPressed: loggingButton.clicked()
onClicked: {
PageController.goToPage(PageEnum.PageSettingsLogging)
}
}
ConnectButton {
id: connectButton
objectName: "connectButton"
Layout.fillHeight: true
Layout.alignment: Qt.AlignCenter
}
BasicButtonType {
id: splitTunnelingButton
objectName: "splitTunnelingButton"
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
leftPadding: 16
rightPadding: 16
implicitHeight: 36
defaultColor: AmneziaStyle.color.transparent
hoveredColor: AmneziaStyle.color.translucentWhite
pressedColor: AmneziaStyle.color.sheerWhite
disabledColor: AmneziaStyle.color.mutedGray
textColor: AmneziaStyle.color.mutedGray
borderWidth: 0
buttonTextLabel.lineHeight: 20
buttonTextLabel.font.pixelSize: 14
buttonTextLabel.font.weight: 500
property bool isSplitTunnelingEnabled: SitesModel.isTunnelingEnabled || AppSplitTunnelingModel.isTunnelingEnabled ||
ServersModel.isDefaultServerDefaultContainerHasSplitTunneling
text: isSplitTunnelingEnabled ? qsTr("Split tunneling enabled") : qsTr("Split tunneling disabled")
leftImageSource: isSplitTunnelingEnabled ? "qrc:/images/controls/split-tunneling.svg" : ""
leftImageColor: ""
rightImageSource: "qrc:/images/controls/chevron-down.svg"
Keys.onEnterPressed: splitTunnelingButton.clicked()
Keys.onReturnPressed: splitTunnelingButton.clicked()
onClicked: {
homeSplitTunnelingDrawer.openTriggered()
}
HomeSplitTunnelingDrawer {
id: homeSplitTunnelingDrawer
objectName: "homeSplitTunnelingDrawer"
parent: root
}
}
}
}
DrawerType2 {
id: drawer
objectName: "drawerProtocol"
anchors.fill: parent
collapsedStateContent: Item {
objectName: "ProtocolDrawerCollapsedContent"
implicitHeight: Qt.platform.os !== "ios" ? root.height * 0.9 : screen.height * 0.77
Component.onCompleted: {
drawer.expandedHeight = implicitHeight
}
ColumnLayout {
id: collapsed
objectName: "collapsedColumnLayout"
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
Component.onCompleted: {
drawer.collapsedHeight = collapsed.implicitHeight
}
DividerType {
Layout.topMargin: 10
Layout.fillWidth: false
Layout.preferredWidth: 20
Layout.preferredHeight: 2
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
}
RowLayout {
objectName: "rowLayout"
Layout.topMargin: 14
Layout.leftMargin: 24
Layout.rightMargin: 24
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
spacing: 0
Connections {
objectName: "drawerConnections"
target: drawer
function onCursorEntered() {
if (drawer.isCollapsedStateActive) {
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.hoveredColor
collapsedButtonHeader.opacity = 0.8
} else {
collapsedButtonHeader.opacity = 1
}
}
function onCursorExited() {
if (drawer.isCollapsedStateActive) {
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.defaultColor
collapsedButtonHeader.opacity = 1
} else {
collapsedButtonHeader.opacity = 1
}
}
function onPressed(pressed, entered) {
if (drawer.isCollapsedStateActive) {
collapsedButtonChevron.backgroundColor = pressed ? collapsedButtonChevron.pressedColor : entered ? collapsedButtonChevron.hoveredColor : collapsedButtonChevron.defaultColor
collapsedButtonHeader.opacity = 0.7
} else {
collapsedButtonHeader.opacity = 1
}
}
}
Header1TextType {
id: collapsedButtonHeader
objectName: "collapsedButtonHeader"
Layout.maximumWidth: drawer.width - 48 - 18 - 12
maximumLineCount: 2
elide: Qt.ElideRight
text: ServersModel.defaultServerName
horizontalAlignment: Qt.AlignHCenter
Behavior on opacity {
PropertyAnimation { duration: 200 }
}
}
ImageButtonType {
id: collapsedButtonChevron
objectName: "collapsedButtonChevron"
Layout.leftMargin: 8
visible: drawer.isCollapsedStateActive()
hoverEnabled: false
image: "qrc:/images/controls/chevron-down.svg"
imageColor: AmneziaStyle.color.paleGray
icon.width: 18
icon.height: 18
backgroundRadius: 16
horizontalPadding: 4
topPadding: 4
bottomPadding: 3
Keys.onEnterPressed: collapsedButtonChevron.clicked()
Keys.onReturnPressed: collapsedButtonChevron.clicked()
onClicked: {
if (drawer.isCollapsedStateActive()) {
drawer.openTriggered()
}
}
}
}
RowLayout {
objectName: "rowLayoutLabel"
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.topMargin: 8
Layout.bottomMargin: drawer.isCollapsedStateActive ? 44 : ServersModel.isDefaultServerFromApi ? 61 : 16
spacing: 0
BasicButtonType {
enabled: (ServersModel.defaultServerImagePathCollapsed !== "") && drawer.isCollapsedStateActive
hoverEnabled: enabled
implicitHeight: 36
leftPadding: 16
rightPadding: 16
defaultColor: AmneziaStyle.color.transparent
hoveredColor: AmneziaStyle.color.translucentWhite
pressedColor: AmneziaStyle.color.sheerWhite
disabledColor: AmneziaStyle.color.transparent
textColor: AmneziaStyle.color.mutedGray
buttonTextLabel.lineHeight: 16
buttonTextLabel.font.pixelSize: 13
buttonTextLabel.font.weight: 400
text: drawer.isCollapsedStateActive ? ServersModel.defaultServerDescriptionCollapsed : ServersModel.defaultServerDescriptionExpanded
leftImageSource: ServersModel.defaultServerImagePathCollapsed
leftImageColor: ""
changeLeftImageSize: false
rightImageSource: hoverEnabled ? "qrc:/images/controls/chevron-down.svg" : ""
onClicked: {
ServersModel.processedIndex = ServersModel.defaultIndex
if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) {
if (ServersModel.getProcessedServerData("isCountrySelectionAvailable")) {
PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries)
} else {
PageController.showBusyIndicator(true)
let result = ApiSettingsController.getAccountInfo(false)
PageController.showBusyIndicator(false)
if (!result) {
return
}
PageController.goToPage(PageEnum.PageSettingsApiServerInfo)
}
} else {
PageController.goToPage(PageEnum.PageSettingsServerInfo)
}
}
}
}
}
ColumnLayout {
id: serversMenuHeader
objectName: "serversMenuHeader"
anchors.top: collapsed.bottom
anchors.right: parent.right
anchors.left: parent.left
RowLayout {
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
spacing: 8
visible: !ServersModel.isDefaultServerFromApi
DropDownType {
id: containersDropDown
objectName: "containersDropDown"
rootButtonImageColor: AmneziaStyle.color.midnightBlack
rootButtonBackgroundColor: AmneziaStyle.color.paleGray
rootButtonBackgroundHoveredColor: AmneziaStyle.color.mistyGray
rootButtonBackgroundPressedColor: AmneziaStyle.color.cloudyGray
rootButtonHoveredBorderColor: AmneziaStyle.color.transparent
rootButtonDefaultBorderColor: AmneziaStyle.color.transparent
rootButtonTextTopMargin: 8
rootButtonTextBottomMargin: 8
enabled: drawer.isOpened
text: ServersModel.defaultServerDefaultContainerName
textColor: AmneziaStyle.color.midnightBlack
headerText: qsTr("VPN protocol")
headerBackButtonImage: "qrc:/images/controls/arrow-left.svg"
rootButtonClickedFunction: function() {
containersDropDown.openTriggered()
}
drawerParent: root
listView: HomeContainersListView {
id: containersListView
objectName: "containersListView"
rootWidth: root.width
Connections {
objectName: "rowLayoutConnections"
target: ServersModel
function onDefaultServerIndexChanged() {
updateContainersModelFilters()
}
}
function updateContainersModelFilters() {
if (ServersModel.isDefaultServerHasWriteAccess()) {
proxyDefaultServerContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
} else {
proxyDefaultServerContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
}
}
model: SortFilterProxyModel {
id: proxyDefaultServerContainersModel
sourceModel: DefaultServerContainersModel
sorters: [
RoleSorter { roleName: "isInstalled"; sortOrder: Qt.DescendingOrder }
]
}
Component.onCompleted: updateContainersModelFilters()
}
}
}
Header2Type {
Layout.fillWidth: true
Layout.topMargin: 48
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: qsTr("Servers")
}
}
ButtonGroup {
id: serversRadioButtonGroup
objectName: "serversRadioButtonGroup"
}
ServersListView {
id: serversMenuContent
objectName: "serversMenuContent"
isFocusable: false
Connections {
target: drawer
// this item shouldn't be focused when drawer is closed
function onIsOpenedChanged() {
serversMenuContent.isFocusable = drawer.isOpened
}
}
}
}
}
}