added page transition effects

- added functionality for buttons on PageSettingsServerData page
This commit is contained in:
vladimir.kuznetsov 2023-06-01 11:25:33 +08:00
parent 1e180489a4
commit de0cd976de
38 changed files with 656 additions and 335 deletions

View file

@ -179,7 +179,7 @@ void AmneziaApplication::registerTypes()
qRegisterMetaType<PageProtocolLogicBase *>("PageProtocolLogicBase *"); qRegisterMetaType<PageProtocolLogicBase *>("PageProtocolLogicBase *");
declareQmlPageEnum(); // declareQmlPageEnum();
declareQmlProtocolEnum(); declareQmlProtocolEnum();
declareQmlContainerEnum(); declareQmlContainerEnum();

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.4 KiB

View file

@ -0,0 +1,6 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17 10C18.6569 10 20 8.65685 20 7C20 5.34315 18.6569 4 17 4C15.3431 4 14 5.34315 14 7C14 8.65685 15.3431 10 17 10Z" stroke="#D7D8DB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="4" y="4" width="6" height="6" rx="1" stroke="#D7D8DB" stroke-width="2"/>
<rect x="14" y="14" width="6" height="6" rx="1" stroke="#D7D8DB" stroke-width="2"/>
<path d="M7.18963 13.8523L10.8078 20H2.91364L7.18963 13.8523Z" stroke="#D7D8DB" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 576 B

View file

@ -0,0 +1,7 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 14C13.1046 14 14 13.1046 14 12C14 10.8954 13.1046 10 12 10C10.8954 10 10 10.8954 10 12C10 13.1046 10.8954 14 12 14Z" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.93006 19.0702C3.05535 17.1949 2.0022 14.6518 2.0022 12.0002C2.0022 9.34853 3.05535 6.80545 4.93006 4.93018" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.75993 16.24C7.20263 15.6818 6.76087 15.0191 6.45993 14.29C5.85157 12.8205 5.85157 11.1695 6.45993 9.7C6.76087 8.97087 7.20263 8.30823 7.75993 7.75" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16.24 7.75977C16.8028 8.33271 17.2449 9.01281 17.54 9.75977C18.1483 11.2293 18.1483 12.8802 17.54 14.3498C17.2391 15.0789 16.7973 15.7415 16.24 16.2998" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M19.0701 4.93018C20.9448 6.80545 21.9979 9.34853 21.9979 12.0002C21.9979 14.6518 20.9448 17.1949 19.0701 19.0702" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V5C3 4.46957 3.21071 3.96086 3.58579 3.58579C3.96086 3.21071 4.46957 3 5 3H16L21 8V19C21 19.5304 20.7893 20.0391 20.4142 20.4142C20.0391 20.7893 19.5304 21 19 21Z" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M17 21V13H7V21" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7 3V8H15" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 652 B

View file

@ -0,0 +1,6 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 2H4C2.89543 2 2 2.89543 2 4V8C2 9.10457 2.89543 10 4 10H20C21.1046 10 22 9.10457 22 8V4C22 2.89543 21.1046 2 20 2Z" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M20 14H4C2.89543 14 2 14.8954 2 16V20C2 21.1046 2.89543 22 4 22H20C21.1046 22 22 21.1046 22 20V16C22 14.8954 21.1046 14 20 14Z" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 6H6.01" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 18H6.01" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 742 B

View file

@ -228,16 +228,26 @@
<file>images/controls/download.svg</file> <file>images/controls/download.svg</file>
<file>ui/qml/Controls2/ProgressBarType.qml</file> <file>ui/qml/Controls2/ProgressBarType.qml</file>
<file>ui/qml/Components/ConnectionTypeSelectionDrawer.qml</file> <file>ui/qml/Components/ConnectionTypeSelectionDrawer.qml</file>
<file>ui/qml/Components/ContainersPageHomeListView.qml</file> <file>ui/qml/Components/HomeContainersListView.qml</file>
<file>ui/qml/Controls2/TextTypes/CaptionTextType.qml</file> <file>ui/qml/Controls2/TextTypes/CaptionTextType.qml</file>
<file>images/controls/settings.svg</file> <file>images/controls/settings.svg</file>
<file>ui/qml/Pages2/PageSettings.qml</file> <file>ui/qml/Pages2/PageSettingsServerInfo.qml</file>
<file>ui/qml/Controls2/PageType.qml</file> <file>ui/qml/Controls2/PageType.qml</file>
<file>ui/qml/Controls2/PopupType.qml</file> <file>ui/qml/Controls2/PopupType.qml</file>
<file>images/controls/edit-3.svg</file> <file>images/controls/edit-3.svg</file>
<file>ui/qml/Pages2/PageSettingsData.qml</file> <file>ui/qml/Pages2/PageSettingsServerData.qml</file>
<file>ui/qml/Components/PageSettingsContainersListView.qml</file> <file>ui/qml/Components/SettingsContainersListView.qml</file>
<file>ui/qml/Controls2/TextTypes/ListItemTitleType.qml</file> <file>ui/qml/Controls2/TextTypes/ListItemTitleType.qml</file>
<file>ui/qml/Controls2/DividerType.qml</file> <file>ui/qml/Controls2/DividerType.qml</file>
<file>ui/qml/Controls2/DrawerType.qml</file>
<file>ui/qml/Controls2/StackViewType.qml</file>
<file>ui/qml/Pages2/PageSettings.qml</file>
<file>images/controls/amnezia.svg</file>
<file>images/controls/app.svg</file>
<file>images/controls/radio.svg</file>
<file>images/controls/save.svg</file>
<file>images/controls/server.svg</file>
<file>ui/qml/Pages2/PageSettingsServerProtocols.qml</file>
<file>ui/qml/Pages2/PageSettingsServerServices.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View file

@ -74,4 +74,3 @@ bool ConnectionController::closeVpnConnection()
emit disconnectFromVpn(); emit disconnectFromVpn();
m_isConnected = false; m_isConnected = false;
} }

View file

@ -49,8 +49,9 @@ void InstallController::installServer(DockerContainer container, QJsonObject& co
server.insert(config_key::containers, QJsonArray{ config }); server.insert(config_key::containers, QJsonArray{ config });
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
m_settings->addServer(server); m_serversModel->addServer(server);
m_settings->setDefaultServer(m_settings->serversCount() - 1); auto newServerIndex = m_serversModel->index(m_serversModel->getServersCount() - 1);
m_serversModel->setData(newServerIndex, true, ServersModel::ServersModelRoles::IsDefaultRole);
emit installServerFinished(); emit installServerFinished();
return; return;

View file

@ -9,7 +9,8 @@ QString PageController::getInitialPage()
{ {
if (m_serversModel->getServersCount()) { if (m_serversModel->getServersCount()) {
if (m_serversModel->getDefaultServerIndex() < 0) { if (m_serversModel->getDefaultServerIndex() < 0) {
m_serversModel->setDefaultServerIndex(0); auto defaultServerIndex = m_serversModel->index(0);
m_serversModel->setData(defaultServerIndex, true, ServersModel::ServersModelRoles::IsDefaultRole);
} }
return getPagePath(PageLoader::PageEnum::PageStart); return getPagePath(PageLoader::PageEnum::PageStart);
} else { } else {

View file

@ -9,7 +9,10 @@
namespace PageLoader namespace PageLoader
{ {
Q_NAMESPACE Q_NAMESPACE
enum class PageEnum { PageStart = 0, PageHome, PageSettings, PageShare, enum class PageEnum { PageStart = 0, PageHome, PageShare,
PageSettingsServersList, PageSettings, PageSettingsServerData, PageSettingsServerInfo,
PageSettingsServerProtocols, PageSettingsServerServices,
PageSetupWizardStart, PageTest, PageSetupWizardCredentials, PageSetupWizardProtocols, PageSetupWizardEasy, PageSetupWizardStart, PageTest, PageSetupWizardCredentials, PageSetupWizardProtocols, PageSetupWizardEasy,
PageSetupWizardProtocolSettings, PageSetupWizardInstalling, PageSetupWizardConfigSource, PageSetupWizardProtocolSettings, PageSetupWizardInstalling, PageSetupWizardConfigSource,
@ -41,6 +44,8 @@ public slots:
signals: signals:
void goToPageHome(); void goToPageHome();
void restorePageHomeState(bool isContainerInstalled = false);
void replaceStartPage();
void showErrorMessage(QString errorMessage); void showErrorMessage(QString errorMessage);
private: private:

View file

@ -86,6 +86,7 @@ void ContainersModel::setCurrentlyProcessedServerIndex(int index)
beginResetModel(); beginResetModel();
m_currentlyProcessedServerIndex = index; m_currentlyProcessedServerIndex = index;
endResetModel(); endResetModel();
emit defaultContainerChanged();
} }
void ContainersModel::setCurrentlyInstalledContainerIndex(int index) void ContainersModel::setCurrentlyInstalledContainerIndex(int index)
@ -115,7 +116,7 @@ void ContainersModel::removeAllContainers()
auto errorCode = serverController.removeAllContainers(m_settings->serverCredentials(m_currentlyProcessedServerIndex)); auto errorCode = serverController.removeAllContainers(m_settings->serverCredentials(m_currentlyProcessedServerIndex));
if (errorCode == ErrorCode::NoError) { if (errorCode == ErrorCode::NoError) {
beginResetModel(); beginResetModel();
m_settings->setContainers(m_currentlyProcessedServerIndex, {}); m_settings->setContainers(m_currentlyProcessedServerIndex, {});
m_settings->setDefaultContainer(m_currentlyProcessedServerIndex, DockerContainer::None); m_settings->setDefaultContainer(m_currentlyProcessedServerIndex, DockerContainer::None);
endResetModel(); endResetModel();
@ -124,6 +125,14 @@ void ContainersModel::removeAllContainers()
//todo process errors //todo process errors
} }
void ContainersModel::clearCachedProfiles()
{
const auto &containers = m_settings->containers(m_currentlyProcessedServerIndex);
for (DockerContainer container : containers.keys()) {
m_settings->clearLastConnectionConfig(m_currentlyProcessedServerIndex, container);
}
}
QHash<int, QByteArray> ContainersModel::roleNames() const { QHash<int, QByteArray> ContainersModel::roleNames() const {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[NameRole] = "name"; roles[NameRole] = "name";

View file

@ -49,6 +49,7 @@ public slots:
int getCurrentlyInstalledContainerIndex(); int getCurrentlyInstalledContainerIndex();
void removeAllContainers(); void removeAllContainers();
void clearCachedProfiles();
protected: protected:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;

View file

@ -17,15 +17,14 @@ bool ServersModel::setData(const QModelIndex &index, const QVariant &value, int
|| index.row() >= static_cast<int>(m_settings->serversCount())) { || index.row() >= static_cast<int>(m_settings->serversCount())) {
return false; return false;
} }
// if (role == DescRole) {
// return m_data[index.row()].desc; switch (role) {
// } case IsDefaultRole: m_settings->setDefaultServer(index.row());
// if (role == AddressRole) { default: return true;
// return m_data[index.row()].address; }
// }
// if (role == IsDefaultRole) { emit dataChanged(index, index);
// return m_data[index.row()].isDefault; return true;
// }
} }
QVariant ServersModel::data(const QModelIndex &index, int role) const QVariant ServersModel::data(const QModelIndex &index, int role) const
@ -58,14 +57,6 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
return QVariant(); return QVariant();
} }
//todo mode to setData?
void ServersModel::setDefaultServerIndex(int index)
{
// beginResetModel();
m_settings->setDefaultServer(index);
// endResetModel();
}
const int ServersModel::getDefaultServerIndex() const int ServersModel::getDefaultServerIndex()
{ {
return m_settings->defaultServerIndex(); return m_settings->defaultServerIndex();
@ -81,14 +72,38 @@ void ServersModel::setCurrentlyProcessedServerIndex(int index)
m_currenlyProcessedServerIndex = index; m_currenlyProcessedServerIndex = index;
} }
bool ServersModel::isDefaultServerCurrentlyProcessed()
{
return m_settings->defaultServerIndex() == m_currenlyProcessedServerIndex;
}
ServerCredentials ServersModel::getCurrentlyProcessedServerCredentials() ServerCredentials ServersModel::getCurrentlyProcessedServerCredentials()
{ {
return qvariant_cast<ServerCredentials>(data(index(m_currenlyProcessedServerIndex), CredentialsRole)); return qvariant_cast<ServerCredentials>(data(index(m_currenlyProcessedServerIndex), CredentialsRole));
} }
void ServersModel::addServer() void ServersModel::addServer(const QJsonObject &server)
{ {
beginResetModel();
m_settings->addServer(server);
endResetModel();
}
void ServersModel::removeServer()
{
beginResetModel();
m_settings->removeServer(m_currenlyProcessedServerIndex);
if (m_settings->defaultServerIndex() == m_currenlyProcessedServerIndex) {
m_settings->setDefaultServer(0);
} else if (m_settings->defaultServerIndex() > m_currenlyProcessedServerIndex) {
m_settings->setDefaultServer(m_settings->defaultServerIndex() - 1);
}
if (m_settings->serversCount() == 0) {
m_settings->setDefaultServer(-1);
}
endResetModel();
} }
QHash<int, QByteArray> ServersModel::roleNames() const { QHash<int, QByteArray> ServersModel::roleNames() const {

View file

@ -31,15 +31,16 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
public slots: public slots:
void setDefaultServerIndex(int index);
const int getDefaultServerIndex(); const int getDefaultServerIndex();
bool isDefaultServerCurrentlyProcessed();
const int getServersCount(); const int getServersCount();
void setCurrentlyProcessedServerIndex(int index); void setCurrentlyProcessedServerIndex(int index);
ServerCredentials getCurrentlyProcessedServerCredentials(); ServerCredentials getCurrentlyProcessedServerCredentials();
void addServer(); void addServer(const QJsonObject &server);
void removeServer();
protected: protected:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;

View file

@ -26,14 +26,7 @@ enum class Page { Start = 0, NewServer, NewServerProtocols, Vpn,
GeneralSettings, AppSettings, NetworkSettings, ServerSettings, GeneralSettings, AppSettings, NetworkSettings, ServerSettings,
ServerContainers, ServersList, ShareConnection, Sites, ServerContainers, ServersList, ShareConnection, Sites,
ProtocolSettings, ProtocolShare, QrDecoder, QrDecoderIos, About, ViewConfig, ProtocolSettings, ProtocolShare, QrDecoder, QrDecoderIos, About, ViewConfig,
AdvancedServerSettings, ClientManagement, ClientInfo, AdvancedServerSettings, ClientManagement, ClientInfo};
PageSetupWizardStart, PageTest, PageSetupWizardCredentials, PageSetupWizardProtocols, PageSetupWizardEasy,
PageSetupWizardProtocolSettings, PageSetupWizardInstalling, PageSetupWizardConfigSource, PageSetupWizardTextKey,
PageSettings, PageSettingsServersList,
PageStart, PageHome, PageShare};
Q_ENUM_NS(Page) Q_ENUM_NS(Page)
static void declareQmlPageEnum() { static void declareQmlPageEnum() {

View file

@ -7,7 +7,7 @@ import ConnectionState 1.0
Button { Button {
id: root id: root
text: "Подключиться" text: qsTr("Connect")
background: Image { background: Image {
id: border id: border
@ -60,37 +60,37 @@ Button {
case ConnectionState.Disconnected: { case ConnectionState.Disconnected: {
console.log("Disconnected") console.log("Disconnected")
connectionProccess.running = false connectionProccess.running = false
root.text = "Подключиться" root.text = qsTr("Connect")
break break
} }
case ConnectionState.Preparing: { case ConnectionState.Preparing: {
console.log("Preparing") console.log("Preparing")
connectionProccess.running = true connectionProccess.running = true
root.text = "Подключение..." root.text = qsTr("Connection...")
break break
} }
case ConnectionState.Connecting: { case ConnectionState.Connecting: {
console.log("Connecting") console.log("Connecting")
connectionProccess.running = true connectionProccess.running = true
root.text = "Подключение..." root.text = qsTr("Connection...")
break break
} }
case ConnectionState.Connected: { case ConnectionState.Connected: {
console.log("Connected") console.log("Connected")
connectionProccess.running = false connectionProccess.running = false
root.text = "Подключено" root.text = qsTr("Connected")
break break
} }
case ConnectionState.Disconnecting: { case ConnectionState.Disconnecting: {
console.log("Disconnecting") console.log("Disconnecting")
connectionProccess.running = true connectionProccess.running = true
root.text = "Отключение..." root.text = qsTr("Disconnection...")
break break
} }
case ConnectionState.Reconnecting: { case ConnectionState.Reconnecting: {
console.log("Reconnecting") console.log("Reconnecting")
connectionProccess.running = true connectionProccess.running = true
root.text = "Переподключение..." root.text = qsTr("Reconnection...")
break break
} }
case ConnectionState.Error: { case ConnectionState.Error: {

View file

@ -8,16 +8,12 @@ import "../Controls2"
import "../Controls2/TextTypes" import "../Controls2/TextTypes"
import "../Config" import "../Config"
Drawer { DrawerType {
id: root id: root
edge: Qt.BottomEdge
width: parent.width width: parent.width
height: parent.height * 0.4375 height: parent.height * 0.4375
clip: true
modal: true
background: Rectangle { background: Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.bottomMargin: -radius anchors.bottomMargin: -radius

View file

@ -29,64 +29,23 @@ ListView {
implicitWidth: rootWidth implicitWidth: rootWidth
implicitHeight: containerRadioButton.implicitHeight implicitHeight: containerRadioButton.implicitHeight
RadioButton { VerticalRadioButton {
id: containerRadioButton id: containerRadioButton
implicitWidth: parent.width anchors.fill: parent
implicitHeight: containerRadioButtonContent.implicitHeight anchors.rightMargin: 16
anchors.leftMargin: 16
hoverEnabled: true text: name
descriptionText: description
ButtonGroup.group: containersRadioButtonGroup ButtonGroup.group: containersRadioButtonGroup
checked: isDefault imageSource: "qrc:/images/controls/download.svg"
showImage: !isInstalled
indicator: Rectangle {
anchors.fill: parent
color: containerRadioButton.hovered ? "#2C2D30" : "#1C1D21"
Behavior on color {
PropertyAnimation { duration: 200 }
}
}
checkable: isInstalled checkable: isInstalled
checked: isDefault
RowLayout {
id: containerRadioButtonContent
anchors.fill: parent
anchors.rightMargin: 16
anchors.leftMargin: 16
z: 1
Image {
source: isInstalled ? "qrc:/images/controls/check.svg" : "qrc:/images/controls/download.svg"
visible: isInstalled ? containerRadioButton.checked : true
width: 24
height: 24
Layout.rightMargin: 8
}
Text {
id: containerRadioButtonText
text: name
color: "#D7D8DB"
font.pixelSize: 16
font.weight: 400
font.family: "PT Root UI VF"
height: 24
Layout.fillWidth: true
Layout.topMargin: 20
Layout.bottomMargin: 20
}
}
onClicked: { onClicked: {
if (checked) { if (checked) {

View file

@ -14,6 +14,7 @@ import "../Controls2/TextTypes"
ListView { ListView {
id: root id: root
width: parent.width
height: root.contentItem.height height: root.contentItem.height
clip: true clip: true
@ -23,7 +24,7 @@ ListView {
} }
delegate: Item { delegate: Item {
implicitWidth: parent.width implicitWidth: root.width
implicitHeight: containerRadioButton.implicitHeight implicitHeight: containerRadioButton.implicitHeight
RadioButton { RadioButton {

View file

@ -0,0 +1,20 @@
import QtQuick
import QtQuick.Controls
Drawer {
edge: Qt.BottomEdge
clip: true
modal: true
enter: Transition {
SmoothedAnimation {
velocity: 4
}
}
exit: Transition {
SmoothedAnimation {
velocity: 4
}
}
}

View file

@ -111,16 +111,12 @@ Item {
} }
} }
Drawer { DrawerType {
id: menu id: menu
edge: Qt.BottomEdge
width: parent.width width: parent.width
height: parent.height * 0.9 height: parent.height * 0.9
clip: true
modal: true
background: Rectangle { background: Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.bottomMargin: -radius anchors.bottomMargin: -radius

View file

@ -8,10 +8,11 @@ Item {
property StackView stackView: StackView.view property StackView stackView: StackView.view
function goToPage(page, slide = true) { function goToPage(page, slide = true) {
var pagePath = PageController.getPagePath(page)
if (slide) { if (slide) {
root.stackView.push(PageController.getPagePath(page), {}, StackView.PushTransition) root.stackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
} else { } else {
root.stackView.push(PageController.getPagePath(page), {}, StackView.Immediate) root.stackView.push(pagePath, { "objectName" : pagePath }, StackView.Immediate)
} }
} }

View file

@ -0,0 +1,61 @@
import QtQuick
import QtQuick.Controls
StackView {
id: root
pushEnter: Transition {
PropertyAnimation {
property: "opacity"
from: 0
to:1
duration: 200
}
}
pushExit: Transition {
PropertyAnimation {
property: "opacity"
from: 1
to:0
duration: 200
}
}
popEnter: Transition {
PropertyAnimation {
property: "opacity"
from: 0
to:1
duration: 200
}
}
popExit: Transition {
PropertyAnimation {
property: "opacity"
from: 1
to:0
duration: 200
}
}
replaceEnter: Transition {
PropertyAnimation {
property: "opacity"
from: 0
to:1
duration: 200
}
}
replaceExit: Transition {
PropertyAnimation {
property: "opacity"
from: 1
to:0
duration: 200
}
}
}

View file

@ -59,6 +59,7 @@ Switch {
} }
} }
contentItem: ColumnLayout {
contentItem: ColumnLayout { contentItem: ColumnLayout {
id: content id: content

View file

@ -3,6 +3,8 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import Qt5Compat.GraphicalEffects import Qt5Compat.GraphicalEffects
import "TextTypes"
RadioButton { RadioButton {
id: root id: root
@ -13,7 +15,8 @@ RadioButton {
property string disabledColor: Qt.rgba(1, 1, 1, 0) property string disabledColor: Qt.rgba(1, 1, 1, 0)
property string selectedColor: Qt.rgba(1, 1, 1, 0) property string selectedColor: Qt.rgba(1, 1, 1, 0)
property string textColor: "#0E0E11" property string textColor: "#D7D8DB"
property string selectedTextColor: "#FBB26A"
property string pressedBorderColor: Qt.rgba(251/255, 178/255, 106/255, 0.3) property string pressedBorderColor: Qt.rgba(251/255, 178/255, 106/255, 0.3)
property string selectedBorderColor: "#FBB26A" property string selectedBorderColor: "#FBB26A"
@ -26,11 +29,16 @@ RadioButton {
property string defaultInnerCircleColor: "#FBB26A" property string defaultInnerCircleColor: "#FBB26A"
property string imageSource
property bool showImage
hoverEnabled: true hoverEnabled: true
indicator: Rectangle { indicator: Rectangle {
id: background id: background
anchors.verticalCenter: parent.verticalCenter
implicitWidth: 56 implicitWidth: 56
implicitHeight: 56 implicitHeight: 56
radius: 16 radius: 16
@ -52,6 +60,16 @@ RadioButton {
PropertyAnimation { duration: 200 } PropertyAnimation { duration: 200 }
} }
Image {
source: imageSource
visible: showImage
anchors.centerIn: parent
width: 24
height: 24
}
Rectangle { Rectangle {
id: outerCircle id: outerCircle
@ -59,6 +77,8 @@ RadioButton {
height: 24 height: 24
radius: 16 radius: 16
visible: !showImage
anchors.centerIn: parent anchors.centerIn: parent
color: "transparent" color: "transparent"
@ -120,34 +140,41 @@ RadioButton {
contentItem: ColumnLayout { contentItem: ColumnLayout {
id: content id: content
anchors.fill: parent anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 8 + background.width anchors.leftMargin: 8 + background.width
Text { spacing: 4
text: root.text
wrapMode: Text.WordWrap ListItemTitleType {
color: "#D7D8DB" text: root.text
font.pixelSize: 16
font.weight: 400 color: {
font.family: "PT Root UI VF" if (root.checked) {
return selectedTextColor
}
return textColor
}
height: 24
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 16
Layout.bottomMargin: description.visible ? 0 : 16
Behavior on color {
PropertyAnimation { duration: 200 }
}
} }
Text { CaptionTextType {
font.family: "PT Root UI VF" id: description
font.styleName: "normal"
font.pixelSize: 13
font.letterSpacing: 0.02
color: "#878B91" color: "#878B91"
text: root.descriptionText text: root.descriptionText
wrapMode: Text.WordWrap
visible: root.descriptionText !== "" visible: root.descriptionText !== ""
Layout.fillWidth: true Layout.fillWidth: true
height: 16 Layout.bottomMargin: 16
} }
} }

View file

@ -37,6 +37,17 @@ PageType {
} }
} }
Connections {
target: PageController
function onRestorePageHomeState(isContainerInstalled) {
menu.visible = true
if (isContainerInstalled) {
containersDropDown.menuVisible = true
}
}
}
Rectangle { Rectangle {
id: buttonBackground id: buttonBackground
anchors.fill: buttonContent anchors.fill: buttonContent
@ -96,16 +107,12 @@ PageType {
} }
} }
Drawer { DrawerType {
id: menu id: menu
edge: Qt.BottomEdge
width: parent.width width: parent.width
height: parent.height * 0.90 height: parent.height * 0.90
clip: true
modal: true
background: Rectangle { background: Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.bottomMargin: -radius anchors.bottomMargin: -radius
@ -180,7 +187,7 @@ PageType {
containersDropDown.menuVisible = true containersDropDown.menuVisible = true
} }
listView: ContainersPageHomeListView { listView: HomeContainersListView {
rootWidth: root.width rootWidth: root.width
model: proxyContainersModel model: proxyContainersModel
@ -251,81 +258,63 @@ PageType {
property variant delegateData: model property variant delegateData: model
implicitWidth: serversMenuContent.width implicitWidth: serversMenuContent.width
implicitHeight: serverRadioButton.implicitHeight implicitHeight: serverRadioButtonContent.implicitHeight
RadioButton { ColumnLayout {
id: serverRadioButton id: serverRadioButtonContent
anchors.fill: parent
implicitWidth: parent.width anchors.rightMargin: 16
implicitHeight: serverRadioButtonContent.implicitHeight anchors.leftMargin: 16
hoverEnabled: true spacing: 0
checked: index === serversMenuContent.currentIndex
ButtonGroup.group: serversRadioButtonGroup
indicator: Rectangle {
anchors.fill: parent
color: serverRadioButton.hovered ? "#2C2D30" : "#1C1D21"
Behavior on color {
PropertyAnimation { duration: 200 }
}
}
RowLayout { RowLayout {
id: serverRadioButtonContent VerticalRadioButton {
anchors.fill: parent id: serverRadioButton
anchors.rightMargin: 16
anchors.leftMargin: 16
z: 1
Image {
source: "qrc:/images/controls/check.svg"
visible: serverRadioButton.checked
width: 24
height: 24
Layout.rightMargin: 8
}
Text {
id: serverRadioButtonText
text: name
color: "#D7D8DB"
font.pixelSize: 16
font.weight: 400
font.family: "PT Root UI VF"
height: 24
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 20
Layout.bottomMargin: 20 text: name
descriptionText: "description"
checked: index === serversMenuContent.currentIndex
ButtonGroup.group: serversRadioButtonGroup
onClicked: {
serversMenuContent.currentIndex = index
isDefault = true
ContainersModel.setCurrentlyProcessedServerIndex(index)
}
MouseArea {
anchors.fill: serverRadioButton
cursorShape: Qt.PointingHandCursor
enabled: false
}
} }
ImageButtonType { ImageButtonType {
image: "qrc:/images/controls/settings.svg" image: "qrc:/images/controls/settings.svg"
// onClicked: implicitWidth: 56
implicitHeight: 56
z: 1
onClicked: function() {
ServersModel.setCurrentlyProcessedServerIndex(index)
ContainersModel.setCurrentlyProcessedServerIndex(index)
goToPage(PageEnum.PageSettingsServerInfo)
menu.visible = false
}
} }
} }
onClicked: { DividerType {
serversMenuContent.currentIndex = index Layout.fillWidth: true
ServersModel.setDefaultServerIndex(index)
ContainersModel.setCurrentlyProcessedServerIndex(index)
}
MouseArea {
anchors.fill: serverRadioButton
cursorShape: Qt.PointingHandCursor
enabled: false
} }
} }
} }

View file

@ -1,142 +1,109 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Dialogs
import SortFilterProxyModel 0.2
import PageEnum 1.0 import PageEnum 1.0
import ProtocolEnum 1.0
import ContainerProps 1.0
import ProtocolProps 1.0
import "./" import "./"
import "../Controls2" import "../Controls2"
import "../Controls2/TextTypes" import "../Controls2/TextTypes"
import "../Config" import "../Config"
import "../Components"
PageType { PageType {
id: root id: root
SortFilterProxyModel { FlickableType {
id: proxyServersModel id: fl
sourceModel: ServersModel anchors.top: root.top
filters: [ anchors.bottom: root.bottom
ValueFilter { contentHeight: content.height
roleName: "isCurrentlyProcessed"
value: true
}
]
}
ColumnLayout { ColumnLayout {
id: content id: content
anchors.fill: parent anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: 16 HeaderType {
Layout.fillWidth: true
Layout.topMargin: 20
Layout.rightMargin: 16
Layout.leftMargin: 16
Repeater { headerText: qsTr("Settings")
id: header }
model: proxyServersModel
delegate: HeaderType { LabelWithButtonType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 16
Layout.leftMargin: 16
Layout.rightMargin: 16
actionButtonImage: "qrc:/images/controls/edit-3.svg" text: qsTr("Servers")
backButtonImage: "qrc:/images/controls/arrow-left.svg" buttonImage: "qrc:/images/controls/chevron-right.svg"
iconImage: "qrc:/images/controls/server.svg"
headerText: name clickedFunction: function() {
descriptionText: hostName goToPage(PageEnum.PageSettingsServersList)
actionButtonFunction: function() {
connectionTypeSelection.visible = true
}
backButtonFunction: function() {
closePage()
}
} }
} }
TabBar { DividerType {}
id: tabBar
LabelWithButtonType {
Layout.fillWidth: true Layout.fillWidth: true
background: Rectangle { text: qsTr("Connection")
color: "transparent" buttonImage: "qrc:/images/controls/chevron-right.svg"
} iconImage: "qrc:/images/controls/radio.svg"
TabButtonType { clickedFunction: function() {
isSelected: tabBar.currentIndex === 0
text: qsTr("Protocols")
}
TabButtonType {
isSelected: tabBar.currentIndex === 1
text: qsTr("Services")
}
TabButtonType {
isSelected: tabBar.currentIndex === 2
text: qsTr("Data")
} }
} }
StackLayout { DividerType {}
id: stackLayout
currentIndex: tabBar.currentIndex
LabelWithButtonType {
Layout.fillWidth: true Layout.fillWidth: true
height: root.height
StackView { text: qsTr("Application")
id: protocolsStackView buttonImage: "qrc:/images/controls/chevron-right.svg"
initialItem: PageSettingsContainersListView { iconImage: "qrc:/images/controls/app.svg"
model: SortFilterProxyModel {
sourceModel: ContainersModel
filters: [
ValueFilter {
roleName: "serviceType"
value: ProtocolEnum.Vpn
},
ValueFilter {
roleName: "isSupported"
value: true
}
]
}
}
}
StackView { clickedFunction: function() {
id: servicesStackView goToPage(PageEnum.PageSetupWizardTextKey)
initialItem: PageSettingsContainersListView {
model: SortFilterProxyModel {
sourceModel: ContainersModel
filters: [
ValueFilter {
roleName: "serviceType"
value: ProtocolEnum.Other
},
ValueFilter {
roleName: "isSupported"
value: true
}
]
}
}
}
StackView {
id: dataStackView
initialItem: PageSettingsData {
}
} }
} }
DividerType {}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Backup")
buttonImage: "qrc:/images/controls/chevron-right.svg"
iconImage: "qrc:/images/controls/save.svg"
clickedFunction: function() {
goToPage(PageEnum.PageSetupWizardTextKey)
}
}
DividerType {}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("About AmneziaVPN")
buttonImage: "qrc:/images/controls/chevron-right.svg"
iconImage: "qrc:/images/controls/amnezia.svg"
clickedFunction: function() {
goToPage(PageEnum.PageSetupWizardTextKey)
}
}
DividerType {}
} }
// } }
} }

View file

@ -33,6 +33,7 @@ PageType {
descriptionText: "May be needed when changing other settings" descriptionText: "May be needed when changing other settings"
clickedFunction: function() { clickedFunction: function() {
ContainersModel.clearCachedProfiles()
} }
} }
@ -45,6 +46,15 @@ PageType {
textColor: "#EB5757" textColor: "#EB5757"
clickedFunction: function() { clickedFunction: function() {
if (ServersModel.isDefaultServerCurrentlyProcessed && ConnectionController.isConnected()) {
ConnectionController.closeVpnConnection()
}
ServersModel.removeServer()
if (!ServersModel.getServersCount()) {
PageController.replaceStartPage()
} else {
goToStartPage()
}
} }
} }
@ -57,6 +67,9 @@ PageType {
textColor: "#EB5757" textColor: "#EB5757"
clickedFunction: function() { clickedFunction: function() {
if (ServersModel.isDefaultServerCurrentlyProcessed && ConnectionController.isConnected()) {
ConnectionController.closeVpnConnection()
}
ContainersModel.removeAllContainers() ContainersModel.removeAllContainers()
} }
} }

View file

@ -0,0 +1,134 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import PageEnum 1.0
import ProtocolEnum 1.0
import ContainerProps 1.0
import ProtocolProps 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
SortFilterProxyModel {
id: proxyServersModel
sourceModel: ServersModel
filters: [
ValueFilter {
roleName: "isCurrentlyProcessed"
value: true
}
]
}
ColumnLayout {
id: content
anchors.fill: parent
spacing: 16
Repeater {
id: header
model: proxyServersModel
delegate: HeaderType {
Layout.fillWidth: true
Layout.topMargin: 20
Layout.leftMargin: 16
Layout.rightMargin: 16
actionButtonImage: "qrc:/images/controls/edit-3.svg"
backButtonImage: "qrc:/images/controls/arrow-left.svg"
headerText: name
descriptionText: hostName
actionButtonFunction: function() {
connectionTypeSelection.visible = true
}
backButtonFunction: function() {
closePage()
}
}
}
TabBar {
id: tabBar
Layout.fillWidth: true
background: Rectangle {
color: "transparent"
}
TabButtonType {
isSelected: tabBar.currentIndex === 0
text: qsTr("Protocols")
// onClicked: {
// tabBarStackView.goToTabBarPage(PageEnum.PageSettingsServerProtocols)
// }
}
TabButtonType {
isSelected: tabBar.currentIndex === 1
text: qsTr("Services")
// onClicked: {
// tabBarStackView.goToTabBarPage(PageEnum.PageSettingsServerServices)
// }
}
TabButtonType {
isSelected: tabBar.currentIndex === 2
text: qsTr("Data")
// onClicked: {
// tabBarStackView.goToTabBarPage(PageEnum.PageSettingsServerData)
// }
}
}
StackLayout {
Layout.preferredWidth: root.width
Layout.preferredHeight: root.height - tabBar.implicitHeight - header.implicitHeight
currentIndex: tabBar.currentIndex
PageSettingsServerProtocols {
stackView: root.stackView
}
PageSettingsServerServices {
stackView: root.stackView
}
PageSettingsServerData {
stackView: root.stackView
}
}
// StackViewType {
// id: tabBarStackView
// Layout.preferredWidth: root.width
// Layout.preferredHeight: root.height - tabBar.implicitHeight - header.implicitHeight
// function goToTabBarPage(page) {
// var pagePath = PageController.getPagePath(page)
// while (tabBarStackView.depth > 1) {
// tabBarStackView.pop()
// }
// tabBarStackView.replace(pagePath, { "objectName" : pagePath })
// }
// Component.onCompleted: {
// var pagePath = PageController.getPagePath(PageEnum.PageSettingsServerProtocols)
// tabBarStackView.push(pagePath, { "objectName" : pagePath })
// }
// }
}
}

View file

@ -0,0 +1,38 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import PageEnum 1.0
import ProtocolEnum 1.0
import ContainerProps 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
SortFilterProxyModel {
id: containersProxyModel
sourceModel: ContainersModel
filters: [
ValueFilter {
roleName: "serviceType"
value: ProtocolEnum.Vpn
},
ValueFilter {
roleName: "isSupported"
value: true
}
]
}
SettingsContainersListView {
model: containersProxyModel
}
}

View file

@ -0,0 +1,38 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import PageEnum 1.0
import ProtocolEnum 1.0
import ContainerProps 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
SortFilterProxyModel {
id: containersProxyModel
sourceModel: ContainersModel
filters: [
ValueFilter {
roleName: "serviceType"
value: ProtocolEnum.Other
},
ValueFilter {
roleName: "isSupported"
value: true
}
]
}
SettingsContainersListView {
model: containersProxyModel
}
}

View file

@ -36,10 +36,6 @@ PageType {
actionButtonFunction: function() { actionButtonFunction: function() {
connectionTypeSelection.visible = true connectionTypeSelection.visible = true
} }
backButtonFunction: function() {
PageController.goToPageHome()
}
} }
ConnectionTypeSelectionDrawer { ConnectionTypeSelectionDrawer {
@ -87,7 +83,8 @@ PageType {
clickedFunction: function() { clickedFunction: function() {
ServersModel.setCurrentlyProcessedServerIndex(index) ServersModel.setCurrentlyProcessedServerIndex(index)
goToPage(PageEnum.PageSettings) ContainersModel.setCurrentlyProcessedServerIndex(index)
goToPage(PageEnum.PageSettingsServerInfo)
} }
} }

View file

@ -26,10 +26,26 @@ PageType {
function onInstallContainerFinished() { function onInstallContainerFinished() {
goToStartPage() goToStartPage()
if (stackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageHome)) {
PageController.restorePageHomeState(true)
} else if (stackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageSettings)) {
goToPage(PageEnum.PageSettingsServersList, false)
goToPage(PageEnum.PageSettingsServerInfo, false)
} else {
goToPage(PageEnum.PageHome)
}
} }
function onInstallServerFinished() { function onInstallServerFinished() {
goToStartPage() goToStartPage()
if (stackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageHome)) {
PageController.restorePageHomeState()
} else if (stackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageSettings)) {
goToPage(PageEnum.PageSettingsServersList, false)
} else {
var pagePath = PageController.getPagePath(PageEnum.PageStart)
stackView.replace(pagePath, { "objectName" : pagePath })
}
} }
} }

View file

@ -22,16 +22,6 @@ PageType {
} }
} }
Connections {
target: InstallController
function onInstallServerFinished() {
//todo add smt like changeStartPage
goToStartPage()
goToPage(PageEnum.PageStart)
}
}
FlickableType { FlickableType {
id: fl id: fl
anchors.top: root.top anchors.top: root.top

View file

@ -17,6 +17,7 @@ PageType {
function onGoToPageHome() { function onGoToPageHome() {
tabBar.currentIndex = 0 tabBar.currentIndex = 0
tabBarStackView.goToTabBarPage(PageController.getPagePath(PageEnum.PageHome))
} }
function onShowErrorMessage(errorMessage) { function onShowErrorMessage(errorMessage) {
@ -25,9 +26,8 @@ PageType {
} }
} }
StackLayout { StackViewType {
id: stackLayout id: tabBarStackView
currentIndex: tabBar.currentIndex
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
@ -37,20 +37,15 @@ PageType {
width: parent.width width: parent.width
height: root.height - tabBar.implicitHeight height: root.height - tabBar.implicitHeight
StackView { function goToTabBarPage(page) {
initialItem: PageHome { var pagePath = PageController.getPagePath(page)
id: pageHome tabBarStackView.clear(StackView.PopTransition)
} tabBarStackView.replace(pagePath, { "objectName" : pagePath })
} }
Item { Component.onCompleted: {
var pagePath = PageController.getPagePath(PageEnum.PageHome)
} tabBarStackView.push(pagePath, { "objectName" : pagePath })
StackView {
initialItem: PageSettingsServersList {
id: pageSettingsServersList
}
} }
} }
@ -70,12 +65,12 @@ PageType {
color: "#1C1D21" color: "#1C1D21"
} }
TabImageButtonType { TabImageButtonType {
isSelected: tabBar.currentIndex === 0 isSelected: tabBar.currentIndex === 0
image: "qrc:/images/controls/home.svg" image: "qrc:/images/controls/home.svg"
onClicked: { onClicked: {
pageSettingsServersList.goToStartPage() tabBarStackView.goToTabBarPage(PageEnum.PageHome)
ContainersModel.setCurrentlyProcessedServerIndex(ServersModel.getDefaultServerIndex())
} }
} }
TabImageButtonType { TabImageButtonType {
@ -86,7 +81,7 @@ PageType {
isSelected: tabBar.currentIndex === 2 isSelected: tabBar.currentIndex === 2
image: "qrc:/images/controls/settings-2.svg" image: "qrc:/images/controls/settings-2.svg"
onClicked: { onClicked: {
pageHome.goToStartPage() tabBarStackView.goToTabBarPage(PageEnum.PageSettings)
} }
} }
} }

View file

@ -4,8 +4,10 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import PageType 1.0 import PageType 1.0
import PageEnum 1.0
import "Config" import "Config"
import "Controls2"
Window { Window {
id: root id: root
@ -27,9 +29,27 @@ Window {
color: "#0E0E11" color: "#0E0E11"
} }
StackView { StackViewType {
id: rootStackView
anchors.fill: parent anchors.fill: parent
focus: true focus: true
initialItem: PageController.getInitialPage()
Component.onCompleted: {
var pagePath = PageController.getPagePath(PageEnum.PageStart)
rootStackView.push(pagePath, { "objectName" : pagePath })
}
}
Connections {
target: PageController
function onReplaceStartPage() {
var pagePath = PageController.getInitialPage()
while (rootStackView.depth > 1) {
rootStackView.pop()
}
rootStackView.replace(pagePath, { "objectName" : pagePath })
}
} }
} }

View file

@ -149,13 +149,13 @@ void UiLogic::initializeUiLogic()
connect(m_notificationHandler, &NotificationHandler::connectRequested, pageLogic<VpnLogic>(), &VpnLogic::onConnect); connect(m_notificationHandler, &NotificationHandler::connectRequested, pageLogic<VpnLogic>(), &VpnLogic::onConnect);
connect(m_notificationHandler, &NotificationHandler::disconnectRequested, pageLogic<VpnLogic>(), &VpnLogic::onDisconnect); connect(m_notificationHandler, &NotificationHandler::disconnectRequested, pageLogic<VpnLogic>(), &VpnLogic::onDisconnect);
if (m_settings->serversCount() > 0) { // if (m_settings->serversCount() > 0) {
if (m_settings->defaultServerIndex() < 0) m_settings->setDefaultServer(0); // if (m_settings->defaultServerIndex() < 0) m_settings->setDefaultServer(0);
emit goToPage(Page::PageStart, true, false); // emit goToPage(Page::PageStart, true, false);
} // }
else { // else {
emit goToPage(Page::PageSetupWizardStart, true, false); // emit goToPage(Page::PageSetupWizardStart, true, false);
} // }
m_selectedServerIndex = m_settings->defaultServerIndex(); m_selectedServerIndex = m_settings->defaultServerIndex();