Browse Source

Change placement of stop tracker timeout

adaptive-webui-19844
An0n 5 years ago committed by an0n666
parent
commit
bf32e90c40
  1. 33
      src/base/bittorrent/session.cpp
  2. 6
      src/base/bittorrent/session.h
  3. 17
      src/gui/advancedsettings.cpp
  4. 4
      src/gui/advancedsettings.h
  5. 14
      src/webui/api/appcontroller.cpp
  6. 20
      src/webui/www/private/views/preferences.html

33
src/base/bittorrent/session.cpp

@ -373,7 +373,6 @@ Session::Session(QObject *parent)
, m_announceToAllTrackers(BITTORRENT_SESSION_KEY("AnnounceToAllTrackers"), false) , m_announceToAllTrackers(BITTORRENT_SESSION_KEY("AnnounceToAllTrackers"), false)
, m_announceToAllTiers(BITTORRENT_SESSION_KEY("AnnounceToAllTiers"), true) , m_announceToAllTiers(BITTORRENT_SESSION_KEY("AnnounceToAllTiers"), true)
, m_asyncIOThreads(BITTORRENT_SESSION_KEY("AsyncIOThreadsCount"), 4) , m_asyncIOThreads(BITTORRENT_SESSION_KEY("AsyncIOThreadsCount"), 4)
, m_stopTrackerTimeout(BITTORRENT_SESSION_KEY("StopTrackerTimeout"), 1)
, m_filePoolSize(BITTORRENT_SESSION_KEY("FilePoolSize"), 40) , m_filePoolSize(BITTORRENT_SESSION_KEY("FilePoolSize"), 40)
, m_checkingMemUsage(BITTORRENT_SESSION_KEY("CheckingMemUsageSize"), 32) , m_checkingMemUsage(BITTORRENT_SESSION_KEY("CheckingMemUsageSize"), 32)
, m_diskCacheSize(BITTORRENT_SESSION_KEY("DiskCacheSize"), -1) , m_diskCacheSize(BITTORRENT_SESSION_KEY("DiskCacheSize"), -1)
@ -403,6 +402,7 @@ Session::Session(QObject *parent)
, m_ignoreLimitsOnLAN(BITTORRENT_SESSION_KEY("IgnoreLimitsOnLAN"), false) , m_ignoreLimitsOnLAN(BITTORRENT_SESSION_KEY("IgnoreLimitsOnLAN"), false)
, m_includeOverheadInLimits(BITTORRENT_SESSION_KEY("IncludeOverheadInLimits"), false) , m_includeOverheadInLimits(BITTORRENT_SESSION_KEY("IncludeOverheadInLimits"), false)
, m_announceIP(BITTORRENT_SESSION_KEY("AnnounceIP")) , m_announceIP(BITTORRENT_SESSION_KEY("AnnounceIP"))
, m_stopTrackerTimeout(BITTORRENT_SESSION_KEY("StopTrackerTimeout"), 1)
, m_isSuperSeedingEnabled(BITTORRENT_SESSION_KEY("SuperSeedingEnabled"), false) , m_isSuperSeedingEnabled(BITTORRENT_SESSION_KEY("SuperSeedingEnabled"), false)
, m_maxConnections(BITTORRENT_SESSION_KEY("MaxConnections"), 500, lowerLimited(0, -1)) , m_maxConnections(BITTORRENT_SESSION_KEY("MaxConnections"), 500, lowerLimited(0, -1))
, m_maxUploads(BITTORRENT_SESSION_KEY("MaxUploads"), -1, lowerLimited(0, -1)) , m_maxUploads(BITTORRENT_SESSION_KEY("MaxUploads"), -1, lowerLimited(0, -1))
@ -1304,7 +1304,6 @@ void Session::loadLTSettings(lt::settings_pack &settingsPack)
settingsPack.set_bool(lt::settings_pack::announce_to_all_tiers, announceToAllTiers()); settingsPack.set_bool(lt::settings_pack::announce_to_all_tiers, announceToAllTiers());
settingsPack.set_int(lt::settings_pack::aio_threads, asyncIOThreads()); settingsPack.set_int(lt::settings_pack::aio_threads, asyncIOThreads());
settingsPack.set_int(lt::settings_pack::stop_tracker_timeout, stopTrackerTimeout());
settingsPack.set_int(lt::settings_pack::file_pool_size, filePoolSize()); settingsPack.set_int(lt::settings_pack::file_pool_size, filePoolSize());
const int checkingMemUsageSize = checkingMemUsage() * 64; const int checkingMemUsageSize = checkingMemUsage() * 64;
@ -1360,6 +1359,8 @@ void Session::loadLTSettings(lt::settings_pack &settingsPack)
settingsPack.set_bool(lt::settings_pack::rate_limit_ip_overhead, includeOverheadInLimits()); settingsPack.set_bool(lt::settings_pack::rate_limit_ip_overhead, includeOverheadInLimits());
// IP address to announce to trackers // IP address to announce to trackers
settingsPack.set_str(lt::settings_pack::announce_ip, announceIP().toStdString()); settingsPack.set_str(lt::settings_pack::announce_ip, announceIP().toStdString());
// Stop tracker timeout
settingsPack.set_int(lt::settings_pack::stop_tracker_timeout, stopTrackerTimeout());
// Super seeding // Super seeding
settingsPack.set_bool(lt::settings_pack::strict_super_seeding, isSuperSeedingEnabled()); settingsPack.set_bool(lt::settings_pack::strict_super_seeding, isSuperSeedingEnabled());
// * Max connections limit // * Max connections limit
@ -3149,20 +3150,6 @@ void Session::setAsyncIOThreads(const int num)
configureDeferred(); configureDeferred();
} }
int Session::stopTrackerTimeout() const
{
return m_stopTrackerTimeout;
}
void Session::setStopTrackerTimeout(const int value)
{
if (value == m_stopTrackerTimeout)
return;
m_stopTrackerTimeout = value;
configureDeferred();
}
int Session::filePoolSize() const int Session::filePoolSize() const
{ {
return m_filePoolSize; return m_filePoolSize;
@ -3517,6 +3504,20 @@ void Session::setAnnounceIP(const QString &ip)
} }
} }
int Session::stopTrackerTimeout() const
{
return m_stopTrackerTimeout;
}
void Session::setStopTrackerTimeout(const int value)
{
if (value == m_stopTrackerTimeout)
return;
m_stopTrackerTimeout = value;
configureDeferred();
}
bool Session::isSuperSeedingEnabled() const bool Session::isSuperSeedingEnabled() const
{ {
return m_isSuperSeedingEnabled; return m_isSuperSeedingEnabled;

6
src/base/bittorrent/session.h

@ -325,8 +325,6 @@ namespace BitTorrent
void setAnnounceToAllTiers(bool val); void setAnnounceToAllTiers(bool val);
int asyncIOThreads() const; int asyncIOThreads() const;
void setAsyncIOThreads(int num); void setAsyncIOThreads(int num);
int stopTrackerTimeout() const;
void setStopTrackerTimeout(int value);
int filePoolSize() const; int filePoolSize() const;
void setFilePoolSize(int size); void setFilePoolSize(int size);
int checkingMemUsage() const; int checkingMemUsage() const;
@ -371,6 +369,8 @@ namespace BitTorrent
void setIncludeOverheadInLimits(bool include); void setIncludeOverheadInLimits(bool include);
QString announceIP() const; QString announceIP() const;
void setAnnounceIP(const QString &ip); void setAnnounceIP(const QString &ip);
int stopTrackerTimeout() const;
void setStopTrackerTimeout(int value);
bool isSuperSeedingEnabled() const; bool isSuperSeedingEnabled() const;
void setSuperSeedingEnabled(bool enabled); void setSuperSeedingEnabled(bool enabled);
int maxConnections() const; int maxConnections() const;
@ -606,7 +606,6 @@ namespace BitTorrent
CachedSettingValue<bool> m_announceToAllTrackers; CachedSettingValue<bool> m_announceToAllTrackers;
CachedSettingValue<bool> m_announceToAllTiers; CachedSettingValue<bool> m_announceToAllTiers;
CachedSettingValue<int> m_asyncIOThreads; CachedSettingValue<int> m_asyncIOThreads;
CachedSettingValue<int> m_stopTrackerTimeout;
CachedSettingValue<int> m_filePoolSize; CachedSettingValue<int> m_filePoolSize;
CachedSettingValue<int> m_checkingMemUsage; CachedSettingValue<int> m_checkingMemUsage;
CachedSettingValue<int> m_diskCacheSize; CachedSettingValue<int> m_diskCacheSize;
@ -632,6 +631,7 @@ namespace BitTorrent
CachedSettingValue<bool> m_ignoreLimitsOnLAN; CachedSettingValue<bool> m_ignoreLimitsOnLAN;
CachedSettingValue<bool> m_includeOverheadInLimits; CachedSettingValue<bool> m_includeOverheadInLimits;
CachedSettingValue<QString> m_announceIP; CachedSettingValue<QString> m_announceIP;
CachedSettingValue<int> m_stopTrackerTimeout;
CachedSettingValue<bool> m_isSuperSeedingEnabled; CachedSettingValue<bool> m_isSuperSeedingEnabled;
CachedSettingValue<int> m_maxConnections; CachedSettingValue<int> m_maxConnections;
CachedSettingValue<int> m_maxUploads; CachedSettingValue<int> m_maxUploads;

17
src/gui/advancedsettings.cpp

@ -89,7 +89,6 @@ enum AdvSettingsRows
// libtorrent section // libtorrent section
LIBTORRENT_HEADER, LIBTORRENT_HEADER,
ASYNC_IO_THREADS, ASYNC_IO_THREADS,
STOP_TRACKER_TIMEOUT,
FILE_POOL_SIZE, FILE_POOL_SIZE,
CHECKING_MEM_USAGE, CHECKING_MEM_USAGE,
// cache // cache
@ -118,6 +117,7 @@ enum AdvSettingsRows
ANNOUNCE_ALL_TRACKERS, ANNOUNCE_ALL_TRACKERS,
ANNOUNCE_ALL_TIERS, ANNOUNCE_ALL_TIERS,
ANNOUNCE_IP, ANNOUNCE_IP,
STOP_TRACKER_TIMEOUT,
ROW_COUNT ROW_COUNT
}; };
@ -178,8 +178,6 @@ void AdvancedSettings::saveAdvancedSettings()
#endif #endif
// Async IO threads // Async IO threads
session->setAsyncIOThreads(m_spinBoxAsyncIOThreads.value()); session->setAsyncIOThreads(m_spinBoxAsyncIOThreads.value());
// Stop tracker timeout
session->setStopTrackerTimeout(m_spinBoxStopTrackerTimeout.value());
// File pool size // File pool size
session->setFilePoolSize(m_spinBoxFilePoolSize.value()); session->setFilePoolSize(m_spinBoxFilePoolSize.value());
// Checking Memory Usage // Checking Memory Usage
@ -237,7 +235,8 @@ void AdvancedSettings::saveAdvancedSettings()
// Construct a QHostAddress to filter malformed strings // Construct a QHostAddress to filter malformed strings
const QHostAddress addr(m_lineEditAnnounceIP.text().trimmed()); const QHostAddress addr(m_lineEditAnnounceIP.text().trimmed());
session->setAnnounceIP(addr.toString()); session->setAnnounceIP(addr.toString());
// Stop tracker timeout
session->setStopTrackerTimeout(m_spinBoxStopTrackerTimeout.value());
// Program notification // Program notification
MainWindow *const mainWindow = static_cast<Application*>(QCoreApplication::instance())->mainWindow(); MainWindow *const mainWindow = static_cast<Application*>(QCoreApplication::instance())->mainWindow();
mainWindow->setNotificationsEnabled(m_checkBoxProgramNotifications.isChecked()); mainWindow->setNotificationsEnabled(m_checkBoxProgramNotifications.isChecked());
@ -379,11 +378,6 @@ void AdvancedSettings::loadAdvancedSettings()
m_spinBoxAsyncIOThreads.setValue(session->asyncIOThreads()); m_spinBoxAsyncIOThreads.setValue(session->asyncIOThreads());
addRow(ASYNC_IO_THREADS, (tr("Asynchronous I/O threads") + ' ' + makeLink("https://www.libtorrent.org/reference-Settings.html#aio_threads", "(?)")) addRow(ASYNC_IO_THREADS, (tr("Asynchronous I/O threads") + ' ' + makeLink("https://www.libtorrent.org/reference-Settings.html#aio_threads", "(?)"))
, &m_spinBoxAsyncIOThreads); , &m_spinBoxAsyncIOThreads);
// stop tracker timeout
m_spinBoxStopTrackerTimeout.setValue(session->stopTrackerTimeout());
m_spinBoxStopTrackerTimeout.setSuffix(tr(" s", " seconds"));
addRow(STOP_TRACKER_TIMEOUT, (tr("Stop tracker timeout") + ' ' + makeLink("https://www.libtorrent.org/reference-Settings.html#stop_tracker_timeout", "(?)"))
, &m_spinBoxStopTrackerTimeout);
// File pool size // File pool size
m_spinBoxFilePoolSize.setMinimum(1); m_spinBoxFilePoolSize.setMinimum(1);
m_spinBoxFilePoolSize.setMaximum(std::numeric_limits<int>::max()); m_spinBoxFilePoolSize.setMaximum(std::numeric_limits<int>::max());
@ -531,6 +525,11 @@ void AdvancedSettings::loadAdvancedSettings()
// Announce IP // Announce IP
m_lineEditAnnounceIP.setText(session->announceIP()); m_lineEditAnnounceIP.setText(session->announceIP());
addRow(ANNOUNCE_IP, tr("IP Address to report to trackers (requires restart)"), &m_lineEditAnnounceIP); addRow(ANNOUNCE_IP, tr("IP Address to report to trackers (requires restart)"), &m_lineEditAnnounceIP);
// stop tracker timeout
m_spinBoxStopTrackerTimeout.setValue(session->stopTrackerTimeout());
m_spinBoxStopTrackerTimeout.setSuffix(tr(" s", " seconds"));
addRow(STOP_TRACKER_TIMEOUT, (tr("Stop tracker timeout") + ' ' + makeLink("https://www.libtorrent.org/reference-Settings.html#stop_tracker_timeout", "(?)"))
, &m_spinBoxStopTrackerTimeout);
// Program notifications // Program notifications
const MainWindow *const mainWindow = static_cast<Application*>(QCoreApplication::instance())->mainWindow(); const MainWindow *const mainWindow = static_cast<Application*>(QCoreApplication::instance())->mainWindow();

4
src/gui/advancedsettings.h

@ -57,10 +57,10 @@ private:
void loadAdvancedSettings(); void loadAdvancedSettings();
template <typename T> void addRow(int row, const QString &text, T *widget); template <typename T> void addRow(int row, const QString &text, T *widget);
QSpinBox m_spinBoxAsyncIOThreads, m_spinBoxStopTrackerTimeout, m_spinBoxFilePoolSize, m_spinBoxCheckingMemUsage, m_spinBoxCache, QSpinBox m_spinBoxAsyncIOThreads, m_spinBoxFilePoolSize, m_spinBoxCheckingMemUsage, m_spinBoxCache,
m_spinBoxSaveResumeDataInterval, m_spinBoxOutgoingPortsMin, m_spinBoxOutgoingPortsMax, m_spinBoxListRefresh, m_spinBoxSaveResumeDataInterval, m_spinBoxOutgoingPortsMin, m_spinBoxOutgoingPortsMax, m_spinBoxListRefresh,
m_spinBoxTrackerPort, m_spinBoxCacheTTL, m_spinBoxSendBufferWatermark, m_spinBoxSendBufferLowWatermark, m_spinBoxTrackerPort, m_spinBoxCacheTTL, m_spinBoxSendBufferWatermark, m_spinBoxSendBufferLowWatermark,
m_spinBoxSendBufferWatermarkFactor, m_spinBoxSocketBacklogSize, m_spinBoxSavePathHistoryLength; m_spinBoxSendBufferWatermarkFactor, m_spinBoxSocketBacklogSize, m_spinBoxStopTrackerTimeout, m_spinBoxSavePathHistoryLength;
QCheckBox m_checkBoxOsCache, m_checkBoxRecheckCompleted, m_checkBoxResolveCountries, m_checkBoxResolveHosts, m_checkBoxSuperSeeding, QCheckBox m_checkBoxOsCache, m_checkBoxRecheckCompleted, m_checkBoxResolveCountries, m_checkBoxResolveHosts, m_checkBoxSuperSeeding,
m_checkBoxProgramNotifications, m_checkBoxTorrentAddedNotifications, m_checkBoxTrackerFavicon, m_checkBoxTrackerStatus, m_checkBoxProgramNotifications, m_checkBoxTorrentAddedNotifications, m_checkBoxTrackerFavicon, m_checkBoxTrackerStatus,
m_checkBoxConfirmTorrentRecheck, m_checkBoxConfirmRemoveAllTags, m_checkBoxAnnounceAllTrackers, m_checkBoxAnnounceAllTiers, m_checkBoxConfirmTorrentRecheck, m_checkBoxConfirmRemoveAllTags, m_checkBoxAnnounceAllTrackers, m_checkBoxAnnounceAllTiers,

14
src/webui/api/appcontroller.cpp

@ -270,8 +270,6 @@ void AppController::preferencesAction()
// libtorrent preferences // libtorrent preferences
// Async IO threads // Async IO threads
data["async_io_threads"] = session->asyncIOThreads(); data["async_io_threads"] = session->asyncIOThreads();
// stop tracker timeout
data["stop_tracker_timeout"] = session->stopTrackerTimeout();
// File pool size // File pool size
data["file_pool_size"] = session->filePoolSize(); data["file_pool_size"] = session->filePoolSize();
// Checking memory usage // Checking memory usage
@ -311,6 +309,8 @@ void AppController::preferencesAction()
data["announce_to_all_trackers"] = session->announceToAllTrackers(); data["announce_to_all_trackers"] = session->announceToAllTrackers();
data["announce_to_all_tiers"] = session->announceToAllTiers(); data["announce_to_all_tiers"] = session->announceToAllTiers();
data["announce_ip"] = session->announceIP(); data["announce_ip"] = session->announceIP();
// Stop tracker timeout
data["stop_tracker_timeout"] = session->stopTrackerTimeout();
setResult(data); setResult(data);
} }
@ -649,8 +649,8 @@ void AppController::setPreferencesAction()
}); });
const QString ifaceName = (ifacesIter != ifaces.cend()) ? ifacesIter->humanReadableName() : QString {}; const QString ifaceName = (ifacesIter != ifaces.cend()) ? ifacesIter->humanReadableName() : QString {};
session->setNetworkInterface(ifaceValue); session->setNetworkInterface(ifaceValue);
session->setNetworkInterfaceName(ifaceName); session->setNetworkInterfaceName(ifaceName);
} }
// Current network interface address // Current network interface address
if (hasKey("current_interface_address")) { if (hasKey("current_interface_address")) {
@ -671,9 +671,6 @@ void AppController::setPreferencesAction()
// Async IO threads // Async IO threads
if (hasKey("async_io_threads")) if (hasKey("async_io_threads"))
session->setAsyncIOThreads(it.value().toInt()); session->setAsyncIOThreads(it.value().toInt());
// Stop tracker timeout
if (hasKey("stop_tracker_timeout"))
session->setStopTrackerTimeout(it.value().toInt());
// File pool size // File pool size
if (hasKey("file_pool_size")) if (hasKey("file_pool_size"))
session->setFilePoolSize(it.value().toInt()); session->setFilePoolSize(it.value().toInt());
@ -738,6 +735,9 @@ void AppController::setPreferencesAction()
const QHostAddress announceAddr {it.value().toString().trimmed()}; const QHostAddress announceAddr {it.value().toString().trimmed()};
session->setAnnounceIP(announceAddr.isNull() ? QString {} : announceAddr.toString()); session->setAnnounceIP(announceAddr.isNull() ? QString {} : announceAddr.toString());
} }
// Stop tracker timeout
if (hasKey("stop_tracker_timeout"))
session->setStopTrackerTimeout(it.value().toInt());
// Save preferences // Save preferences
pref->apply(); pref->apply();

20
src/webui/www/private/views/preferences.html

@ -878,14 +878,6 @@
<input type="text" id="asyncIOThreads" style="width: 15em;" /> <input type="text" id="asyncIOThreads" style="width: 15em;" />
</td> </td>
</tr> </tr>
<tr>
<td>
<label for="stopTrackerTimeout">QBT_TR(Stop tracker timeout:)QBT_TR[CONTEXT=OptionsDialog]&nbsp;<a href="https://www.libtorrent.org/reference-Settings.html#stop_tracker_timeout" target="_blank">(?)</a></label>
</td>
<td>
<input type="text" id="stopTrackerTimeout" style="width: 15em;" />
</td>
</tr>
<tr> <tr>
<td> <td>
<label for="filePoolSize">QBT_TR(File pool size:)QBT_TR[CONTEXT=OptionsDialog]&nbsp;<a href="https://www.libtorrent.org/reference-Settings.html#file_pool_size" target="_blank">(?)</a></label> <label for="filePoolSize">QBT_TR(File pool size:)QBT_TR[CONTEXT=OptionsDialog]&nbsp;<a href="https://www.libtorrent.org/reference-Settings.html#file_pool_size" target="_blank">(?)</a></label>
@ -1080,6 +1072,14 @@
<input type="text" id="announceIP" style="width: 15em;" /> <input type="text" id="announceIP" style="width: 15em;" />
</td> </td>
</tr> </tr>
<tr>
<td>
<label for="stopTrackerTimeout">QBT_TR(Stop tracker timeout:)QBT_TR[CONTEXT=OptionsDialog]&nbsp;<a href="https://www.libtorrent.org/reference-Settings.html#stop_tracker_timeout" target="_blank">(?)</a></label>
</td>
<td>
<input type="text" id="stopTrackerTimeout" style="width: 15em;" />
</td>
</tr>
</table> </table>
</fieldset> </fieldset>
</div> </div>
@ -1742,7 +1742,6 @@
$('resolvePeerCountries').setProperty('checked', pref.resolve_peer_countries); $('resolvePeerCountries').setProperty('checked', pref.resolve_peer_countries);
// libtorrent section // libtorrent section
$('asyncIOThreads').setProperty('value', pref.async_io_threads); $('asyncIOThreads').setProperty('value', pref.async_io_threads);
$('stopTrackerTimeout').setProperty('value', pref.stop_tracker_timeout);
$('filePoolSize').setProperty('value', pref.file_pool_size); $('filePoolSize').setProperty('value', pref.file_pool_size);
$('outstandMemoryWhenCheckingTorrents').setProperty('value', pref.checking_memory_use); $('outstandMemoryWhenCheckingTorrents').setProperty('value', pref.checking_memory_use);
$('diskCache').setProperty('value', pref.disk_cache); $('diskCache').setProperty('value', pref.disk_cache);
@ -1766,6 +1765,7 @@
$('announceAllTrackers').setProperty('checked', pref.announce_to_all_trackers); $('announceAllTrackers').setProperty('checked', pref.announce_to_all_trackers);
$('announceAllTiers').setProperty('checked', pref.announce_to_all_tiers); $('announceAllTiers').setProperty('checked', pref.announce_to_all_tiers);
$('announceIP').setProperty('value', pref.announce_ip); $('announceIP').setProperty('value', pref.announce_ip);
$('stopTrackerTimeout').setProperty('value', pref.stop_tracker_timeout);
} }
} }
}).send(); }).send();
@ -2107,7 +2107,6 @@
// libtorrent section // libtorrent section
settings.set('async_io_threads', $('asyncIOThreads').getProperty('value')); settings.set('async_io_threads', $('asyncIOThreads').getProperty('value'));
settings.set('stop_tracker_timeout', $('stopTrackerTimeout').getProperty('value'));
settings.set('file_pool_size', $('filePoolSize').getProperty('value')); settings.set('file_pool_size', $('filePoolSize').getProperty('value'));
settings.set('checking_memory_use', $('outstandMemoryWhenCheckingTorrents').getProperty('value')); settings.set('checking_memory_use', $('outstandMemoryWhenCheckingTorrents').getProperty('value'));
settings.set('disk_cache', $('diskCache').getProperty('value')); settings.set('disk_cache', $('diskCache').getProperty('value'));
@ -2131,6 +2130,7 @@
settings.set('announce_to_all_trackers', $('announceAllTrackers').getProperty('checked')); settings.set('announce_to_all_trackers', $('announceAllTrackers').getProperty('checked'));
settings.set('announce_to_all_tiers', $('announceAllTiers').getProperty('checked')); settings.set('announce_to_all_tiers', $('announceAllTiers').getProperty('checked'));
settings.set('announce_ip', $('announceIP').getProperty('value')); settings.set('announce_ip', $('announceIP').getProperty('value'));
settings.set('stop_tracker_timeout', $('stopTrackerTimeout').getProperty('value'));
// Send it to qBT // Send it to qBT
const json_str = JSON.encode(settings); const json_str = JSON.encode(settings);

Loading…
Cancel
Save