Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into HEAD

This commit is contained in:
vladimir.kuznetsov 2025-01-09 13:56:08 +07:00
commit 98a5219137
37 changed files with 340 additions and 169 deletions

View file

@ -120,7 +120,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
} }
} }
QString subnetIp = containerConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress); QString subnetIp = containerConfig.value(m_protocolName).toObject().value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
{ {
QStringList l = subnetIp.split(".", Qt::SkipEmptyParts); QStringList l = subnetIp.split(".", Qt::SkipEmptyParts);
if (l.isEmpty()) { if (l.isEmpty()) {

View file

@ -346,7 +346,9 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
} }
if (container == DockerContainer::Awg) { if (container == DockerContainer::Awg) {
if ((oldProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort) if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)
!= newProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress))
|| (oldProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort)
!= newProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort)) != newProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort))
|| (oldProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount) || (oldProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount)
!= newProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount)) != newProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount))
@ -370,8 +372,10 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
} }
if (container == DockerContainer::WireGuard) { if (container == DockerContainer::WireGuard) {
if (oldProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort) if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)
!= newProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)) != newProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress))
|| (oldProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)
!= newProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)))
return true; return true;
} }
@ -607,6 +611,8 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
vars.append({ { "$SFTP_PASSWORD", sftpConfig.value(config_key::password).toString() } }); vars.append({ { "$SFTP_PASSWORD", sftpConfig.value(config_key::password).toString() } });
// Amnezia wireguard vars // Amnezia wireguard vars
vars.append({ { "$AWG_SUBNET_IP",
amneziaWireguarConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) } });
vars.append({ { "$AWG_SERVER_PORT", amneziaWireguarConfig.value(config_key::port).toString(protocols::awg::defaultPort) } }); vars.append({ { "$AWG_SERVER_PORT", amneziaWireguarConfig.value(config_key::port).toString(protocols::awg::defaultPort) } });
vars.append({ { "$JUNK_PACKET_COUNT", amneziaWireguarConfig.value(config_key::junkPacketCount).toString() } }); vars.append({ { "$JUNK_PACKET_COUNT", amneziaWireguarConfig.value(config_key::junkPacketCount).toString() } });

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="M18 13V19C18 19.5304 17.7893 20.0391 17.4142 20.4142C17.0391 20.7893 16.5304 21 16 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V8C3 7.46957 3.21071 6.96086 3.58579 6.58579C3.96086 6.21071 4.46957 6 5 6H11" stroke="#D7D8DB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M15 3H21V9" stroke="#D7D8DB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 14L21 3" stroke="#D7D8DB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 644 B

View file

@ -1,7 +1,6 @@
#include "xrayprotocol.h" #include "xrayprotocol.h"
#include "utilities.h" #include "utilities.h"
#include "containers/containers_defs.h"
#include "core/networkUtilities.h" #include "core/networkUtilities.h"
#include <QCryptographicHash> #include <QCryptographicHash>
@ -22,9 +21,8 @@ XrayProtocol::XrayProtocol(const QJsonObject &configuration, QObject *parent):
XrayProtocol::~XrayProtocol() XrayProtocol::~XrayProtocol()
{ {
qDebug() << "XrayProtocol::~XrayProtocol()";
XrayProtocol::stop(); XrayProtocol::stop();
QThread::msleep(200);
m_xrayProcess.close();
} }
ErrorCode XrayProtocol::start() ErrorCode XrayProtocol::start()
@ -36,10 +34,6 @@ ErrorCode XrayProtocol::start()
return lastError(); return lastError();
} }
if (Utils::processIsRunning(Utils::executable(xrayExecPath(), true))) {
Utils::killProcessByName(Utils::executable(xrayExecPath(), true));
}
#ifdef QT_DEBUG #ifdef QT_DEBUG
m_xrayCfgFile.setAutoRemove(false); m_xrayCfgFile.setAutoRemove(false);
#endif #endif
@ -54,9 +48,16 @@ ErrorCode XrayProtocol::start()
qDebug().noquote() << "XrayProtocol::start()" qDebug().noquote() << "XrayProtocol::start()"
<< xrayExecPath() << args.join(" "); << xrayExecPath() << args.join(" ");
m_xrayProcess.setProcessChannelMode(QProcess::MergedChannels);
m_xrayProcess.setProcessChannelMode(QProcess::MergedChannels);
m_xrayProcess.setProgram(xrayExecPath()); m_xrayProcess.setProgram(xrayExecPath());
if (Utils::processIsRunning(Utils::executable("xray", false))) {
qDebug().noquote() << "kill previos xray";
Utils::killProcessByName(Utils::executable("xray", false));
}
m_xrayProcess.setArguments(args); m_xrayProcess.setArguments(args);
connect(&m_xrayProcess, &QProcess::readyReadStandardOutput, this, [this]() { connect(&m_xrayProcess, &QProcess::readyReadStandardOutput, this, [this]() {
@ -68,13 +69,9 @@ ErrorCode XrayProtocol::start()
connect(&m_xrayProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) { connect(&m_xrayProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug().noquote() << "XrayProtocol finished, exitCode, exitStatus" << exitCode << exitStatus; qDebug().noquote() << "XrayProtocol finished, exitCode, exitStatus" << exitCode << exitStatus;
setConnectionState(Vpn::ConnectionState::Disconnected); setConnectionState(Vpn::ConnectionState::Disconnected);
if (exitStatus != QProcess::NormalExit) { if ((exitStatus != QProcess::NormalExit) || (exitCode != 0)) {
emit protocolError(amnezia::ErrorCode::XrayExecutableCrashed); emit protocolError(amnezia::ErrorCode::XrayExecutableCrashed);
stop(); emit setConnectionState(Vpn::ConnectionState::Error);
}
if (exitCode != 0) {
emit protocolError(amnezia::ErrorCode::InternalError);
stop();
} }
}); });
@ -177,14 +174,14 @@ void XrayProtocol::stop()
IpcClient::Interface()->StartRoutingIpv6(); IpcClient::Interface()->StartRoutingIpv6();
#endif #endif
qDebug() << "XrayProtocol::stop()"; qDebug() << "XrayProtocol::stop()";
m_xrayProcess.terminate(); m_xrayProcess.disconnect();
m_xrayProcess.kill();
m_xrayProcess.waitForFinished(3000);
if (m_t2sProcess) { if (m_t2sProcess) {
m_t2sProcess->stop(); m_t2sProcess->stop();
} }
#ifdef Q_OS_WIN setConnectionState(Vpn::ConnectionState::Disconnected);
Utils::signalCtrl(m_xrayProcess.processId(), CTRL_C_EVENT);
#endif
} }
QString XrayProtocol::xrayExecPath() QString XrayProtocol::xrayExecPath()

View file

@ -21,6 +21,7 @@
<file>images/controls/edit-3.svg</file> <file>images/controls/edit-3.svg</file>
<file>images/controls/eye-off.svg</file> <file>images/controls/eye-off.svg</file>
<file>images/controls/eye.svg</file> <file>images/controls/eye.svg</file>
<file>images/controls/external-link.svg</file>
<file>images/controls/file-check-2.svg</file> <file>images/controls/file-check-2.svg</file>
<file>images/controls/file-cog-2.svg</file> <file>images/controls/file-cog-2.svg</file>
<file>images/controls/folder-open.svg</file> <file>images/controls/folder-open.svg</file>
@ -119,6 +120,7 @@
<file>server_scripts/xray/run_container.sh</file> <file>server_scripts/xray/run_container.sh</file>
<file>server_scripts/xray/start.sh</file> <file>server_scripts/xray/start.sh</file>
<file>server_scripts/xray/template.json</file> <file>server_scripts/xray/template.json</file>
<file>ui/qml/Components/AdLabel.qml</file>
<file>ui/qml/Components/ConnectButton.qml</file> <file>ui/qml/Components/ConnectButton.qml</file>
<file>ui/qml/Components/ConnectionTypeSelectionDrawer.qml</file> <file>ui/qml/Components/ConnectionTypeSelectionDrawer.qml</file>
<file>ui/qml/Components/HomeContainersListView.qml</file> <file>ui/qml/Components/HomeContainersListView.qml</file>

View file

@ -12,7 +12,7 @@ echo $WIREGUARD_PSK > /opt/amnezia/awg/wireguard_psk.key
cat > /opt/amnezia/awg/wg0.conf <<EOF cat > /opt/amnezia/awg/wg0.conf <<EOF
[Interface] [Interface]
PrivateKey = $WIREGUARD_SERVER_PRIVATE_KEY PrivateKey = $WIREGUARD_SERVER_PRIVATE_KEY
Address = $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR Address = $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR
ListenPort = $AWG_SERVER_PORT ListenPort = $AWG_SERVER_PORT
Jc = $JUNK_PACKET_COUNT Jc = $JUNK_PACKET_COUNT
Jmin = $JUNK_PACKET_MIN_SIZE Jmin = $JUNK_PACKET_MIN_SIZE

View file

@ -17,12 +17,12 @@ iptables -A FORWARD -i wg0 -j ACCEPT
iptables -A OUTPUT -o wg0 -j ACCEPT iptables -A OUTPUT -o wg0 -j ACCEPT
# Allow forwarding traffic only from the VPN. # Allow forwarding traffic only from the VPN.
iptables -A FORWARD -i wg0 -o eth0 -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT iptables -A FORWARD -i wg0 -o eth0 -s $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -i wg0 -o eth1 -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT iptables -A FORWARD -i wg0 -o eth1 -s $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -o eth0 -j MASQUERADE iptables -t nat -A POSTROUTING -s $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -o eth1 -j MASQUERADE iptables -t nat -A POSTROUTING -s $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -o eth1 -j MASQUERADE
tail -f /dev/null tail -f /dev/null

View file

@ -538,3 +538,13 @@ void Settings::toggleDevGatewayEnv(bool enabled)
{ {
m_isDevGatewayEnv = enabled; m_isDevGatewayEnv = enabled;
} }
bool Settings::isHomeAdLabelVisible()
{
return value("Conf/homeAdLabelVisible", true).toBool();
}
void Settings::disableHomeAdLabel()
{
setValue("Conf/homeAdLabelVisible", false);
}

View file

@ -222,6 +222,9 @@ public:
bool isDevGatewayEnv(); bool isDevGatewayEnv();
void toggleDevGatewayEnv(bool enabled); void toggleDevGatewayEnv(bool enabled);
bool isHomeAdLabelVisible();
void disableHomeAdLabel();
signals: signals:
void saveLogsChanged(bool enabled); void saveLogsChanged(bool enabled);
void screenshotsEnabledChanged(bool enabled); void screenshotsEnabledChanged(bool enabled);

View file

@ -10,16 +10,15 @@ FocusController::FocusController(QQmlApplicationEngine *engine, QObject *parent)
m_focusChain {}, m_focusChain {},
m_focusedItem { nullptr }, m_focusedItem { nullptr },
m_rootObjects {}, m_rootObjects {},
m_defaultFocusItem { QSharedPointer<QQuickItem>() }, m_defaultFocusItem { nullptr },
m_lvfc { nullptr } m_lvfc { nullptr }
{ {
QObject::connect(m_engine.get(), &QQmlApplicationEngine::objectCreated, this, QObject::connect(m_engine, &QQmlApplicationEngine::objectCreated, this, [this](QObject *object, const QUrl &url) {
[this](QObject *object, const QUrl &url) { QQuickItem *newDefaultFocusItem = object->findChild<QQuickItem *>("defaultFocusItem");
QQuickItem *newDefaultFocusItem = object->findChild<QQuickItem *>("defaultFocusItem"); if (newDefaultFocusItem && m_defaultFocusItem != newDefaultFocusItem) {
if (newDefaultFocusItem && m_defaultFocusItem != newDefaultFocusItem) { m_defaultFocusItem = newDefaultFocusItem;
m_defaultFocusItem.reset(newDefaultFocusItem); }
} });
});
QObject::connect(this, &FocusController::focusedItemChanged, this, QObject::connect(this, &FocusController::focusedItemChanged, this,
[this]() { m_focusedItem->forceActiveFocus(Qt::TabFocusReason); }); [this]() { m_focusedItem->forceActiveFocus(Qt::TabFocusReason); });
@ -65,7 +64,7 @@ void FocusController::setFocusItem(QQuickItem *item)
void FocusController::setFocusOnDefaultItem() void FocusController::setFocusOnDefaultItem()
{ {
setFocusItem(m_defaultFocusItem.get()); setFocusItem(m_defaultFocusItem);
} }
void FocusController::pushRootObject(QObject *object) void FocusController::pushRootObject(QObject *object)

View file

@ -42,11 +42,11 @@ private:
void focusPreviousListViewItem(); void focusPreviousListViewItem();
void dropListView(); void dropListView();
QSharedPointer<QQmlApplicationEngine> m_engine; // Pointer to engine to get root object QQmlApplicationEngine *m_engine; // Pointer to engine to get root object
QList<QObject *> m_focusChain; // List of current objects to be focused QList<QObject *> m_focusChain; // List of current objects to be focused
QQuickItem *m_focusedItem; // Pointer to the active focus item QQuickItem *m_focusedItem; // Pointer to the active focus item
QStack<QObject *> m_rootObjects; QStack<QObject *> m_rootObjects; // Pointer to stack of roots for focus chain
QSharedPointer<QQuickItem> m_defaultFocusItem; QQuickItem *m_defaultFocusItem;
ListViewFocusController *m_lvfc; // ListView focus manager ListViewFocusController *m_lvfc; // ListView focus manager

View file

@ -320,4 +320,15 @@ bool SettingsController::isOnTv()
#else #else
return false; return false;
#endif #endif
} }
bool SettingsController::isHomeAdLabelVisible()
{
return m_settings->isHomeAdLabelVisible();
}
void SettingsController::disableHomeAdLabel()
{
m_settings->disableHomeAdLabel();
emit isHomeAdLabelVisibleChanged(false);
}

View file

@ -29,6 +29,8 @@ public:
Q_PROPERTY(QString gatewayEndpoint READ getGatewayEndpoint WRITE setGatewayEndpoint NOTIFY gatewayEndpointChanged) Q_PROPERTY(QString gatewayEndpoint READ getGatewayEndpoint WRITE setGatewayEndpoint NOTIFY gatewayEndpointChanged)
Q_PROPERTY(bool isDevGatewayEnv READ isDevGatewayEnv WRITE toggleDevGatewayEnv NOTIFY devGatewayEnvChanged) Q_PROPERTY(bool isDevGatewayEnv READ isDevGatewayEnv WRITE toggleDevGatewayEnv NOTIFY devGatewayEnvChanged)
Q_PROPERTY(bool isHomeAdLabelVisible READ isHomeAdLabelVisible NOTIFY isHomeAdLabelVisibleChanged)
public slots: public slots:
void toggleAmneziaDns(bool enable); void toggleAmneziaDns(bool enable);
bool isAmneziaDnsEnabled(); bool isAmneziaDnsEnabled();
@ -89,6 +91,9 @@ public slots:
bool isOnTv(); bool isOnTv();
bool isHomeAdLabelVisible();
void disableHomeAdLabel();
signals: signals:
void primaryDnsChanged(); void primaryDnsChanged();
void secondaryDnsChanged(); void secondaryDnsChanged();
@ -112,6 +117,8 @@ signals:
void gatewayEndpointChanged(const QString &endpoint); void gatewayEndpointChanged(const QString &endpoint);
void devGatewayEnvChanged(bool enabled); void devGatewayEnvChanged(bool enabled);
void isHomeAdLabelVisibleChanged(bool visible);
private: private:
QSharedPointer<ServersModel> m_serversModel; QSharedPointer<ServersModel> m_serversModel;
QSharedPointer<ContainersModel> m_containersModel; QSharedPointer<ContainersModel> m_containersModel;

View file

@ -70,7 +70,7 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
.arg(speed); .arg(speed);
} else if (serviceType == serviceType::amneziaFree){ } else if (serviceType == serviceType::amneziaFree){
QString description = tr("VPN to access blocked sites in regions with high levels of Internet censorship. "); QString description = tr("VPN to access blocked sites in regions with high levels of Internet censorship. ");
if (isServiceAvailable) { if (!isServiceAvailable) {
description += tr("<p><a style=\"color: #EB5757;\">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a>"); description += tr("<p><a style=\"color: #EB5757;\">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a>");
} }
return description; return description;
@ -86,7 +86,7 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
} }
case IsServiceAvailableRole: { case IsServiceAvailableRole: {
if (serviceType == serviceType::amneziaFree) { if (serviceType == serviceType::amneziaFree) {
if (isServiceAvailable) { if (!isServiceAvailable) {
return false; return false;
} }
} }

View file

@ -21,6 +21,7 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in
} }
switch (role) { switch (role) {
case Roles::SubnetAddressRole: m_serverProtocolConfig.insert(config_key::subnet_address, value.toString()); break;
case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break; case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break;
case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break; case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
@ -58,6 +59,7 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const
} }
switch (role) { switch (role) {
case Roles::SubnetAddressRole: return m_serverProtocolConfig.value(config_key::subnet_address).toString();
case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString(); case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu); case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
@ -92,6 +94,7 @@ void AwgConfigModel::updateModel(const QJsonObject &config)
m_serverProtocolConfig.insert(config_key::transport_proto, m_serverProtocolConfig.insert(config_key::transport_proto,
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config); m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
m_serverProtocolConfig[config_key::subnet_address] = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort); m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
m_serverProtocolConfig[config_key::junkPacketCount] = m_serverProtocolConfig[config_key::junkPacketCount] =
serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
@ -168,6 +171,7 @@ QHash<int, QByteArray> AwgConfigModel::roleNames() const
{ {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[SubnetAddressRole] = "subnetAddress";
roles[PortRole] = "port"; roles[PortRole] = "port";
roles[ClientMtuRole] = "clientMtu"; roles[ClientMtuRole] = "clientMtu";
@ -197,6 +201,7 @@ AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig)
clientJunkPacketMinSize = clientProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize); clientJunkPacketMinSize = clientProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
clientJunkPacketMaxSize = clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize); clientJunkPacketMaxSize = clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
subnetAddress = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
port = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort); port = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
serverJunkPacketCount = serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); serverJunkPacketCount = serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
serverJunkPacketMinSize = serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize); serverJunkPacketMinSize = serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
@ -216,7 +221,7 @@ AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig)
bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
{ {
if (port != other.port || serverJunkPacketCount != other.serverJunkPacketCount if (subnetAddress != other.subnetAddress || port != other.port || serverJunkPacketCount != other.serverJunkPacketCount
|| serverJunkPacketMinSize != other.serverJunkPacketMinSize || serverJunkPacketMaxSize != other.serverJunkPacketMaxSize || serverJunkPacketMinSize != other.serverJunkPacketMinSize || serverJunkPacketMaxSize != other.serverJunkPacketMaxSize
|| serverInitPacketJunkSize != other.serverInitPacketJunkSize || serverResponsePacketJunkSize != other.serverResponsePacketJunkSize || serverInitPacketJunkSize != other.serverInitPacketJunkSize || serverResponsePacketJunkSize != other.serverResponsePacketJunkSize
|| serverInitPacketMagicHeader != other.serverInitPacketMagicHeader || serverInitPacketMagicHeader != other.serverInitPacketMagicHeader

View file

@ -15,6 +15,7 @@ struct AwgConfig
{ {
AwgConfig(const QJsonObject &jsonConfig); AwgConfig(const QJsonObject &jsonConfig);
QString subnetAddress;
QString port; QString port;
QString clientMtu; QString clientMtu;
@ -43,7 +44,8 @@ class AwgConfigModel : public QAbstractListModel
public: public:
enum Roles { enum Roles {
PortRole = Qt::UserRole + 1, SubnetAddressRole = Qt::UserRole + 1,
PortRole,
ClientMtuRole, ClientMtuRole,
ClientJunkPacketCountRole, ClientJunkPacketCountRole,

View file

@ -21,6 +21,7 @@ bool WireGuardConfigModel::setData(const QModelIndex &index, const QVariant &val
} }
switch (role) { switch (role) {
case Roles::SubnetAddressRole: m_serverProtocolConfig.insert(config_key::subnet_address, value.toString()); break;
case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break; case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break;
case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break; case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
} }
@ -36,6 +37,7 @@ QVariant WireGuardConfigModel::data(const QModelIndex &index, int role) const
} }
switch (role) { switch (role) {
case Roles::SubnetAddressRole: return m_serverProtocolConfig.value(config_key::subnet_address).toString();
case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString(); case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu); case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
} }
@ -56,6 +58,7 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
m_serverProtocolConfig.insert(config_key::transport_proto, m_serverProtocolConfig.insert(config_key::transport_proto,
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config); m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
m_serverProtocolConfig[config_key::subnet_address] = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort); m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString(); auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
@ -96,6 +99,7 @@ QHash<int, QByteArray> WireGuardConfigModel::roleNames() const
{ {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[SubnetAddressRole] = "subnetAddress";
roles[PortRole] = "port"; roles[PortRole] = "port";
roles[ClientMtuRole] = "clientMtu"; roles[ClientMtuRole] = "clientMtu";
@ -108,12 +112,13 @@ WgConfig::WgConfig(const QJsonObject &serverProtocolConfig)
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu); clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu);
subnetAddress = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
port = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort); port = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
} }
bool WgConfig::hasEqualServerSettings(const WgConfig &other) const bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
{ {
if (port != other.port) { if (subnetAddress != other.subnetAddress || port != other.port) {
return false; return false;
} }
return true; return true;

View file

@ -10,6 +10,7 @@ struct WgConfig
{ {
WgConfig(const QJsonObject &jsonConfig); WgConfig(const QJsonObject &jsonConfig);
QString subnetAddress;
QString port; QString port;
QString clientMtu; QString clientMtu;
@ -24,7 +25,8 @@ class WireGuardConfigModel : public QAbstractListModel
public: public:
enum Roles { enum Roles {
PortRole = Qt::UserRole + 1, SubnetAddressRole = Qt::UserRole + 1,
PortRole,
ClientMtuRole ClientMtuRole
}; };

View file

@ -0,0 +1,72 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Shapes
import Qt5Compat.GraphicalEffects
import Style 1.0
import "../Config"
import "../Controls2"
import "../Controls2/TextTypes"
Rectangle {
id: root
property real contentHeight: ad.implicitHeight + ad.anchors.topMargin + ad.anchors.bottomMargin
border.width: 1
border.color: AmneziaStyle.color.goldenApricot
color: AmneziaStyle.color.transparent
radius: 13
visible: GC.isDesktop() && ServersModel.isDefaultServerFromApi
&& ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && SettingsController.isHomeAdLabelVisible
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: function() {
Qt.openUrlExternally(LanguageModel.getCurrentSiteUrl() + "/premium")
}
}
RowLayout {
id: ad
anchors.fill: parent
anchors.margins: 16
Image {
source: "qrc:/images/controls/amnezia.svg"
sourceSize: Qt.size(36, 36)
layer {
effect: ColorOverlay {
color: AmneziaStyle.color.paleGray
}
}
}
CaptionTextType {
Layout.fillWidth: true
Layout.rightMargin: 10
Layout.leftMargin: 10
text: qsTr("Amnezia Premium - for access to any website")
color: AmneziaStyle.color.pearlGray
lineHeight: 18
font.pixelSize: 15
}
ImageButtonType {
image: "qrc:/images/controls/close.svg"
imageColor: AmneziaStyle.color.paleGray
onClicked: function() {
SettingsController.disableHomeAdLabel()
}
}
}
}

View file

@ -12,7 +12,7 @@ Item {
readonly property string drawerExpandedStateName: "expanded" readonly property string drawerExpandedStateName: "expanded"
readonly property string drawerCollapsedStateName: "collapsed" readonly property string drawerCollapsedStateName: "collapsed"
readonly property bool isOpened: isExpandedStateActive() || (isCollapsedStateActive && (dragArea.drag.active === true)) readonly property bool isOpened: isExpandedStateActive() || (isCollapsedStateActive() && (dragArea.drag.active === true))
readonly property bool isClosed: isCollapsedStateActive() && (dragArea.drag.active === false) readonly property bool isClosed: isCollapsedStateActive() && (dragArea.drag.active === false)
property Component collapsedStateContent property Component collapsedStateContent
@ -123,7 +123,7 @@ Item {
id: background id: background
anchors.fill: parent anchors.fill: parent
color: root.isCollapsed ? AmneziaStyle.color.transparent : AmneziaStyle.color.translucentMidnightBlack color: root.isCollapsedStateActive() ? AmneziaStyle.color.transparent : AmneziaStyle.color.translucentMidnightBlack
Behavior on color { Behavior on color {
PropertyAnimation { duration: 200 } PropertyAnimation { duration: 200 }

View file

@ -216,9 +216,7 @@ Item {
ColumnLayout { ColumnLayout {
id: header id: header
anchors.top: parent.top anchors.fill: parent
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 16 anchors.topMargin: 16
BackButtonType { BackButtonType {
@ -226,31 +224,21 @@ Item {
backButtonImage: root.headerBackButtonImage backButtonImage: root.headerBackButtonImage
backButtonFunction: function() { menu.closeTriggered() } backButtonFunction: function() { menu.closeTriggered() }
} }
}
Column {
id: col
anchors.top: header.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 16
spacing: 16
Header2Type { Header2Type {
anchors.left: parent.left Layout.leftMargin: 16
anchors.right: parent.right Layout.rightMargin: 16
anchors.leftMargin: 16 Layout.bottomMargin: 16
anchors.rightMargin: 16 Layout.fillWidth: true
headerText: root.headerText headerText: root.headerText
width: parent.width
} }
Loader { Loader {
id: listViewLoader id: listViewLoader
sourceComponent: root.listView sourceComponent: root.listView
Layout.fillHeight: true
} }
} }
} }

View file

@ -30,6 +30,8 @@ ListView {
property bool isFocusable: true property bool isFocusable: true
ScrollBar.vertical: ScrollBarType {}
ButtonGroup { ButtonGroup {
id: buttonGroup id: buttonGroup
} }

View file

@ -26,5 +26,6 @@ QtObject {
readonly property color softGoldenApricot: Qt.rgba(251/255, 178/255, 106/255, 0.3) readonly property color softGoldenApricot: Qt.rgba(251/255, 178/255, 106/255, 0.3)
readonly property color mistyGray: Qt.rgba(215/255, 216/255, 219/255, 0.8) readonly property color mistyGray: Qt.rgba(215/255, 216/255, 219/255, 0.8)
readonly property color cloudyGray: Qt.rgba(215/255, 216/255, 219/255, 0.65) readonly property color cloudyGray: Qt.rgba(215/255, 216/255, 219/255, 0.65)
readonly property color pearlGray: '#EAEAEC'
} }
} }

View file

@ -1,6 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import SortFilterProxyModel 0.2 import SortFilterProxyModel 0.2
@ -42,8 +43,18 @@ PageType {
objectName: "homeColumnLayout" objectName: "homeColumnLayout"
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 34 anchors.topMargin: 12
anchors.bottomMargin: 34 anchors.bottomMargin: 16
AdLabel {
id: adLabel
Layout.fillWidth: true
Layout.preferredHeight: adLabel.contentHeight
Layout.leftMargin: 16
Layout.rightMargin: 16
Layout.bottomMargin: 22
}
BasicButtonType { BasicButtonType {
id: loggingButton id: loggingButton
@ -86,7 +97,6 @@ PageType {
objectName: "splitTunnelingButton" objectName: "splitTunnelingButton"
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.bottomMargin: 34
leftPadding: 16 leftPadding: 16
rightPadding: 16 rightPadding: 16
@ -256,11 +266,11 @@ PageType {
objectName: "rowLayoutLabel" objectName: "rowLayoutLabel"
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.topMargin: 8 Layout.topMargin: 8
Layout.bottomMargin: drawer.isCollapsed ? 44 : ServersModel.isDefaultServerFromApi ? 61 : 16 Layout.bottomMargin: drawer.isCollapsedStateActive ? 44 : ServersModel.isDefaultServerFromApi ? 61 : 16
spacing: 0 spacing: 0
BasicButtonType { BasicButtonType {
enabled: (ServersModel.defaultServerImagePathCollapsed !== "") && drawer.isCollapsed enabled: (ServersModel.defaultServerImagePathCollapsed !== "") && drawer.isCollapsedStateActive
hoverEnabled: enabled hoverEnabled: enabled
implicitHeight: 36 implicitHeight: 36
@ -278,8 +288,9 @@ PageType {
buttonTextLabel.font.pixelSize: 13 buttonTextLabel.font.pixelSize: 13
buttonTextLabel.font.weight: 400 buttonTextLabel.font.weight: 400
text: drawer.isCollapsed ? ServersModel.defaultServerDescriptionCollapsed : ServersModel.defaultServerDescriptionExpanded text: drawer.isCollapsedStateActive ? ServersModel.defaultServerDescriptionCollapsed : ServersModel.defaultServerDescriptionExpanded
leftImageSource: ServersModel.defaultServerImagePathCollapsed leftImageSource: ServersModel.defaultServerImagePathCollapsed
leftImageColor: ""
changeLeftImageSize: false changeLeftImageSize: false
rightImageSource: hoverEnabled ? "qrc:/images/controls/chevron-down.svg" : "" rightImageSource: hoverEnabled ? "qrc:/images/controls/chevron-down.svg" : ""
@ -337,7 +348,6 @@ PageType {
objectName: "containersListView" objectName: "containersListView"
rootWidth: root.width rootWidth: root.width
height: 500 // TODO: make calculated
Connections { Connections {
objectName: "rowLayoutConnections" objectName: "rowLayoutConnections"

View file

@ -36,13 +36,13 @@ PageType {
ListView { ListView {
id: listview id: listview
property bool isFocusable: true
anchors.top: backButtonLayout.bottom anchors.top: backButtonLayout.bottom
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
width: parent.width width: parent.width
property bool isFocusable: true
Keys.onTabPressed: { Keys.onTabPressed: {
FocusController.nextKeyTabItem() FocusController.nextKeyTabItem()
} }
@ -76,7 +76,7 @@ PageType {
implicitWidth: listview.width implicitWidth: listview.width
implicitHeight: col.implicitHeight implicitHeight: col.implicitHeight
property alias portTextField: portTextField property alias vpnAddressSubnetTextField: vpnAddressSubnetTextField
property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess() property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess()
ColumnLayout { ColumnLayout {
@ -98,12 +98,32 @@ PageType {
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
id: portTextField id: vpnAddressSubnetTextField
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 40 Layout.topMargin: 40
enabled: delegateItem.isEnabled enabled: delegateItem.isEnabled
headerText: qsTr("VPN address subnet")
textFieldText: subnetAddress
textField.onEditingFinished: {
if (textFieldText !== subnetAddress) {
subnetAddress = textFieldText
}
}
checkEmptyText: true
}
TextFieldWithHeaderType {
id: portTextField
Layout.fillWidth: true
Layout.topMargin: 16
enabled: delegateItem.isEnabled
headerText: qsTr("Port") headerText: qsTr("Port")
textFieldText: port textFieldText: port
textField.maximumLength: 5 textField.maximumLength: 5
@ -118,26 +138,6 @@ PageType {
checkEmptyText: true checkEmptyText: true
} }
TextFieldWithHeaderType {
id: mtuTextField
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("MTU")
textFieldText: mtu
textField.validator: IntValidator { bottom: 576; top: 65535 }
textField.onEditingFinished: {
if (textFieldText === "") {
textFieldText = "0"
}
if (textFieldText !== mtu) {
mtu = textFieldText
}
}
checkEmptyText: true
}
TextFieldWithHeaderType { TextFieldWithHeaderType {
id: junkPacketCountTextField id: junkPacketCountTextField
Layout.fillWidth: true Layout.fillWidth: true
@ -332,7 +332,8 @@ PageType {
junkPacketMaxSizeTextField.errorText === "" && junkPacketMaxSizeTextField.errorText === "" &&
junkPacketMinSizeTextField.errorText === "" && junkPacketMinSizeTextField.errorText === "" &&
junkPacketCountTextField.errorText === "" && junkPacketCountTextField.errorText === "" &&
portTextField.errorText === "" portTextField.errorText === "" &&
vpnAddressSubnetTextField.errorText === ""
text: qsTr("Save") text: qsTr("Save")

View file

@ -176,7 +176,6 @@ PageType {
headerText: qsTr("Hash") headerText: qsTr("Hash")
drawerParent: root drawerParent: root
parentFlickable: fl
listView: ListViewWithRadioButtonType { listView: ListViewWithRadioButtonType {
id: hashListView id: hashListView
@ -225,7 +224,6 @@ PageType {
headerText: qsTr("Cipher") headerText: qsTr("Cipher")
drawerParent: root drawerParent: root
parentFlickable: fl
listView: ListViewWithRadioButtonType { listView: ListViewWithRadioButtonType {
id: cipherListView id: cipherListView

View file

@ -16,8 +16,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: listview.currentItem.mtuTextField.textField
Item { Item {
id: focusItem id: focusItem
onFocusChanged: { onFocusChanged: {

View file

@ -59,7 +59,7 @@ PageType {
delegate: Item { delegate: Item {
id: delegateItem id: delegateItem
property alias focusItemId: portTextField.textField property alias focusItemId: vpnAddressSubnetTextField
property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess() property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess()
implicitWidth: listview.width implicitWidth: listview.width
@ -83,12 +83,31 @@ PageType {
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
id: portTextField id: vpnAddressSubnetTextField
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 40 Layout.topMargin: 40
enabled: delegateItem.isEnabled enabled: delegateItem.isEnabled
headerText: qsTr("VPN address subnet")
textFieldText: subnetAddress
textField.onEditingFinished: {
if (textFieldText !== subnetAddress) {
subnetAddress = textFieldText
}
}
checkEmptyText: true
}
TextFieldWithHeaderType {
id: portTextField
Layout.fillWidth: true
Layout.topMargin: 16
enabled: delegateItem.isEnabled
headerText: qsTr("Port") headerText: qsTr("Port")
textFieldText: port textFieldText: port
textField.maximumLength: 5 textField.maximumLength: 5
@ -103,33 +122,14 @@ PageType {
checkEmptyText: true checkEmptyText: true
} }
TextFieldWithHeaderType {
id: mtuTextField
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("MTU")
textFieldText: mtu
textField.validator: IntValidator { bottom: 576; top: 65535 }
textField.onEditingFinished: {
if (textFieldText === "") {
textFieldText = "0"
}
if (textFieldText !== mtu) {
mtu = textFieldText
}
}
checkEmptyText: true
}
BasicButtonType { BasicButtonType {
id: saveButton id: saveButton
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 24 Layout.topMargin: 24
Layout.bottomMargin: 24 Layout.bottomMargin: 24
enabled: portTextField.errorText === "" enabled: portTextField.errorText === "" &&
vpnAddressSubnetTextField.errorText === ""
text: qsTr("Save") text: qsTr("Save")

View file

@ -18,13 +18,13 @@ PageType {
ListView { ListView {
id: menuContent id: menuContent
property var selectedText property bool isFocusable: true
width: parent.width width: parent.width
height: menuContent.contentItem.height height: parent.height
clip: true clip: true
interactive: false interactive: true
model: ApiCountryModel model: ApiCountryModel
ButtonGroup { ButtonGroup {
@ -34,8 +34,8 @@ PageType {
delegate: ColumnLayout { delegate: ColumnLayout {
id: content id: content
implicitWidth: parent.width width: menuContent.width
implicitHeight: content.implicitHeight height: content.implicitHeight
RowLayout { RowLayout {
VerticalRadioButton { VerticalRadioButton {

View file

@ -221,15 +221,8 @@ PageType {
SettingsController.clearSettings() SettingsController.clearSettings()
PageController.goToPageHome() PageController.goToPageHome()
} }
if (!GC.isMobile()) {
// root.defaultActiveFocusItem.forceActiveFocus()
}
} }
var noButtonFunction = function() { var noButtonFunction = function() {
if (!GC.isMobile()) {
// root.defaultActiveFocusItem.forceActiveFocus()
}
} }
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)

View file

@ -109,15 +109,8 @@ PageType {
SettingsController.secondaryDns = "1.0.0.1" SettingsController.secondaryDns = "1.0.0.1"
secondaryDns.textFieldText = SettingsController.secondaryDns secondaryDns.textFieldText = SettingsController.secondaryDns
PageController.showNotificationMessage(qsTr("Settings have been reset")) PageController.showNotificationMessage(qsTr("Settings have been reset"))
if (!GC.isMobile()) {
// defaultActiveFocusItem.forceActiveFocus()
}
} }
var noButtonFunction = function() { var noButtonFunction = function() {
if (!GC.isMobile()) {
// defaultActiveFocusItem.forceActiveFocus()
}
} }
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)

View file

@ -206,6 +206,32 @@ PageType {
onClicked: { handler() } onClicked: { handler() }
} }
} }
footer: ColumnLayout {
width: listView.width
BasicButtonType {
id: siteLink2
Layout.topMargin: 24
Layout.bottomMargin: 16
Layout.alignment: Qt.AlignHCenter
implicitHeight: 32
defaultColor: AmneziaStyle.color.transparent
hoveredColor: AmneziaStyle.color.translucentWhite
pressedColor: AmneziaStyle.color.sheerWhite
disabledColor: AmneziaStyle.color.mutedGray
textColor: AmneziaStyle.color.goldenApricot
text: qsTr("Site Amnezia")
rightImageSource: "qrc:/images/controls/external-link.svg"
clickedFunc: function() {
Qt.openUrlExternally(LanguageModel.getCurrentSiteUrl())
}
}
}
} }
property list<QtObject> variants: [ property list<QtObject> variants: [

View file

@ -355,6 +355,7 @@ PageType {
serverSelectorListView.selectedIndex = 0 serverSelectorListView.selectedIndex = 0
} }
serverSelectorListView.positionViewAtIndex(selectedIndex, ListView.Beginning)
serverSelectorListView.triggerCurrentItem() serverSelectorListView.triggerCurrentItem()
} }
@ -410,6 +411,7 @@ PageType {
function onSeverSelectorIndexChanged() { function onSeverSelectorIndexChanged() {
var defaultContainer = proxyContainersModel.mapFromSource(ServersModel.getProcessedServerData("defaultContainer")) var defaultContainer = proxyContainersModel.mapFromSource(ServersModel.getProcessedServerData("defaultContainer"))
protocolSelectorListView.selectedIndex = defaultContainer protocolSelectorListView.selectedIndex = defaultContainer
protocolSelectorListView.positionViewAtIndex(selectedIndex, ListView.Beginning)
protocolSelectorListView.triggerCurrentItem() protocolSelectorListView.triggerCurrentItem()
} }
} }
@ -603,6 +605,7 @@ PageType {
} }
clip: true clip: true
interactive: false
reuseItems: true reuseItems: true
delegate: Item { delegate: Item {
@ -667,7 +670,11 @@ PageType {
ParagraphTextType { ParagraphTextType {
color: AmneziaStyle.color.mutedGray color: AmneziaStyle.color.mutedGray
visible: creationDate visible: creationDate
Layout.fillWidth: true Layout.maximumWidth: parent.width
maximumLineCount: 2
wrapMode: Text.Wrap
elide: Qt.ElideRight
text: qsTr("Creation date: %1").arg(creationDate) text: qsTr("Creation date: %1").arg(creationDate)
} }
@ -675,7 +682,11 @@ PageType {
ParagraphTextType { ParagraphTextType {
color: AmneziaStyle.color.mutedGray color: AmneziaStyle.color.mutedGray
visible: latestHandshake visible: latestHandshake
Layout.fillWidth: true Layout.maximumWidth: parent.width
maximumLineCount: 2
wrapMode: Text.Wrap
elide: Qt.ElideRight
text: qsTr("Latest handshake: %1").arg(latestHandshake) text: qsTr("Latest handshake: %1").arg(latestHandshake)
} }
@ -683,7 +694,11 @@ PageType {
ParagraphTextType { ParagraphTextType {
color: AmneziaStyle.color.mutedGray color: AmneziaStyle.color.mutedGray
visible: dataReceived visible: dataReceived
Layout.fillWidth: true Layout.maximumWidth: parent.width
maximumLineCount: 2
wrapMode: Text.Wrap
elide: Qt.ElideRight
text: qsTr("Data received: %1").arg(dataReceived) text: qsTr("Data received: %1").arg(dataReceived)
} }
@ -691,7 +706,11 @@ PageType {
ParagraphTextType { ParagraphTextType {
color: AmneziaStyle.color.mutedGray color: AmneziaStyle.color.mutedGray
visible: dataSent visible: dataSent
Layout.fillWidth: true Layout.maximumWidth: parent.width
maximumLineCount: 2
wrapMode: Text.Wrap
elide: Qt.ElideRight
text: qsTr("Data sent: %1").arg(dataSent) text: qsTr("Data sent: %1").arg(dataSent)
} }
@ -699,7 +718,9 @@ PageType {
ParagraphTextType { ParagraphTextType {
color: AmneziaStyle.color.mutedGray color: AmneziaStyle.color.mutedGray
visible: allowedIps visible: allowedIps
Layout.fillWidth: true Layout.maximumWidth: parent.width
wrapMode: Text.Wrap
text: qsTr("Allowed IPs: %1").arg(allowedIps) text: qsTr("Allowed IPs: %1").arg(allowedIps)
} }

View file

@ -348,7 +348,7 @@ PageType {
objectName: "settingsTabButton" objectName: "settingsTabButton"
isSelected: tabBar.currentIndex === 2 isSelected: tabBar.currentIndex === 2
image: "qrc:/images/controls/settings-2.svg" image: "qrc:/images/controls/settings.svg"
clickedFunc: function () { clickedFunc: function () {
tabBarStackView.goToTabBarPage(PageEnum.PageSettings) tabBarStackView.goToTabBarPage(PageEnum.PageSettings)
tabBar.currentIndex = 2 tabBar.currentIndex = 2

View file

@ -11,7 +11,6 @@ IpcProcessTun2Socks::IpcProcessTun2Socks(QObject *parent) :
IpcProcessTun2SocksSource(parent), IpcProcessTun2SocksSource(parent),
m_t2sProcess(QSharedPointer<QProcess>(new QProcess())) m_t2sProcess(QSharedPointer<QProcess>(new QProcess()))
{ {
connect(m_t2sProcess.data(), &QProcess::stateChanged, this, &IpcProcessTun2Socks::stateChanged);
qDebug() << "IpcProcessTun2Socks::IpcProcessTun2Socks()"; qDebug() << "IpcProcessTun2Socks::IpcProcessTun2Socks()";
} }
@ -23,8 +22,10 @@ IpcProcessTun2Socks::~IpcProcessTun2Socks()
void IpcProcessTun2Socks::start() void IpcProcessTun2Socks::start()
{ {
connect(m_t2sProcess.data(), &QProcess::stateChanged, this, &IpcProcessTun2Socks::stateChanged);
qDebug() << "IpcProcessTun2Socks::start()"; qDebug() << "IpcProcessTun2Socks::start()";
m_t2sProcess->setProgram(amnezia::permittedProcessPath(static_cast<amnezia::PermittedProcess>(amnezia::PermittedProcess::Tun2Socks))); m_t2sProcess->setProgram(amnezia::permittedProcessPath(static_cast<amnezia::PermittedProcess>(amnezia::PermittedProcess::Tun2Socks)));
QString XrayConStr = "socks5://127.0.0.1:10808"; QString XrayConStr = "socks5://127.0.0.1:10808";
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@ -41,7 +42,11 @@ void IpcProcessTun2Socks::start()
m_t2sProcess->setArguments(arguments); m_t2sProcess->setArguments(arguments);
Utils::killProcessByName(m_t2sProcess->program()); if (Utils::processIsRunning(Utils::executable("tun2socks", false))) {
qDebug().noquote() << "kill previos tun2socks";
Utils::killProcessByName(Utils::executable("tun2socks", false));
}
m_t2sProcess->start(); m_t2sProcess->start();
connect(m_t2sProcess.data(), &QProcess::readyReadStandardOutput, this, [this]() { connect(m_t2sProcess.data(), &QProcess::readyReadStandardOutput, this, [this]() {
@ -54,12 +59,10 @@ void IpcProcessTun2Socks::start()
connect(m_t2sProcess.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) { connect(m_t2sProcess.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug().noquote() << "tun2socks finished, exitCode, exiStatus" << exitCode << exitStatus; qDebug().noquote() << "tun2socks finished, exitCode, exiStatus" << exitCode << exitStatus;
emit setConnectionState(Vpn::ConnectionState::Disconnected); emit setConnectionState(Vpn::ConnectionState::Disconnected);
if (exitStatus != QProcess::NormalExit){ if ((exitStatus != QProcess::NormalExit) || (exitCode != 0)) {
stop(); emit setConnectionState(Vpn::ConnectionState::Error);
}
if (exitCode !=0 ){
stop();
} }
}); });
m_t2sProcess->start(); m_t2sProcess->start();
@ -69,6 +72,8 @@ void IpcProcessTun2Socks::start()
void IpcProcessTun2Socks::stop() void IpcProcessTun2Socks::stop()
{ {
qDebug() << "IpcProcessTun2Socks::stop()"; qDebug() << "IpcProcessTun2Socks::stop()";
m_t2sProcess->close(); m_t2sProcess->disconnect();
m_t2sProcess->kill();
m_t2sProcess->waitForFinished(3000);
} }
#endif #endif

View file

@ -152,21 +152,29 @@ bool RouterLinux::routeDeleteList(const QString &gw, const QStringList &ips)
return cnt; return cnt;
} }
bool RouterLinux::isServiceActive(const QString &serviceName) {
QProcess process;
process.start("systemctl", { "is-active", "--quiet", serviceName });
process.waitForFinished();
return process.exitCode() == 0;
}
void RouterLinux::flushDns() void RouterLinux::flushDns()
{ {
QProcess p; QProcess p;
p.setProcessChannelMode(QProcess::MergedChannels); p.setProcessChannelMode(QProcess::MergedChannels);
//check what the dns manager use //check what the dns manager use
if (QFileInfo::exists("/usr/bin/nscd") if (isServiceActive("nscd.service")) {
|| QFileInfo::exists("/usr/sbin/nscd") qDebug() << "Restarting nscd.service";
|| QFileInfo::exists("/usr/lib/systemd/system/nscd.service"))
{
p.start("systemctl", { "restart", "nscd" }); p.start("systemctl", { "restart", "nscd" });
} } else if (isServiceActive("systemd-resolved.service")) {
else qDebug() << "Restarting systemd-resolved.service";
{
p.start("systemctl", { "restart", "systemd-resolved" }); p.start("systemctl", { "restart", "systemd-resolved" });
} else {
qDebug() << "No suitable DNS manager found.";
return;
} }
p.waitForFinished(); p.waitForFinished();

View file

@ -43,6 +43,7 @@ private:
RouterLinux(RouterLinux const &) = delete; RouterLinux(RouterLinux const &) = delete;
RouterLinux& operator= (RouterLinux const&) = delete; RouterLinux& operator= (RouterLinux const&) = delete;
bool isServiceActive(const QString &serviceName);
QList<Route> m_addedRoutes; QList<Route> m_addedRoutes;
DnsUtilsLinux *m_dnsUtil; DnsUtilsLinux *m_dnsUtil;
}; };