feat: Update local proxy settings page

This commit is contained in:
aiamnezia
2026-01-27 15:09:02 +04:00
parent e946ee2430
commit 4c2010244b
2 changed files with 186 additions and 99 deletions
@@ -81,7 +81,7 @@ PageType {
text: qsTr("Local proxy")
descriptionText: SettingsController.isLocalProxyHttpEnabled ? qsTr("Running: 127.0.0.1:%1").arg(SettingsController.localProxyPort || 0)
: qsTr("Disabled")
: qsTr("Off")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
+185 -98
View File
@@ -8,12 +8,98 @@ import Style 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
PageType {
id: root
readonly property int localProxyPortMin: 1024
readonly property int localProxyPortMax: 65535
readonly property int defaultLocalProxyPort: 10808
property bool portValidationEnabled: false
property string portValidationError: ""
property bool suppressToggleHandler: false
Component.onCompleted: root.syncSwitchState()
function computePortErrorText() {
const text = portField.textField.text.trim()
if (text === "") {
return qsTr("Enter a port")
}
const value = parseInt(text)
if (isNaN(value) || value < root.localProxyPortMin || value > root.localProxyPortMax) {
return qsTr("Port must be between %1 and %2")
.arg(root.localProxyPortMin)
.arg(root.localProxyPortMax)
}
return ""
}
function updatePortValidation(force) {
if (force) {
root.portValidationEnabled = true
}
root.portValidationError = root.portValidationEnabled ? root.computePortErrorText() : ""
}
function isPortValid() {
return root.computePortErrorText() === ""
}
function syncSwitchState() {
setSwitcherChecked(SettingsController.isLocalProxyHttpEnabled)
}
function setSwitcherChecked(value) {
if (localProxyHeader.switcher.checked === value) {
return
}
root.suppressToggleHandler = true
localProxyHeader.switcher.checked = value
}
function handleLocalProxyToggle(checked) {
if (checked) {
const serverUuid = ServersModel.processedServerUuid
if (!serverUuid) {
root.setSwitcherChecked(false)
PageController.showNotificationMessage(qsTr("Unable to determine the current server"))
return
}
if (SettingsController.isLocalProxyHttpEnabled
&& SettingsController.localProxyOwnerUuid
&& SettingsController.localProxyOwnerUuid !== serverUuid) {
root.setSwitcherChecked(false)
PageController.showNotificationMessage(qsTr("Local proxy is already enabled for another server"))
return
}
const requestedPort = portField.portValue()
if (requestedPort < root.localProxyPortMin || requestedPort > root.localProxyPortMax) {
root.setSwitcherChecked(false)
PageController.showNotificationMessage(qsTr("Port must be between %1 and %2")
.arg(root.localProxyPortMin)
.arg(root.localProxyPortMax))
return
}
if (!SettingsController.enableLocalProxy(serverUuid, requestedPort)) {
root.setSwitcherChecked(false)
PageController.showNotificationMessage(qsTr("Failed to enable local proxy. Check the port (%1-%2).")
.arg(root.localProxyPortMin)
.arg(root.localProxyPortMax))
root.syncSwitchState()
return
}
root.syncSwitchState()
} else {
SettingsController.disableLocalProxy()
root.syncSwitchState()
}
}
BackButtonType {
id: backButton
@@ -41,11 +127,48 @@ PageType {
header: ColumnLayout {
width: listView.width
BaseHeaderType {
HeaderTypeWithSwitcher {
id: localProxyHeader
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: qsTr("Local proxy")
headerText: qsTr("Local Proxy")
descriptionText: qsTr("Use a proxy to route selected apps (for example, the CensorTracker extension) through Amnezia Premium.")
showSwitcher: true
switcherFunction: function(checked) {
if (root.suppressToggleHandler) {
root.suppressToggleHandler = false
return
}
root.handleLocalProxyToggle(checked)
}
}
ParagraphTextType {
Layout.fillWidth: true
Layout.topMargin: 8
Layout.leftMargin: 16
Layout.rightMargin: 16
text: qsTr("Only one can be on at a time: VPN or local proxy.")
}
BasicButtonType {
Layout.topMargin: 8
Layout.leftMargin: 8
implicitHeight: 32
defaultColor: AmneziaStyle.color.transparent
hoveredColor: AmneziaStyle.color.translucentWhite
pressedColor: AmneziaStyle.color.sheerWhite
disabledColor: AmneziaStyle.color.mutedGray
textColor: AmneziaStyle.color.goldenApricot
text: qsTr("Learn more")
clickedFunc: function() {
Qt.openUrlExternally(LanguageModel.getCurrentSiteUrl())
}
}
}
@@ -55,79 +178,6 @@ PageType {
width: listView.width
spacing: 16
SwitcherType {
id: localProxySwitch
Layout.fillWidth: true
Layout.margins: 16
property string statusText: ""
text: qsTr("Enable local proxy")
descriptionText: statusText
checked: SettingsController.isLocalProxyHttpEnabled
function computeStatusText() {
statusText = SettingsController.isLocalProxyHttpEnabled
? qsTr("Running: 127.0.0.1:%1").arg(SettingsController.localProxyPort || 0)
: qsTr("Disabled")
}
function syncState() {
computeStatusText()
if (checked !== SettingsController.isLocalProxyHttpEnabled) {
checked = SettingsController.isLocalProxyHttpEnabled
}
}
Component.onCompleted: syncState()
onToggled: function() {
if (checked) {
const serverUuid = ServersModel.processedServerUuid
console.log("serverUuid", serverUuid)
if (!serverUuid) {
checked = false
PageController.showNotificationMessage(qsTr("Unable to determine the current server"))
return
}
if (SettingsController.isLocalProxyHttpEnabled
&& SettingsController.localProxyOwnerUuid
&& SettingsController.localProxyOwnerUuid !== serverUuid) {
checked = false
PageController.showNotificationMessage(qsTr("Local proxy is already enabled for another server"))
return
}
const requestedPort = portField.portValue()
if (requestedPort < root.localProxyPortMin || requestedPort > root.localProxyPortMax) {
checked = false
PageController.showNotificationMessage(qsTr("Port must be between %1 and %2")
.arg(root.localProxyPortMin)
.arg(root.localProxyPortMax))
return
}
if (!SettingsController.enableLocalProxy(serverUuid, requestedPort)) {
checked = false
PageController.showNotificationMessage(qsTr("Failed to enable local proxy. Check the port (%1-%2).")
.arg(root.localProxyPortMin)
.arg(root.localProxyPortMax))
localProxySwitch.syncState()
return
}
localProxySwitch.syncState()
} else {
SettingsController.disableLocalProxy()
localProxySwitch.syncState()
}
}
}
DividerType {}
TextFieldWithHeaderType {
id: portField
@@ -135,14 +185,25 @@ PageType {
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: qsTr("Local proxy port")
headerText: qsTr("Address and port")
buttonText: qsTr("Copy")
errorText: root.portValidationError
enabled: true
rightButtonClickedOnEnter: true
clickedFunc: function() {
const portText = portField.effectivePortText()
GC.copyToClipBoard("127.0.0.1:" + portText)
}
textField.validator: IntValidator {
bottom: root.localProxyPortMin
top: root.localProxyPortMax
}
textField.leftPadding: portPrefix.implicitWidth + 8
textField.placeholderText: root.defaultLocalProxyPort.toString()
textField.inputMethodHints: Qt.ImhDigitsOnly | Qt.ImhNoPredictiveText
function syncPortValue() {
const port = SettingsController.localProxyPort
@@ -154,35 +215,61 @@ PageType {
return isNaN(value) ? -1 : value
}
function effectivePortText() {
const value = portValue()
if (value >= root.localProxyPortMin && value <= root.localProxyPortMax) {
return value.toString()
}
const fallback = SettingsController.localProxyPort
if (fallback >= root.localProxyPortMin && fallback <= root.localProxyPortMax) {
return fallback.toString()
}
return root.defaultLocalProxyPort.toString()
}
Component.onCompleted: syncPortValue()
textField.onEditingFinished: {
const value = portField.portValue()
if (value < root.localProxyPortMin || value > root.localProxyPortMax) {
PageController.showNotificationMessage(qsTr("Port must be between %1 and %2")
.arg(root.localProxyPortMin)
.arg(root.localProxyPortMax))
portField.syncPortValue()
return
textField.onTextChanged: root.updatePortValidation(false)
textField.onActiveFocusChanged: {
if (!textField.activeFocus) {
root.updatePortValidation(true)
}
if (!SettingsController.setLocalProxyPort(value)) {
PageController.showNotificationMessage(qsTr("Failed to save port. Valid range: %1-%2")
.arg(root.localProxyPortMin)
.arg(root.localProxyPortMax))
}
portField.syncPortValue()
}
}
ParagraphTextType {
LabelTextType {
id: portPrefix
parent: portField
text: "127.0.0.1:"
color: AmneziaStyle.color.paleGray
z: 1
anchors.left: portField.textField.left
anchors.verticalCenter: portField.textField.verticalCenter
}
BasicButtonType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
text: qsTr("SOCKS inbound listens on the specified port. Connect your client to 127.0.0.1.")
text: qsTr("Save")
enabled: root.isPortValid()
clickedFunc: function() {
root.updatePortValidation(true)
if (!root.isPortValid()) {
return
}
const value = portField.portValue()
if (!SettingsController.setLocalProxyPort(value)) {
PageController.showNotificationMessage(qsTr("Failed to save port. Valid range: %1-%2")
.arg(root.localProxyPortMin)
.arg(root.localProxyPortMax))
}
portField.syncPortValue()
}
}
}
}
@@ -191,7 +278,7 @@ PageType {
target: SettingsController
function onLocalProxySettingsUpdated() {
localProxySwitch.syncState()
root.syncSwitchState()
if (!portField.textField.activeFocus) {
portField.syncPortValue()
}
@@ -199,7 +286,7 @@ PageType {
function onLocalProxyStartFailed(message) {
PageController.showNotificationMessage(message)
localProxySwitch.syncState()
root.syncSwitchState()
}
}
@@ -207,7 +294,7 @@ PageType {
target: ServersModel
function onProcessedServerChanged() {
localProxySwitch.syncState()
root.syncSwitchState()
if (!portField.textField.activeFocus) {
portField.syncPortValue()
}