mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-24 02:00:24 +07:00
fixed add/delete additional secret
This commit is contained in:
@@ -211,6 +211,12 @@ ErrorCode InstallController::updateServerConfig(const QString &serverId, DockerC
|
|||||||
if (errorCode == ErrorCode::NoError) {
|
if (errorCode == ErrorCode::NoError) {
|
||||||
errorCode = startupContainerWorker(credentials, container, newConfig, sshSession);
|
errorCode = startupContainerWorker(credentials, container, newConfig, sshSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (errorCode == ErrorCode::NoError
|
||||||
|
&& (container == DockerContainer::MtProxy || container == DockerContainer::Telemt)) {
|
||||||
|
const QString containerName = ContainerUtils::containerToString(container);
|
||||||
|
errorCode = sshSession.runScript(credentials, "sudo docker restart " + containerName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool skipXrayInboundSync =
|
const bool skipXrayInboundSync =
|
||||||
@@ -737,18 +743,6 @@ bool InstallController::isReinstallContainerRequired(DockerContainer container,
|
|||||||
if (oldPort != newPort) {
|
if (oldPort != newPort) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const QString oldTransport = oldMt->transportMode.isEmpty() ? QString(
|
|
||||||
protocols::mtProxy::transportModeStandard)
|
|
||||||
: oldMt->transportMode;
|
|
||||||
const QString newTransport = newMt->transportMode.isEmpty() ? QString(
|
|
||||||
protocols::mtProxy::transportModeStandard)
|
|
||||||
: newMt->transportMode;
|
|
||||||
if (oldTransport != newTransport) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (oldMt->tlsDomain != newMt->tlsDomain) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,39 +757,6 @@ bool InstallController::isReinstallContainerRequired(DockerContainer container,
|
|||||||
if (oldPort != newPort) {
|
if (oldPort != newPort) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const QString oldTransport = oldT->transportMode.isEmpty()
|
|
||||||
? QString(protocols::telemt::transportModeStandard)
|
|
||||||
: oldT->transportMode;
|
|
||||||
const QString newTransport = newT->transportMode.isEmpty()
|
|
||||||
? QString(protocols::telemt::transportModeStandard)
|
|
||||||
: newT->transportMode;
|
|
||||||
if (oldTransport != newTransport) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (oldT->tlsDomain != newT->tlsDomain) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (oldT->maskEnabled != newT->maskEnabled) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (oldT->tlsEmulation != newT->tlsEmulation) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (oldT->useMiddleProxy != newT->useMiddleProxy) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (oldT->tag != newT->tag) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const QString oldUser = oldT->userName.isEmpty()
|
|
||||||
? QString::fromUtf8(protocols::telemt::defaultUserName)
|
|
||||||
: oldT->userName;
|
|
||||||
const QString newUser = newT->userName.isEmpty()
|
|
||||||
? QString::fromUtf8(protocols::telemt::defaultUserName)
|
|
||||||
: newT->userName;
|
|
||||||
if (oldUser != newUser) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -367,6 +367,14 @@ amnezia::ScriptVars amnezia::genTelemtVars(const ContainerConfig &containerConfi
|
|||||||
vars.append({ { "$TELEMT_USE_MIDDLE_PROXY", c.useMiddleProxy ? QLatin1String("true") : QLatin1String("false") } });
|
vars.append({ { "$TELEMT_USE_MIDDLE_PROXY", c.useMiddleProxy ? QLatin1String("true") : QLatin1String("false") } });
|
||||||
vars.append({ { "$TELEMT_MASK", c.maskEnabled ? QLatin1String("true") : QLatin1String("false") } });
|
vars.append({ { "$TELEMT_MASK", c.maskEnabled ? QLatin1String("true") : QLatin1String("false") } });
|
||||||
vars.append({ { "$TELEMT_TLS_EMULATION", c.tlsEmulation ? QLatin1String("true") : QLatin1String("false") } });
|
vars.append({ { "$TELEMT_TLS_EMULATION", c.tlsEmulation ? QLatin1String("true") : QLatin1String("false") } });
|
||||||
|
|
||||||
|
QStringList additionalList;
|
||||||
|
for (const QString &s : c.additionalSecrets) {
|
||||||
|
if (!s.isEmpty()) {
|
||||||
|
additionalList << s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vars.append({ { "$TELEMT_ADDITIONAL_SECRETS", additionalList.join(QLatin1Char(',')) } });
|
||||||
}
|
}
|
||||||
|
|
||||||
return vars;
|
return vars;
|
||||||
|
|||||||
@@ -61,6 +61,12 @@ rm -f /data/config.toml
|
|||||||
echo ""
|
echo ""
|
||||||
echo "[access.users]"
|
echo "[access.users]"
|
||||||
echo "$TELEMT_USER_NAME = \"$SECRET\""
|
echo "$TELEMT_USER_NAME = \"$SECRET\""
|
||||||
|
i=1
|
||||||
|
for EXTRA in $(echo "$TELEMT_ADDITIONAL_SECRETS" | tr ',' ' '); do
|
||||||
|
echo "$EXTRA" | grep -qE '^[0-9a-fA-F]{32}$' || continue
|
||||||
|
echo "extra_$i = \"$EXTRA\""
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
} > /data/config.toml
|
} > /data/config.toml
|
||||||
|
|
||||||
echo "$SECRET" > /data/secret
|
echo "$SECRET" > /data/secret
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ PageType {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property int containerStatus: 1
|
property int containerStatus: 1
|
||||||
// Last status-query error code (0 = none). 305 = SshTimeoutError → server unreachable.
|
|
||||||
property int statusErrorCode: 0
|
property int statusErrorCode: 0
|
||||||
property bool isUpdating: false
|
property bool isUpdating: false
|
||||||
property bool isCheckingStatus: false
|
property bool isCheckingStatus: false
|
||||||
@@ -869,6 +868,28 @@ PageType {
|
|||||||
return "tg://proxy?server=" + mtProxyEffectiveHostForLinks() + "&port=" + port + "&secret=" + mtProxyActiveSecretForBaseHex(baseHex)
|
return "tg://proxy?server=" + mtProxyEffectiveHostForLinks() + "&port=" + port + "&secret=" + mtProxyActiveSecretForBaseHex(baseHex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mtProxyIsAdditionalPersisted(hex) {
|
||||||
|
return root.mtProxyIsPersistedAdditionalHex(hex)
|
||||||
|
}
|
||||||
|
|
||||||
|
function mtProxyCopyText(text) {
|
||||||
|
GC.copyToClipBoard(text)
|
||||||
|
PageController.showNotificationMessage(qsTr("Copied"))
|
||||||
|
}
|
||||||
|
|
||||||
|
function mtProxyShareQr(link) {
|
||||||
|
ExportController.generateQrFromString(link)
|
||||||
|
PageController.goToShareConnectionPage(qsTr("Telegram connection link"),
|
||||||
|
qsTr("MTProxy connection link"), "", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
function mtProxyRemoveAdditionalSecret(idx) {
|
||||||
|
MtProxyConfigModel.removeAdditionalSecret(idx)
|
||||||
|
if (root.containerStatus === 1) {
|
||||||
|
root.mtProxyScheduleUpdate(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SwitcherType {
|
SwitcherType {
|
||||||
id: enableMtProxySwitch
|
id: enableMtProxySwitch
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -1322,7 +1343,7 @@ PageType {
|
|||||||
delegate: ColumnLayout {
|
delegate: ColumnLayout {
|
||||||
id: addSecretDelegate
|
id: addSecretDelegate
|
||||||
property bool linksExpanded: false
|
property bool linksExpanded: false
|
||||||
readonly property bool linksPanelAllowed: root.mtProxyIsPersistedAdditionalHex(modelData)
|
readonly property bool linksPanelAllowed: settingsRoot.mtProxyIsAdditionalPersisted(modelData)
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
@@ -1379,11 +1400,7 @@ PageType {
|
|||||||
sourceSize.width: 24
|
sourceSize.width: 24
|
||||||
sourceSize.height: 24
|
sourceSize.height: 24
|
||||||
rotation: addSecretDelegate.linksExpanded ? 180 : 0
|
rotation: addSecretDelegate.linksExpanded ? 180 : 0
|
||||||
Behavior on rotation {
|
Behavior on rotation { NumberAnimation { duration: 150 } }
|
||||||
NumberAnimation {
|
|
||||||
duration: 150
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1400,15 +1417,9 @@ PageType {
|
|||||||
implicitWidth: 32
|
implicitWidth: 32
|
||||||
implicitHeight: 32
|
implicitHeight: 32
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
visible: ServersUiController.isProcessedServerHasWriteAccess()
|
|
||||||
image: "qrc:/images/controls/trash.svg"
|
image: "qrc:/images/controls/trash.svg"
|
||||||
imageColor: AmneziaStyle.color.vibrantRed
|
imageColor: AmneziaStyle.color.vibrantRed
|
||||||
onClicked: {
|
onClicked: settingsRoot.mtProxyRemoveAdditionalSecret(index)
|
||||||
MtProxyConfigModel.removeAdditionalSecret(index)
|
|
||||||
if (containerStatus === 1) {
|
|
||||||
root.mtProxyScheduleUpdate(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1457,13 +1468,7 @@ PageType {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
image: "qrc:/images/controls/qr-code.svg"
|
image: "qrc:/images/controls/qr-code.svg"
|
||||||
imageColor: AmneziaStyle.color.paleGray
|
imageColor: AmneziaStyle.color.paleGray
|
||||||
onClicked: {
|
onClicked: settingsRoot.mtProxyShareQr(settingsRoot.mtProxyTmeLinkForAdditional(modelData))
|
||||||
ExportController.generateQrFromString(settingsRoot.mtProxyTmeLinkForAdditional(modelData))
|
|
||||||
PageController.goToShareConnectionPage(
|
|
||||||
qsTr("Telegram connection link"),
|
|
||||||
qsTr("MTProxy connection link"),
|
|
||||||
"", "", "")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageButtonType {
|
ImageButtonType {
|
||||||
@@ -1472,10 +1477,7 @@ PageType {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
image: "qrc:/images/controls/copy.svg"
|
image: "qrc:/images/controls/copy.svg"
|
||||||
imageColor: AmneziaStyle.color.paleGray
|
imageColor: AmneziaStyle.color.paleGray
|
||||||
onClicked: {
|
onClicked: settingsRoot.mtProxyCopyText(settingsRoot.mtProxyTmeLinkForAdditional(modelData))
|
||||||
GC.copyToClipBoard(settingsRoot.mtProxyTmeLinkForAdditional(modelData))
|
|
||||||
PageController.showNotificationMessage(qsTr("Copied"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1512,13 +1514,7 @@ PageType {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
image: "qrc:/images/controls/qr-code.svg"
|
image: "qrc:/images/controls/qr-code.svg"
|
||||||
imageColor: AmneziaStyle.color.paleGray
|
imageColor: AmneziaStyle.color.paleGray
|
||||||
onClicked: {
|
onClicked: settingsRoot.mtProxyShareQr(settingsRoot.mtProxyTgLinkForAdditional(modelData))
|
||||||
ExportController.generateQrFromString(settingsRoot.mtProxyTgLinkForAdditional(modelData))
|
|
||||||
PageController.goToShareConnectionPage(
|
|
||||||
qsTr("Telegram connection link"),
|
|
||||||
qsTr("MTProxy connection link"),
|
|
||||||
"", "", "")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageButtonType {
|
ImageButtonType {
|
||||||
@@ -1527,10 +1523,7 @@ PageType {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
image: "qrc:/images/controls/copy.svg"
|
image: "qrc:/images/controls/copy.svg"
|
||||||
imageColor: AmneziaStyle.color.paleGray
|
imageColor: AmneziaStyle.color.paleGray
|
||||||
onClicked: {
|
onClicked: settingsRoot.mtProxyCopyText(settingsRoot.mtProxyTgLinkForAdditional(modelData))
|
||||||
GC.copyToClipBoard(settingsRoot.mtProxyTgLinkForAdditional(modelData))
|
|
||||||
PageController.showNotificationMessage(qsTr("Copied"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1615,8 +1608,6 @@ PageType {
|
|||||||
textField.text: workers
|
textField.text: workers
|
||||||
textField.maximumLength: 2
|
textField.maximumLength: 2
|
||||||
textField.inputMethodHints: Qt.ImhDigitsOnly
|
textField.inputMethodHints: Qt.ImhDigitsOnly
|
||||||
// Range input like the port field: IntValidator bounds the value and the
|
|
||||||
// clamp keeps it within 0..maxWorkers on every change (rejects 33+, neg.).
|
|
||||||
textField.validator: IntValidator {
|
textField.validator: IntValidator {
|
||||||
bottom: 0
|
bottom: 0
|
||||||
top: MtProxyConfigModel.maxWorkers()
|
top: MtProxyConfigModel.maxWorkers()
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ PageType {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property int containerStatus: 1
|
property int containerStatus: 1
|
||||||
// Last status-query error code (0 = none). 305 = SshTimeoutError → server unreachable.
|
|
||||||
property int statusErrorCode: 0
|
property int statusErrorCode: 0
|
||||||
property bool isUpdating: false
|
property bool isUpdating: false
|
||||||
property bool isCheckingStatus: false
|
property bool isCheckingStatus: false
|
||||||
@@ -871,6 +870,25 @@ PageType {
|
|||||||
return "tg://proxy?server=" + telemtEffectiveHostForLinks() + "&port=" + port + "&secret=" + telemtActiveSecretForBaseHex(baseHex)
|
return "tg://proxy?server=" + telemtEffectiveHostForLinks() + "&port=" + port + "&secret=" + telemtActiveSecretForBaseHex(baseHex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function telemtIsAdditionalPersisted(hex) {
|
||||||
|
return root.telemtIsPersistedAdditionalHex(hex)
|
||||||
|
}
|
||||||
|
|
||||||
|
function telemtCopyText(text) {
|
||||||
|
GC.copyToClipBoard(text)
|
||||||
|
PageController.showNotificationMessage(qsTr("Copied"))
|
||||||
|
}
|
||||||
|
|
||||||
|
function telemtShareQr(link) {
|
||||||
|
ExportController.generateQrFromString(link)
|
||||||
|
PageController.goToShareConnectionPage(qsTr("Telegram connection link"),
|
||||||
|
qsTr("Telemt connection link"), "", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
function telemtRemoveAdditionalSecret(idx) {
|
||||||
|
TelemtConfigModel.removeAdditionalSecret(idx)
|
||||||
|
}
|
||||||
|
|
||||||
SwitcherType {
|
SwitcherType {
|
||||||
id: enableTelemtSwitch
|
id: enableTelemtSwitch
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -1329,7 +1347,7 @@ PageType {
|
|||||||
delegate: ColumnLayout {
|
delegate: ColumnLayout {
|
||||||
id: addSecretDelegate
|
id: addSecretDelegate
|
||||||
property bool linksExpanded: false
|
property bool linksExpanded: false
|
||||||
readonly property bool linksPanelAllowed: root.telemtIsPersistedAdditionalHex(modelData)
|
readonly property bool linksPanelAllowed: settingsRoot.telemtIsAdditionalPersisted(modelData)
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
@@ -1386,11 +1404,7 @@ PageType {
|
|||||||
sourceSize.width: 24
|
sourceSize.width: 24
|
||||||
sourceSize.height: 24
|
sourceSize.height: 24
|
||||||
rotation: addSecretDelegate.linksExpanded ? 180 : 0
|
rotation: addSecretDelegate.linksExpanded ? 180 : 0
|
||||||
Behavior on rotation {
|
Behavior on rotation { NumberAnimation { duration: 150 } }
|
||||||
NumberAnimation {
|
|
||||||
duration: 150
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1407,15 +1421,9 @@ PageType {
|
|||||||
implicitWidth: 32
|
implicitWidth: 32
|
||||||
implicitHeight: 32
|
implicitHeight: 32
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
visible: ServersUiController.isProcessedServerHasWriteAccess()
|
|
||||||
image: "qrc:/images/controls/trash.svg"
|
image: "qrc:/images/controls/trash.svg"
|
||||||
imageColor: AmneziaStyle.color.vibrantRed
|
imageColor: AmneziaStyle.color.vibrantRed
|
||||||
onClicked: {
|
onClicked: settingsRoot.telemtRemoveAdditionalSecret(index)
|
||||||
TelemtConfigModel.removeAdditionalSecret(index)
|
|
||||||
if (containerStatus === 1) {
|
|
||||||
root.telemtScheduleUpdate(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1464,13 +1472,7 @@ PageType {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
image: "qrc:/images/controls/qr-code.svg"
|
image: "qrc:/images/controls/qr-code.svg"
|
||||||
imageColor: AmneziaStyle.color.paleGray
|
imageColor: AmneziaStyle.color.paleGray
|
||||||
onClicked: {
|
onClicked: settingsRoot.telemtShareQr(settingsRoot.telemtTmeLinkForAdditional(modelData))
|
||||||
ExportController.generateQrFromString(settingsRoot.telemtTmeLinkForAdditional(modelData))
|
|
||||||
PageController.goToShareConnectionPage(
|
|
||||||
qsTr("Telegram connection link"),
|
|
||||||
qsTr("Telemt connection link"),
|
|
||||||
"", "", "")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageButtonType {
|
ImageButtonType {
|
||||||
@@ -1479,10 +1481,7 @@ PageType {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
image: "qrc:/images/controls/copy.svg"
|
image: "qrc:/images/controls/copy.svg"
|
||||||
imageColor: AmneziaStyle.color.paleGray
|
imageColor: AmneziaStyle.color.paleGray
|
||||||
onClicked: {
|
onClicked: settingsRoot.telemtCopyText(settingsRoot.telemtTmeLinkForAdditional(modelData))
|
||||||
GC.copyToClipBoard(settingsRoot.telemtTmeLinkForAdditional(modelData))
|
|
||||||
PageController.showNotificationMessage(qsTr("Copied"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1519,13 +1518,7 @@ PageType {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
image: "qrc:/images/controls/qr-code.svg"
|
image: "qrc:/images/controls/qr-code.svg"
|
||||||
imageColor: AmneziaStyle.color.paleGray
|
imageColor: AmneziaStyle.color.paleGray
|
||||||
onClicked: {
|
onClicked: settingsRoot.telemtShareQr(settingsRoot.telemtTgLinkForAdditional(modelData))
|
||||||
ExportController.generateQrFromString(settingsRoot.telemtTgLinkForAdditional(modelData))
|
|
||||||
PageController.goToShareConnectionPage(
|
|
||||||
qsTr("Telegram connection link"),
|
|
||||||
qsTr("Telemt connection link"),
|
|
||||||
"", "", "")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageButtonType {
|
ImageButtonType {
|
||||||
@@ -1534,10 +1527,7 @@ PageType {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
image: "qrc:/images/controls/copy.svg"
|
image: "qrc:/images/controls/copy.svg"
|
||||||
imageColor: AmneziaStyle.color.paleGray
|
imageColor: AmneziaStyle.color.paleGray
|
||||||
onClicked: {
|
onClicked: settingsRoot.telemtCopyText(settingsRoot.telemtTgLinkForAdditional(modelData))
|
||||||
GC.copyToClipBoard(settingsRoot.telemtTgLinkForAdditional(modelData))
|
|
||||||
PageController.showNotificationMessage(qsTr("Copied"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1622,8 +1612,6 @@ PageType {
|
|||||||
textField.text: workers
|
textField.text: workers
|
||||||
textField.maximumLength: 2
|
textField.maximumLength: 2
|
||||||
textField.inputMethodHints: Qt.ImhDigitsOnly
|
textField.inputMethodHints: Qt.ImhDigitsOnly
|
||||||
// Range input like the port field: IntValidator bounds the value and the
|
|
||||||
// clamp keeps it within 0..maxWorkers on every change (rejects 33+, neg.).
|
|
||||||
textField.validator: IntValidator {
|
textField.validator: IntValidator {
|
||||||
bottom: 0
|
bottom: 0
|
||||||
top: TelemtConfigModel.maxWorkers()
|
top: TelemtConfigModel.maxWorkers()
|
||||||
|
|||||||
Reference in New Issue
Block a user