Add proxy config with Socks5 and HTTP proxy support
Resolve https://invent.kde.org/network/neochat/-/issues/547 This patch attempts to add proxy config support to NeoChat so people could set a HTTP or Socks5 proxy for anonymity or privacy/censorship-circumvention reason. Currently this will only allows setting proxy type, host and port (which should be usable for most of the cases). Settings in that page needs to be applied by clicking the Apply button so the proxy setting won't accidentally get changed. Proxy is disabled (use System Default option) by default.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@ compile_commands.json
|
||||
.cache/
|
||||
.vscode/
|
||||
kate.project.ctags.*
|
||||
*.user
|
||||
|
||||
@@ -140,6 +140,7 @@ if(ANDROID)
|
||||
"edit-copy"
|
||||
"gtk-quit"
|
||||
"compass"
|
||||
"computer"
|
||||
"network-connect"
|
||||
"list-remove-user"
|
||||
"org.kde.neochat"
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <QFileInfo>
|
||||
#include <QGuiApplication>
|
||||
#include <QImageReader>
|
||||
#include <QNetworkProxy>
|
||||
#include <QQuickItem>
|
||||
#include <QQuickTextDocument>
|
||||
#include <QQuickWindow>
|
||||
@@ -65,6 +66,8 @@ Controller::Controller(QObject *parent)
|
||||
Connection::setRoomType<NeoChatRoom>();
|
||||
Connection::setUserType<NeoChatUser>();
|
||||
|
||||
setApplicationProxy();
|
||||
|
||||
#ifndef Q_OS_ANDROID
|
||||
if (NeoChatConfig::self()->systemTray()) {
|
||||
m_trayIcon = new TrayIcon(this);
|
||||
@@ -784,3 +787,29 @@ void Controller::forceRefreshTextDocument(QQuickTextDocument *textDocument, QQui
|
||||
// HACK: Workaround bug QTBUG 93281
|
||||
connect(textDocument->textDocument(), SIGNAL(imagesLoaded()), item, SLOT(updateWholeDocument()));
|
||||
}
|
||||
|
||||
void Controller::setApplicationProxy()
|
||||
{
|
||||
NeoChatConfig *cfg = NeoChatConfig::self();
|
||||
QNetworkProxy proxy;
|
||||
|
||||
// type match to ProxyType from neochatconfig.kcfg
|
||||
switch (cfg->proxyType()) {
|
||||
case 1: // HTTP
|
||||
proxy.setType(QNetworkProxy::HttpProxy);
|
||||
proxy.setHostName(cfg->proxyHost());
|
||||
proxy.setPort(cfg->proxyPort());
|
||||
break;
|
||||
case 2: // SOCKS 5
|
||||
proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||
proxy.setHostName(cfg->proxyHost());
|
||||
proxy.setPort(cfg->proxyPort());
|
||||
break;
|
||||
case 0: // System Default
|
||||
default:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
QNetworkProxy::setApplicationProxy(proxy);
|
||||
}
|
||||
|
||||
@@ -99,6 +99,8 @@ public:
|
||||
|
||||
Q_INVOKABLE void forceRefreshTextDocument(QQuickTextDocument *textDocument, QQuickItem *item);
|
||||
|
||||
Q_INVOKABLE void setApplicationProxy();
|
||||
|
||||
private:
|
||||
explicit Controller(QObject *parent = nullptr);
|
||||
|
||||
|
||||
@@ -98,5 +98,30 @@
|
||||
<default>true</default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="NetworkProxy">
|
||||
<entry name="ProxyType" type="Enum">
|
||||
<label>The type of proxy used by the application.</label>
|
||||
<choices>
|
||||
<choice name="System">
|
||||
<label>System Default</label>
|
||||
</choice>
|
||||
<choice name="HTTP">
|
||||
<label>HTTP</label>
|
||||
</choice>
|
||||
<choice name="Socks5">
|
||||
<label>Socks5</label>
|
||||
</choice>
|
||||
<default>System</default>
|
||||
</choices>
|
||||
</entry>
|
||||
<entry name="ProxyHost" type="String">
|
||||
<label>IP or hostname of the proxy</label>
|
||||
<default>127.0.0.1</default>
|
||||
</entry>
|
||||
<entry name="ProxyPort" type="int">
|
||||
<label>The port number of the proxy</label>
|
||||
<default>1080</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
||||
|
||||
97
src/qml/Settings/NetworkProxyPage.qml
Normal file
97
src/qml/Settings/NetworkProxyPage.qml
Normal file
@@ -0,0 +1,97 @@
|
||||
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later OR LicenseRef-KDE-Accepted-LGPL
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
title: i18nc("@title:window", "General")
|
||||
property int currentType
|
||||
property bool proxyConfigChanged: false
|
||||
|
||||
ColumnLayout {
|
||||
Kirigami.FormLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
QQC2.RadioButton {
|
||||
Kirigami.FormData.label: i18n("Network Proxy")
|
||||
text: i18n("System Default")
|
||||
checked: currentType === 0
|
||||
enabled: !Config.isProxyTypeImmutable
|
||||
onToggled: {
|
||||
currentType = 0
|
||||
}
|
||||
}
|
||||
QQC2.RadioButton {
|
||||
text: i18n("HTTP")
|
||||
checked: currentType === 1
|
||||
enabled: !Config.isProxyTypeImmutable
|
||||
onToggled: {
|
||||
currentType = 1
|
||||
}
|
||||
}
|
||||
QQC2.RadioButton {
|
||||
text: i18n("Socks5")
|
||||
checked: currentType === 2
|
||||
enabled: !Config.isProxyTypeImmutable
|
||||
onToggled: {
|
||||
currentType = 2
|
||||
}
|
||||
}
|
||||
QQC2.TextField {
|
||||
id: hostField
|
||||
Kirigami.FormData.label: i18n("Proxy Host")
|
||||
text: Config.proxyHost
|
||||
inputMethodHints: Qt.ImhUrlCharactersOnly
|
||||
onEditingFinished: {
|
||||
proxyConfigChanged = true
|
||||
}
|
||||
}
|
||||
QQC2.SpinBox {
|
||||
id: portField
|
||||
Kirigami.FormData.label: i18n("Proxy Port")
|
||||
value: Config.proxyPort
|
||||
from: 0
|
||||
to: 65536
|
||||
validator: IntValidator {bottom: from; top: to}
|
||||
textFromValue: function(value, locale) {
|
||||
return value // it will add a thousands separator if we don't do this, not sure why
|
||||
}
|
||||
onValueChanged: {
|
||||
proxyConfigChanged = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer: QQC2.ToolBar {
|
||||
height: visible ? implicitHeight : 0
|
||||
contentItem: RowLayout {
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
QQC2.Button {
|
||||
text: i18n("Apply")
|
||||
enabled: currentType !== Config.proxyType || proxyConfigChanged
|
||||
onClicked: {
|
||||
Config.proxyType = currentType
|
||||
Config.proxyHost = hostField.text
|
||||
Config.proxyPort = portField.value
|
||||
Config.save()
|
||||
proxyConfigChanged = false
|
||||
Controller.setApplicationProxy()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
currentType = Config.proxyType
|
||||
}
|
||||
}
|
||||
@@ -34,8 +34,13 @@ Kirigami.CategorizedSettings {
|
||||
page: Qt.resolvedUrl("SonnetConfigPage.qml")
|
||||
},
|
||||
Kirigami.SettingAction {
|
||||
text: i18n("Devices")
|
||||
text: i18n("Network Proxy")
|
||||
iconName: "network-connect"
|
||||
page: Qt.resolvedUrl("NetworkProxyPage.qml")
|
||||
},
|
||||
Kirigami.SettingAction {
|
||||
text: i18n("Devices")
|
||||
iconName: "computer"
|
||||
page: Qt.resolvedUrl("DevicesPage.qml")
|
||||
},
|
||||
Kirigami.SettingAction {
|
||||
|
||||
@@ -83,5 +83,6 @@
|
||||
<file alias="DevicesPage.qml">qml/Settings/DevicesPage.qml</file>
|
||||
<file alias="About.qml">qml/Settings/About.qml</file>
|
||||
<file alias="SonnetConfigPage.qml">qml/Settings/SonnetConfigPage.qml</file>
|
||||
<file alias="NetworkProxyPage.qml">qml/Settings/NetworkProxyPage.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
Reference in New Issue
Block a user