core_settings.cpp 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "core/core_settings.h"
  8. #include "base/platform/base_platform_info.h"
  9. #include "calls/group/calls_group_common.h"
  10. #include "history/view/history_view_quick_action.h"
  11. #include "lang/lang_keys.h"
  12. #include "platform/platform_notifications_manager.h"
  13. #include "spellcheck/spellcheck_types.h"
  14. #include "storage/serialize_common.h"
  15. #include "ui/gl/gl_detection.h"
  16. #include "ui/widgets/fields/input_field.h"
  17. #include "webrtc/webrtc_create_adm.h"
  18. #include "webrtc/webrtc_device_common.h"
  19. #include "window/section_widget.h"
  20. namespace Core {
  21. namespace {
  22. constexpr auto kInitialVideoQuality = 480; // Start with SD.
  23. [[nodiscard]] WindowPosition Deserialize(const QByteArray &data) {
  24. QDataStream stream(data);
  25. stream.setVersion(QDataStream::Qt_5_1);
  26. auto result = WindowPosition();
  27. stream
  28. >> result.x
  29. >> result.y
  30. >> result.w
  31. >> result.h
  32. >> result.moncrc
  33. >> result.maximized
  34. >> result.scale;
  35. return result;
  36. }
  37. void LogPosition(const WindowPosition &position, const QString &name) {
  38. DEBUG_LOG(("%1 Pos: Writing to storage %2, %3, %4, %5"
  39. " (scale %6%, maximized %7)")
  40. .arg(name)
  41. .arg(position.x)
  42. .arg(position.y)
  43. .arg(position.w)
  44. .arg(position.h)
  45. .arg(position.scale)
  46. .arg(position.maximized));
  47. }
  48. [[nodiscard]] QByteArray Serialize(const WindowPosition &position) {
  49. auto result = QByteArray();
  50. const auto size = 7 * sizeof(qint32);
  51. result.reserve(size);
  52. {
  53. QDataStream stream(&result, QIODevice::WriteOnly);
  54. stream.setVersion(QDataStream::Qt_5_1);
  55. stream
  56. << qint32(position.x)
  57. << qint32(position.y)
  58. << qint32(position.w)
  59. << qint32(position.h)
  60. << qint32(position.moncrc)
  61. << qint32(position.maximized)
  62. << qint32(position.scale);
  63. }
  64. return result;
  65. }
  66. [[nodiscard]] QString Serialize(RecentEmojiDocument document) {
  67. return u"%1-%2"_q.arg(document.id).arg(document.test ? 1 : 0);
  68. }
  69. [[nodiscard]] std::optional<RecentEmojiDocument> ParseRecentEmojiDocument(
  70. const QString &serialized) {
  71. const auto parts = QStringView(serialized).split('-');
  72. if (parts.size() != 2 || parts[1].size() != 1) {
  73. return {};
  74. }
  75. const auto id = parts[0].toULongLong();
  76. const auto test = parts[1][0];
  77. if (!id || (test != '0' && test != '1')) {
  78. return {};
  79. }
  80. return RecentEmojiDocument{ id, (test == '1') };
  81. }
  82. [[nodiscard]] quint32 SerializeVideoQuality(Media::VideoQuality quality) {
  83. static_assert(sizeof(Media::VideoQuality) == sizeof(uint32));
  84. auto result = uint32();
  85. const auto data = static_cast<const void*>(&quality);
  86. memcpy(&result, data, sizeof(quality));
  87. return result;
  88. }
  89. [[nodiscard]] Media::VideoQuality DeserializeVideoQuality(quint32 value) {
  90. auto result = Media::VideoQuality();
  91. const auto data = static_cast<void*>(&result);
  92. memcpy(data, &value, sizeof(result));
  93. return (result.height <= 4320) ? result : Media::VideoQuality();
  94. }
  95. } // namespace
  96. [[nodiscard]] WindowPosition AdjustToScale(
  97. WindowPosition position,
  98. const QString &name) {
  99. DEBUG_LOG(("%1 Pos: Initializing first %2, %3, %4, %5 "
  100. "(scale %6%, maximized %7)")
  101. .arg(name)
  102. .arg(position.x)
  103. .arg(position.y)
  104. .arg(position.w)
  105. .arg(position.h)
  106. .arg(position.scale)
  107. .arg(position.maximized));
  108. if (!position.scale) {
  109. return position;
  110. }
  111. const auto scaleFactor = cScale() / float64(position.scale);
  112. if (scaleFactor != 1.) {
  113. // Change scale while keeping the position center in place.
  114. position.x += position.w / 2;
  115. position.y += position.h / 2;
  116. position.w *= scaleFactor;
  117. position.h *= scaleFactor;
  118. position.x -= position.w / 2;
  119. position.y -= position.h / 2;
  120. }
  121. return position;
  122. }
  123. Settings::Settings()
  124. : _sendSubmitWay(Ui::InputSubmitSettings::Enter)
  125. , _floatPlayerColumn(Window::Column::Second)
  126. , _floatPlayerCorner(RectPart::TopRight)
  127. , _dialogsWithChatWidthRatio(DefaultDialogsWidthRatio())
  128. , _dialogsNoChatWidthRatio(DefaultDialogsWidthRatio())
  129. , _videoQuality({ .height = kInitialVideoQuality }) {
  130. }
  131. Settings::~Settings() = default;
  132. QByteArray Settings::serialize() const {
  133. const auto themesAccentColors = _themesAccentColors.serialize();
  134. const auto windowPosition = Serialize(_windowPosition);
  135. LogPosition(_windowPosition, u"Window"_q);
  136. const auto mediaViewPosition = Serialize(_mediaViewPosition);
  137. LogPosition(_mediaViewPosition, u"Viewer"_q);
  138. const auto ivPosition = Serialize(_ivPosition);
  139. LogPosition(_ivPosition, u"IV"_q);
  140. const auto proxy = _proxy.serialize();
  141. const auto skipLanguages = _skipTranslationLanguages.current();
  142. auto recentEmojiPreloadGenerated = std::vector<RecentEmojiPreload>();
  143. if (_recentEmojiPreload.empty()) {
  144. recentEmojiPreloadGenerated.reserve(_recentEmoji.size());
  145. for (const auto &[id, rating] : _recentEmoji) {
  146. auto string = QString();
  147. if (const auto document = std::get_if<RecentEmojiDocument>(
  148. &id.data)) {
  149. string = Serialize(*document);
  150. } else if (const auto emoji = std::get_if<EmojiPtr>(&id.data)) {
  151. string = (*emoji)->id();
  152. }
  153. recentEmojiPreloadGenerated.push_back({ string, rating });
  154. }
  155. }
  156. const auto &recentEmojiPreloadData = _recentEmojiPreload.empty()
  157. ? recentEmojiPreloadGenerated
  158. : _recentEmojiPreload;
  159. const auto noWarningExtensions = QStringList(
  160. begin(_noWarningExtensions),
  161. end(_noWarningExtensions)
  162. ).join(' ');
  163. auto size = Serialize::bytearraySize(themesAccentColors)
  164. + sizeof(qint32) * 5
  165. + Serialize::stringSize(_downloadPath.current())
  166. + Serialize::bytearraySize(_downloadPathBookmark)
  167. + sizeof(qint32) * 9
  168. + Serialize::stringSize(QString()) // legacy call output device id
  169. + Serialize::stringSize(QString()) // legacy call input device id
  170. + sizeof(qint32) * 5;
  171. for (const auto &[key, value] : _soundOverrides) {
  172. size += Serialize::stringSize(key) + Serialize::stringSize(value);
  173. }
  174. size += sizeof(qint32) * 13
  175. + Serialize::bytearraySize(_videoPipGeometry)
  176. + sizeof(qint32)
  177. + (_dictionariesEnabled.current().size() * sizeof(quint64))
  178. + sizeof(qint32) * 12
  179. + Serialize::stringSize(_cameraDeviceId.current())
  180. + sizeof(qint32) * 2
  181. + Serialize::bytearraySize(_groupCallPushToTalkShortcut)
  182. + sizeof(qint64)
  183. + sizeof(qint32) * 2
  184. + Serialize::bytearraySize(windowPosition)
  185. + sizeof(qint32);
  186. for (const auto &[id, rating] : recentEmojiPreloadData) {
  187. size += Serialize::stringSize(id) + sizeof(quint16);
  188. }
  189. size += sizeof(qint32);
  190. for (const auto &[id, variant] : _emojiVariants) {
  191. size += Serialize::stringSize(id) + sizeof(quint8);
  192. }
  193. size += sizeof(qint32) * 3
  194. + Serialize::bytearraySize(proxy)
  195. + sizeof(qint32) * 2
  196. + Serialize::bytearraySize(_photoEditorBrush)
  197. + sizeof(qint32) * 3
  198. + Serialize::stringSize(_customDeviceModel.current())
  199. + sizeof(qint32) * 4
  200. + (_accountsOrder.size() * sizeof(quint64))
  201. + sizeof(qint32) * 7
  202. + (skipLanguages.size() * sizeof(quint64))
  203. + sizeof(qint32) * 2
  204. + sizeof(quint64)
  205. + sizeof(qint32) * 3
  206. + Serialize::bytearraySize(mediaViewPosition)
  207. + sizeof(qint32)
  208. + sizeof(quint64)
  209. + sizeof(qint32) * 2;
  210. for (const auto &id : _recentEmojiSkip) {
  211. size += Serialize::stringSize(id);
  212. }
  213. size += sizeof(qint32) * 2
  214. + Serialize::stringSize(_playbackDeviceId.current())
  215. + Serialize::stringSize(_captureDeviceId.current())
  216. + Serialize::stringSize(_callPlaybackDeviceId.current())
  217. + Serialize::stringSize(_callCaptureDeviceId.current())
  218. + Serialize::bytearraySize(ivPosition)
  219. + Serialize::stringSize(noWarningExtensions)
  220. + Serialize::stringSize(_customFontFamily)
  221. + sizeof(qint32) * 3
  222. + Serialize::bytearraySize(_tonsiteStorageToken)
  223. + sizeof(qint32) * 8;
  224. auto result = QByteArray();
  225. result.reserve(size);
  226. {
  227. QDataStream stream(&result, QIODevice::WriteOnly);
  228. stream.setVersion(QDataStream::Qt_5_1);
  229. stream
  230. << themesAccentColors
  231. << qint32(_adaptiveForWide.current() ? 1 : 0)
  232. << qint32(_moderateModeEnabled ? 1 : 0)
  233. << qint32(qRound(_songVolume.current() * 1e6))
  234. << qint32(qRound(_videoVolume.current() * 1e6))
  235. << qint32(_askDownloadPath ? 1 : 0)
  236. << _downloadPath.current()
  237. << _downloadPathBookmark
  238. << qint32(1)
  239. << qint32(_soundNotify ? 1 : 0)
  240. << qint32(_desktopNotify ? 1 : 0)
  241. << qint32(_flashBounceNotify ? 1 : 0)
  242. << static_cast<qint32>(_notifyView)
  243. << qint32(_nativeNotifications ? (*_nativeNotifications ? 1 : 2) : 0)
  244. << qint32(_notificationsCount)
  245. << static_cast<qint32>(_notificationsCorner)
  246. << qint32(_autoLock)
  247. << QString() // legacy call output device id
  248. << QString() // legacy call input device id
  249. << qint32(_callOutputVolume)
  250. << qint32(_callInputVolume)
  251. << qint32(_callAudioDuckingEnabled ? 1 : 0)
  252. << qint32(_lastSeenWarningSeen ? 1 : 0)
  253. << qint32(_soundOverrides.size());
  254. for (const auto &[key, value] : _soundOverrides) {
  255. stream << key << value;
  256. }
  257. stream
  258. << qint32(_sendFilesWay.serialize())
  259. << qint32(_sendSubmitWay.current())
  260. << qint32(_includeMutedCounter ? 1 : 0)
  261. << qint32(_countUnreadMessages ? 1 : 0)
  262. << qint32(1) // legacy exe launch warning
  263. << qint32(_notifyAboutPinned.current() ? 1 : 0)
  264. << qint32(_loopAnimatedStickers ? 1 : 0)
  265. << qint32(_largeEmoji.current() ? 1 : 0)
  266. << qint32(_replaceEmoji.current() ? 1 : 0)
  267. << qint32(_suggestEmoji ? 1 : 0)
  268. << qint32(_suggestStickersByEmoji ? 1 : 0)
  269. << qint32(_spellcheckerEnabled.current() ? 1 : 0)
  270. << qint32(SerializePlaybackSpeed(_videoPlaybackSpeed))
  271. << _videoPipGeometry
  272. << qint32(_dictionariesEnabled.current().size());
  273. for (const auto i : _dictionariesEnabled.current()) {
  274. stream << quint64(i);
  275. }
  276. stream
  277. << qint32(_autoDownloadDictionaries.current() ? 1 : 0)
  278. << qint32(_mainMenuAccountsShown.current() ? 1 : 0)
  279. << qint32(_tabbedSelectorSectionEnabled ? 1 : 0)
  280. << qint32(_floatPlayerColumn)
  281. << qint32(_floatPlayerCorner)
  282. << qint32(_thirdSectionInfoEnabled ? 1 : 0)
  283. << qint32(std::clamp(
  284. qRound(_dialogsWithChatWidthRatio.current() * 1000000),
  285. 0,
  286. 1000000))
  287. << qint32(_thirdColumnWidth.current())
  288. << qint32(_thirdSectionExtendedBy)
  289. << qint32(_notifyFromAll ? 1 : 0)
  290. << qint32(_nativeWindowFrame.current() ? 1 : 0)
  291. << qint32(0) // Legacy system dark mode
  292. << _cameraDeviceId.current()
  293. << qint32(_ipRevealWarning ? 1 : 0)
  294. << qint32(_groupCallPushToTalk ? 1 : 0)
  295. << _groupCallPushToTalkShortcut
  296. << qint64(_groupCallPushToTalkDelay)
  297. << qint32(0) // Call audio backend
  298. << qint32(0) // Legacy disable calls, now in session settings
  299. << windowPosition
  300. << qint32(recentEmojiPreloadData.size());
  301. for (const auto &[id, rating] : recentEmojiPreloadData) {
  302. stream << id << quint16(rating);
  303. }
  304. stream
  305. << qint32(_emojiVariants.size());
  306. for (const auto &[id, variant] : _emojiVariants) {
  307. stream << id << quint8(variant);
  308. }
  309. stream
  310. << qint32(0) // Old Disable OpenGL
  311. << qint32(0) // Old Noise Suppression
  312. << qint32(_workMode.current())
  313. << proxy
  314. << qint32(_hiddenGroupCallTooltips.value())
  315. << qint32(_disableOpenGL ? 1 : 0)
  316. << _photoEditorBrush
  317. << qint32(_groupCallNoiseSuppression ? 1 : 0)
  318. << qint32(SerializePlaybackSpeed(_voicePlaybackSpeed))
  319. << qint32(_closeBehavior)
  320. << _customDeviceModel.current()
  321. << qint32(_playerRepeatMode.current())
  322. << qint32(_playerOrderMode.current())
  323. << qint32(_macWarnBeforeQuit ? 1 : 0);
  324. stream
  325. << qint32(_accountsOrder.size());
  326. for (const auto &id : _accountsOrder) {
  327. stream << quint64(id);
  328. }
  329. stream
  330. << qint32(0) // old hardwareAcceleratedVideo
  331. << qint32(_chatQuickAction)
  332. << qint32(_hardwareAcceleratedVideo ? 1 : 0)
  333. << qint32(_suggestAnimatedEmoji ? 1 : 0)
  334. << qint32(_cornerReaction.current() ? 1 : 0)
  335. << qint32(_translateButtonEnabled ? 1 : 0);
  336. stream
  337. << qint32(skipLanguages.size());
  338. for (const auto &id : skipLanguages) {
  339. stream << quint64(id.value);
  340. }
  341. stream
  342. << qint32(_rememberedDeleteMessageOnlyForYou ? 1 : 0)
  343. << qint32(_translateChatEnabled.current() ? 1 : 0)
  344. << quint64(QLocale::Language(_translateToRaw.current()))
  345. << qint32(_windowTitleContent.current().hideChatName ? 1 : 0)
  346. << qint32(_windowTitleContent.current().hideAccountName ? 1 : 0)
  347. << qint32(_windowTitleContent.current().hideTotalUnread ? 1 : 0)
  348. << mediaViewPosition
  349. << qint32(_ignoreBatterySaving.current() ? 1 : 0)
  350. << quint64(_macRoundIconDigest.value_or(0))
  351. << qint32(_storiesClickTooltipHidden.current() ? 1 : 0)
  352. << qint32(_recentEmojiSkip.size());
  353. for (const auto &id : _recentEmojiSkip) {
  354. stream << id;
  355. }
  356. stream
  357. << qint32(_trayIconMonochrome.current() ? 1 : 0)
  358. << qint32(_ttlVoiceClickTooltipHidden.current() ? 1 : 0)
  359. << _playbackDeviceId.current()
  360. << _captureDeviceId.current()
  361. << _callPlaybackDeviceId.current()
  362. << _callCaptureDeviceId.current()
  363. << ivPosition
  364. << noWarningExtensions
  365. << _customFontFamily
  366. << qint32(std::clamp(
  367. qRound(_dialogsNoChatWidthRatio.current() * 1000000),
  368. 0,
  369. 1000000))
  370. << qint32(_systemUnlockEnabled ? 1 : 0)
  371. << qint32(!_weatherInCelsius ? 0 : *_weatherInCelsius ? 1 : 2)
  372. << _tonsiteStorageToken
  373. << qint32(_includeMutedCounterFolders ? 1 : 0)
  374. << qint32(_chatFiltersHorizontal.current() ? 1 : 0)
  375. << qint32(_skipToastsInFocus ? 1 : 0)
  376. << qint32(_recordVideoMessages ? 1 : 0)
  377. << SerializeVideoQuality(_videoQuality)
  378. << qint32(_ivZoom.current())
  379. << qint32(_systemDarkModeEnabled.current() ? 1 : 0)
  380. << qint32(_quickDialogAction);
  381. }
  382. Ensures(result.size() == size);
  383. return result;
  384. }
  385. void Settings::addFromSerialized(const QByteArray &serialized) {
  386. if (serialized.isEmpty()) {
  387. return;
  388. }
  389. QDataStream stream(serialized);
  390. stream.setVersion(QDataStream::Qt_5_1);
  391. QByteArray themesAccentColors;
  392. qint32 adaptiveForWide = _adaptiveForWide.current() ? 1 : 0;
  393. qint32 moderateModeEnabled = _moderateModeEnabled ? 1 : 0;
  394. qint32 songVolume = qint32(qRound(_songVolume.current() * 1e6));
  395. qint32 videoVolume = qint32(qRound(_videoVolume.current() * 1e6));
  396. qint32 askDownloadPath = _askDownloadPath ? 1 : 0;
  397. QString downloadPath = _downloadPath.current();
  398. QByteArray downloadPathBookmark = _downloadPathBookmark;
  399. qint32 nonDefaultVoicePlaybackSpeed = 1;
  400. qint32 soundNotify = _soundNotify ? 1 : 0;
  401. qint32 desktopNotify = _desktopNotify ? 1 : 0;
  402. qint32 flashBounceNotify = _flashBounceNotify ? 1 : 0;
  403. qint32 notifyView = static_cast<qint32>(_notifyView);
  404. qint32 nativeNotifications = _nativeNotifications ? (*_nativeNotifications ? 1 : 2) : 0;
  405. qint32 notificationsCount = _notificationsCount;
  406. qint32 notificationsCorner = static_cast<qint32>(_notificationsCorner);
  407. qint32 autoLock = _autoLock;
  408. QString playbackDeviceId = _playbackDeviceId.current();
  409. QString captureDeviceId = _captureDeviceId.current();
  410. QString cameraDeviceId = _cameraDeviceId.current();
  411. QString legacyCallPlaybackDeviceId = _callPlaybackDeviceId.current();
  412. QString legacyCallCaptureDeviceId = _callCaptureDeviceId.current();
  413. QString callPlaybackDeviceId = _callPlaybackDeviceId.current();
  414. QString callCaptureDeviceId = _callCaptureDeviceId.current();
  415. qint32 callOutputVolume = _callOutputVolume;
  416. qint32 callInputVolume = _callInputVolume;
  417. qint32 callAudioDuckingEnabled = _callAudioDuckingEnabled ? 1 : 0;
  418. qint32 lastSeenWarningSeen = _lastSeenWarningSeen ? 1 : 0;
  419. qint32 soundOverridesCount = 0;
  420. base::flat_map<QString, QString> soundOverrides;
  421. qint32 sendFilesWay = _sendFilesWay.serialize();
  422. qint32 sendSubmitWay = static_cast<qint32>(_sendSubmitWay.current());
  423. qint32 includeMutedCounter = _includeMutedCounter ? 1 : 0;
  424. qint32 includeMutedCounterFolders = _includeMutedCounterFolders ? 1 : 0;
  425. qint32 countUnreadMessages = _countUnreadMessages ? 1 : 0;
  426. std::optional<QString> noWarningExtensions;
  427. qint32 legacyExeLaunchWarning = 1;
  428. qint32 notifyAboutPinned = _notifyAboutPinned.current() ? 1 : 0;
  429. qint32 loopAnimatedStickers = _loopAnimatedStickers ? 1 : 0;
  430. qint32 largeEmoji = _largeEmoji.current() ? 1 : 0;
  431. qint32 replaceEmoji = _replaceEmoji.current() ? 1 : 0;
  432. qint32 suggestEmoji = _suggestEmoji ? 1 : 0;
  433. qint32 suggestStickersByEmoji = _suggestStickersByEmoji ? 1 : 0;
  434. qint32 spellcheckerEnabled = _spellcheckerEnabled.current() ? 1 : 0;
  435. qint32 videoPlaybackSpeed = SerializePlaybackSpeed(_videoPlaybackSpeed);
  436. qint32 voicePlaybackSpeed = SerializePlaybackSpeed(_voicePlaybackSpeed);
  437. QByteArray videoPipGeometry = _videoPipGeometry;
  438. qint32 dictionariesEnabledCount = 0;
  439. std::vector<int> dictionariesEnabled;
  440. qint32 autoDownloadDictionaries = _autoDownloadDictionaries.current() ? 1 : 0;
  441. qint32 mainMenuAccountsShown = _mainMenuAccountsShown.current() ? 1 : 0;
  442. qint32 tabbedSelectorSectionEnabled = 1;
  443. qint32 floatPlayerColumn = static_cast<qint32>(Window::Column::Second);
  444. qint32 floatPlayerCorner = static_cast<qint32>(RectPart::TopRight);
  445. qint32 thirdSectionInfoEnabled = 0;
  446. float64 dialogsWithChatWidthRatio = _dialogsWithChatWidthRatio.current();
  447. float64 dialogsNoChatWidthRatio = _dialogsNoChatWidthRatio.current();
  448. qint32 thirdColumnWidth = _thirdColumnWidth.current();
  449. qint32 thirdSectionExtendedBy = _thirdSectionExtendedBy;
  450. qint32 notifyFromAll = _notifyFromAll ? 1 : 0;
  451. qint32 nativeWindowFrame = _nativeWindowFrame.current() ? 1 : 0;
  452. qint32 systemDarkModeEnabled = _systemDarkModeEnabled.current() ? 1 : 0;
  453. qint32 ipRevealWarning = _ipRevealWarning ? 1 : 0;
  454. qint32 groupCallPushToTalk = _groupCallPushToTalk ? 1 : 0;
  455. QByteArray groupCallPushToTalkShortcut = _groupCallPushToTalkShortcut;
  456. qint64 groupCallPushToTalkDelay = _groupCallPushToTalkDelay;
  457. qint32 legacyCallAudioBackend = 0;
  458. qint32 disableCallsLegacy = 0;
  459. QByteArray windowPosition;
  460. std::vector<RecentEmojiPreload> recentEmojiPreload;
  461. base::flat_map<QString, uint8> emojiVariants;
  462. qint32 disableOpenGL = _disableOpenGL ? 1 : 0;
  463. qint32 groupCallNoiseSuppression = _groupCallNoiseSuppression ? 1 : 0;
  464. qint32 workMode = static_cast<qint32>(_workMode.current());
  465. QByteArray proxy;
  466. qint32 hiddenGroupCallTooltips = qint32(_hiddenGroupCallTooltips.value());
  467. QByteArray photoEditorBrush = _photoEditorBrush;
  468. qint32 closeBehavior = qint32(_closeBehavior);
  469. QString customDeviceModel = _customDeviceModel.current();
  470. qint32 playerRepeatMode = static_cast<qint32>(_playerRepeatMode.current());
  471. qint32 playerOrderMode = static_cast<qint32>(_playerOrderMode.current());
  472. qint32 macWarnBeforeQuit = _macWarnBeforeQuit ? 1 : 0;
  473. qint32 accountsOrderCount = 0;
  474. std::vector<uint64> accountsOrder;
  475. qint32 hardwareAcceleratedVideo = _hardwareAcceleratedVideo ? 1 : 0;
  476. qint32 chatQuickAction = static_cast<qint32>(_chatQuickAction);
  477. qint32 suggestAnimatedEmoji = _suggestAnimatedEmoji ? 1 : 0;
  478. qint32 cornerReaction = _cornerReaction.current() ? 1 : 0;
  479. qint32 legacySkipTranslationForLanguage = _translateButtonEnabled ? 1 : 0;
  480. qint32 skipTranslationLanguagesCount = 0;
  481. std::vector<LanguageId> skipTranslationLanguages;
  482. qint32 rememberedDeleteMessageOnlyForYou = _rememberedDeleteMessageOnlyForYou ? 1 : 0;
  483. qint32 translateChatEnabled = _translateChatEnabled.current() ? 1 : 0;
  484. quint64 translateToRaw = _translateToRaw.current();
  485. qint32 hideChatName = _windowTitleContent.current().hideChatName ? 1 : 0;
  486. qint32 hideAccountName = _windowTitleContent.current().hideAccountName ? 1 : 0;
  487. qint32 hideTotalUnread = _windowTitleContent.current().hideTotalUnread ? 1 : 0;
  488. QByteArray mediaViewPosition;
  489. qint32 ignoreBatterySaving = _ignoreBatterySaving.current() ? 1 : 0;
  490. quint64 macRoundIconDigest = _macRoundIconDigest.value_or(0);
  491. qint32 storiesClickTooltipHidden = _storiesClickTooltipHidden.current() ? 1 : 0;
  492. base::flat_set<QString> recentEmojiSkip;
  493. qint32 trayIconMonochrome = (_trayIconMonochrome.current() ? 1 : 0);
  494. qint32 ttlVoiceClickTooltipHidden = _ttlVoiceClickTooltipHidden.current() ? 1 : 0;
  495. QByteArray ivPosition;
  496. QString customFontFamily = _customFontFamily;
  497. qint32 systemUnlockEnabled = _systemUnlockEnabled ? 1 : 0;
  498. qint32 weatherInCelsius = !_weatherInCelsius ? 0 : *_weatherInCelsius ? 1 : 2;
  499. QByteArray tonsiteStorageToken = _tonsiteStorageToken;
  500. qint32 ivZoom = _ivZoom.current();
  501. qint32 skipToastsInFocus = _skipToastsInFocus ? 1 : 0;
  502. qint32 recordVideoMessages = _recordVideoMessages ? 1 : 0;
  503. quint32 videoQuality = SerializeVideoQuality(_videoQuality);
  504. quint32 chatFiltersHorizontal = _chatFiltersHorizontal.current() ? 1 : 0;
  505. quint32 quickDialogAction = quint32(_quickDialogAction);
  506. stream >> themesAccentColors;
  507. if (!stream.atEnd()) {
  508. stream
  509. >> adaptiveForWide
  510. >> moderateModeEnabled
  511. >> songVolume
  512. >> videoVolume
  513. >> askDownloadPath
  514. >> downloadPath
  515. >> downloadPathBookmark
  516. >> nonDefaultVoicePlaybackSpeed
  517. >> soundNotify
  518. >> desktopNotify
  519. >> flashBounceNotify
  520. >> notifyView
  521. >> nativeNotifications
  522. >> notificationsCount
  523. >> notificationsCorner
  524. >> autoLock
  525. >> legacyCallPlaybackDeviceId
  526. >> legacyCallCaptureDeviceId
  527. >> callOutputVolume
  528. >> callInputVolume
  529. >> callAudioDuckingEnabled
  530. >> lastSeenWarningSeen
  531. >> soundOverridesCount;
  532. if (stream.status() == QDataStream::Ok) {
  533. for (auto i = 0; i != soundOverridesCount; ++i) {
  534. QString key, value;
  535. stream >> key >> value;
  536. soundOverrides.emplace(key, value);
  537. }
  538. }
  539. stream
  540. >> sendFilesWay
  541. >> sendSubmitWay
  542. >> includeMutedCounter
  543. >> countUnreadMessages
  544. >> legacyExeLaunchWarning
  545. >> notifyAboutPinned
  546. >> loopAnimatedStickers
  547. >> largeEmoji
  548. >> replaceEmoji
  549. >> suggestEmoji
  550. >> suggestStickersByEmoji
  551. >> spellcheckerEnabled
  552. >> videoPlaybackSpeed
  553. >> videoPipGeometry
  554. >> dictionariesEnabledCount;
  555. if (stream.status() == QDataStream::Ok) {
  556. for (auto i = 0; i != dictionariesEnabledCount; ++i) {
  557. qint64 langId;
  558. stream >> langId;
  559. dictionariesEnabled.emplace_back(langId);
  560. }
  561. }
  562. stream
  563. >> autoDownloadDictionaries
  564. >> mainMenuAccountsShown;
  565. }
  566. if (!stream.atEnd()) {
  567. auto dialogsWithChatWidthRatioInt = qint32();
  568. stream
  569. >> tabbedSelectorSectionEnabled
  570. >> floatPlayerColumn
  571. >> floatPlayerCorner
  572. >> thirdSectionInfoEnabled
  573. >> dialogsWithChatWidthRatioInt
  574. >> thirdColumnWidth
  575. >> thirdSectionExtendedBy
  576. >> notifyFromAll;
  577. dialogsWithChatWidthRatio = std::clamp(
  578. dialogsWithChatWidthRatioInt / 1000000.,
  579. 0.,
  580. 1.);
  581. }
  582. if (!stream.atEnd()) {
  583. stream >> nativeWindowFrame;
  584. }
  585. if (!stream.atEnd()) {
  586. // Read over this one below, if was in the file.
  587. stream >> systemDarkModeEnabled;
  588. }
  589. if (!stream.atEnd()) {
  590. stream >> cameraDeviceId;
  591. }
  592. if (!stream.atEnd()) {
  593. stream >> ipRevealWarning;
  594. }
  595. if (!stream.atEnd()) {
  596. stream
  597. >> groupCallPushToTalk
  598. >> groupCallPushToTalkShortcut
  599. >> groupCallPushToTalkDelay;
  600. }
  601. if (!stream.atEnd()) {
  602. stream >> legacyCallAudioBackend;
  603. }
  604. if (!stream.atEnd()) {
  605. stream >> disableCallsLegacy;
  606. }
  607. if (!stream.atEnd()) {
  608. stream >> windowPosition;
  609. }
  610. if (!stream.atEnd()) {
  611. auto recentCount = qint32(0);
  612. stream >> recentCount;
  613. if (recentCount > 0 && recentCount < 10000) {
  614. recentEmojiPreload.reserve(recentCount);
  615. for (auto i = 0; i != recentCount; ++i) {
  616. auto id = QString();
  617. auto rating = quint16();
  618. stream >> id >> rating;
  619. recentEmojiPreload.push_back({ id, rating });
  620. }
  621. }
  622. auto variantsCount = qint32(0);
  623. stream >> variantsCount;
  624. if (variantsCount > 0 && variantsCount < 10000) {
  625. emojiVariants.reserve(variantsCount);
  626. for (auto i = 0; i != variantsCount; ++i) {
  627. auto id = QString();
  628. auto variant = quint8();
  629. stream >> id >> variant;
  630. emojiVariants.emplace(id, variant);
  631. }
  632. }
  633. }
  634. if (!stream.atEnd()) {
  635. qint32 disableOpenGLOld;
  636. stream >> disableOpenGLOld;
  637. }
  638. if (!stream.atEnd()) {
  639. qint32 groupCallNoiseSuppressionOld;
  640. stream >> groupCallNoiseSuppressionOld;
  641. }
  642. if (!stream.atEnd()) {
  643. stream >> workMode;
  644. }
  645. if (!stream.atEnd()) {
  646. stream >> proxy;
  647. }
  648. if (!stream.atEnd()) {
  649. stream >> hiddenGroupCallTooltips;
  650. }
  651. if (!stream.atEnd()) {
  652. stream >> disableOpenGL;
  653. }
  654. if (!stream.atEnd()) {
  655. stream >> photoEditorBrush;
  656. }
  657. if (!stream.atEnd()) {
  658. stream >> groupCallNoiseSuppression;
  659. }
  660. if (!stream.atEnd()) {
  661. stream >> voicePlaybackSpeed;
  662. }
  663. if (!stream.atEnd()) {
  664. stream >> closeBehavior;
  665. }
  666. if (!stream.atEnd()) {
  667. stream >> customDeviceModel;
  668. }
  669. if (!stream.atEnd()) {
  670. stream
  671. >> playerRepeatMode
  672. >> playerOrderMode;
  673. }
  674. if (!stream.atEnd()) {
  675. stream >> macWarnBeforeQuit;
  676. }
  677. if (!stream.atEnd()) {
  678. stream >> accountsOrderCount;
  679. if (stream.status() == QDataStream::Ok) {
  680. for (auto i = 0; i != accountsOrderCount; ++i) {
  681. quint64 sessionUniqueId;
  682. stream >> sessionUniqueId;
  683. accountsOrder.emplace_back(sessionUniqueId);
  684. }
  685. }
  686. }
  687. if (!stream.atEnd()) {
  688. qint32 legacyHardwareAcceleratedVideo = 0;
  689. stream >> legacyHardwareAcceleratedVideo;
  690. }
  691. if (!stream.atEnd()) {
  692. stream >> chatQuickAction;
  693. }
  694. if (!stream.atEnd()) {
  695. stream >> hardwareAcceleratedVideo;
  696. }
  697. if (!stream.atEnd()) {
  698. stream >> suggestAnimatedEmoji;
  699. }
  700. if (!stream.atEnd()) {
  701. stream >> cornerReaction;
  702. }
  703. if (!stream.atEnd()) {
  704. stream >> legacySkipTranslationForLanguage;
  705. }
  706. if (!stream.atEnd()) {
  707. stream >> skipTranslationLanguagesCount;
  708. if (stream.status() == QDataStream::Ok) {
  709. for (auto i = 0; i != skipTranslationLanguagesCount; ++i) {
  710. quint64 language;
  711. stream >> language;
  712. skipTranslationLanguages.push_back({
  713. QLocale::Language(language)
  714. });
  715. }
  716. }
  717. }
  718. if (!stream.atEnd()) {
  719. stream >> rememberedDeleteMessageOnlyForYou;
  720. }
  721. if (!stream.atEnd()) {
  722. stream
  723. >> translateChatEnabled
  724. >> translateToRaw;
  725. }
  726. if (!stream.atEnd()) {
  727. stream
  728. >> hideChatName
  729. >> hideAccountName
  730. >> hideTotalUnread;
  731. }
  732. if (!stream.atEnd()) {
  733. stream >> mediaViewPosition;
  734. }
  735. if (!stream.atEnd()) {
  736. stream >> ignoreBatterySaving;
  737. }
  738. if (!stream.atEnd()) {
  739. stream >> macRoundIconDigest;
  740. }
  741. if (!stream.atEnd()) {
  742. stream >> storiesClickTooltipHidden;
  743. }
  744. if (!stream.atEnd()) {
  745. auto count = qint32();
  746. stream >> count;
  747. if (stream.status() == QDataStream::Ok) {
  748. for (auto i = 0; i != count; ++i) {
  749. auto id = QString();
  750. stream >> id;
  751. if (stream.status() == QDataStream::Ok) {
  752. recentEmojiSkip.emplace(id);
  753. }
  754. }
  755. }
  756. }
  757. if (!stream.atEnd()) {
  758. stream >> trayIconMonochrome;
  759. } else {
  760. // Let existing clients use the old value.
  761. trayIconMonochrome = 0;
  762. }
  763. if (!stream.atEnd()) {
  764. stream >> ttlVoiceClickTooltipHidden;
  765. }
  766. if (!stream.atEnd()) {
  767. stream
  768. >> playbackDeviceId
  769. >> captureDeviceId;
  770. }
  771. if (!stream.atEnd()) {
  772. stream
  773. >> callPlaybackDeviceId
  774. >> callCaptureDeviceId;
  775. } else {
  776. const auto &defaultId = Webrtc::kDefaultDeviceId;
  777. callPlaybackDeviceId = (legacyCallPlaybackDeviceId == defaultId)
  778. ? QString()
  779. : legacyCallPlaybackDeviceId;
  780. callCaptureDeviceId = (legacyCallCaptureDeviceId == defaultId)
  781. ? QString()
  782. : legacyCallCaptureDeviceId;
  783. }
  784. if (!stream.atEnd()) {
  785. stream >> ivPosition;
  786. }
  787. if (!stream.atEnd()) {
  788. noWarningExtensions = QString();
  789. stream >> *noWarningExtensions;
  790. }
  791. if (!stream.atEnd()) {
  792. stream >> customFontFamily;
  793. }
  794. if (!stream.atEnd()) {
  795. auto dialogsNoChatWidthRatioInt = qint32();
  796. stream
  797. >> dialogsNoChatWidthRatioInt;
  798. dialogsNoChatWidthRatio = std::clamp(
  799. dialogsNoChatWidthRatioInt / 1000000.,
  800. 0.,
  801. 1.);
  802. }
  803. if (!stream.atEnd()) {
  804. stream >> systemUnlockEnabled;
  805. }
  806. if (!stream.atEnd()) {
  807. stream >> weatherInCelsius;
  808. }
  809. if (!stream.atEnd()) {
  810. stream >> tonsiteStorageToken;
  811. }
  812. if (!stream.atEnd()) {
  813. stream >> includeMutedCounterFolders;
  814. }
  815. if (!stream.atEnd()) {
  816. stream >> chatFiltersHorizontal;
  817. }
  818. if (!stream.atEnd()) {
  819. stream >> skipToastsInFocus;
  820. }
  821. if (!stream.atEnd()) {
  822. stream >> recordVideoMessages;
  823. }
  824. if (!stream.atEnd()) {
  825. stream >> videoQuality;
  826. }
  827. if (!stream.atEnd()) {
  828. stream >> ivZoom;
  829. }
  830. if (!stream.atEnd()) {
  831. stream >> systemDarkModeEnabled;
  832. }
  833. if (!stream.atEnd()) {
  834. stream >> quickDialogAction;
  835. }
  836. if (stream.status() != QDataStream::Ok) {
  837. LOG(("App Error: "
  838. "Bad data for Core::Settings::constructFromSerialized()"));
  839. return;
  840. } else if (!_themesAccentColors.setFromSerialized(themesAccentColors)) {
  841. return;
  842. } else if (!_proxy.setFromSerialized(proxy)) {
  843. return;
  844. }
  845. _adaptiveForWide = (adaptiveForWide == 1);
  846. _moderateModeEnabled = (moderateModeEnabled == 1);
  847. _songVolume = std::clamp(songVolume / 1e6, 0., 1.);
  848. _videoVolume = std::clamp(videoVolume / 1e6, 0., 1.);
  849. _askDownloadPath = (askDownloadPath == 1);
  850. _downloadPath = downloadPath;
  851. _downloadPathBookmark = downloadPathBookmark;
  852. _soundNotify = (soundNotify == 1);
  853. _desktopNotify = (desktopNotify == 1);
  854. _flashBounceNotify = (flashBounceNotify == 1);
  855. const auto uncheckedNotifyView = static_cast<NotifyView>(notifyView);
  856. switch (uncheckedNotifyView) {
  857. case NotifyView::ShowNothing:
  858. case NotifyView::ShowName:
  859. case NotifyView::ShowPreview: _notifyView = uncheckedNotifyView; break;
  860. }
  861. switch (nativeNotifications) {
  862. case 0: _nativeNotifications = std::nullopt; break;
  863. case 1: _nativeNotifications = true; break;
  864. case 2: _nativeNotifications = false; break;
  865. default: break;
  866. }
  867. _notificationsCount = (notificationsCount > 0) ? notificationsCount : 3;
  868. const auto uncheckedNotificationsCorner = static_cast<ScreenCorner>(notificationsCorner);
  869. switch (uncheckedNotificationsCorner) {
  870. case ScreenCorner::TopLeft:
  871. case ScreenCorner::TopRight:
  872. case ScreenCorner::BottomRight:
  873. case ScreenCorner::BottomLeft: _notificationsCorner = uncheckedNotificationsCorner; break;
  874. }
  875. _includeMutedCounter = (includeMutedCounter == 1);
  876. _includeMutedCounterFolders = (includeMutedCounterFolders == 1);
  877. _countUnreadMessages = (countUnreadMessages == 1);
  878. _notifyAboutPinned = (notifyAboutPinned == 1);
  879. _autoLock = autoLock;
  880. _playbackDeviceId = playbackDeviceId;
  881. _captureDeviceId = captureDeviceId;
  882. const auto kOldDefault = u"default"_q;
  883. _cameraDeviceId = cameraDeviceId;
  884. _callPlaybackDeviceId = callPlaybackDeviceId;
  885. _callCaptureDeviceId = callCaptureDeviceId;
  886. _callOutputVolume = callOutputVolume;
  887. _callInputVolume = callInputVolume;
  888. _callAudioDuckingEnabled = (callAudioDuckingEnabled == 1);
  889. _lastSeenWarningSeen = (lastSeenWarningSeen == 1);
  890. _soundOverrides = std::move(soundOverrides);
  891. _sendFilesWay = Ui::SendFilesWay::FromSerialized(sendFilesWay).value_or(_sendFilesWay);
  892. auto uncheckedSendSubmitWay = static_cast<Ui::InputSubmitSettings>(sendSubmitWay);
  893. switch (uncheckedSendSubmitWay) {
  894. case Ui::InputSubmitSettings::Enter:
  895. case Ui::InputSubmitSettings::CtrlEnter: _sendSubmitWay = uncheckedSendSubmitWay; break;
  896. }
  897. if (noWarningExtensions) {
  898. const auto list = noWarningExtensions->mid(0, 10240)
  899. .split(' ', Qt::SkipEmptyParts)
  900. .mid(0, 1024);
  901. _noWarningExtensions = base::flat_set<QString>(list.begin(), list.end());
  902. }
  903. _ipRevealWarning = (ipRevealWarning == 1);
  904. _notifyAboutPinned = (notifyAboutPinned == 1);
  905. _loopAnimatedStickers = (loopAnimatedStickers == 1);
  906. _largeEmoji = (largeEmoji == 1);
  907. _replaceEmoji = (replaceEmoji == 1);
  908. _suggestEmoji = (suggestEmoji == 1);
  909. _suggestStickersByEmoji = (suggestStickersByEmoji == 1);
  910. _spellcheckerEnabled = (spellcheckerEnabled == 1);
  911. _videoPlaybackSpeed = DeserializePlaybackSpeed(videoPlaybackSpeed);
  912. _voicePlaybackSpeed = DeserializePlaybackSpeed(voicePlaybackSpeed);
  913. if (nonDefaultVoicePlaybackSpeed != 1) {
  914. _voicePlaybackSpeed.enabled = false;
  915. }
  916. _videoPipGeometry = (videoPipGeometry);
  917. _dictionariesEnabled = std::move(dictionariesEnabled);
  918. _autoDownloadDictionaries = (autoDownloadDictionaries == 1);
  919. _mainMenuAccountsShown = (mainMenuAccountsShown == 1);
  920. _tabbedSelectorSectionEnabled = (tabbedSelectorSectionEnabled == 1);
  921. auto uncheckedColumn = static_cast<Window::Column>(floatPlayerColumn);
  922. switch (uncheckedColumn) {
  923. case Window::Column::First:
  924. case Window::Column::Second:
  925. case Window::Column::Third: _floatPlayerColumn = uncheckedColumn; break;
  926. }
  927. auto uncheckedCorner = static_cast<RectPart>(floatPlayerCorner);
  928. switch (uncheckedCorner) {
  929. case RectPart::TopLeft:
  930. case RectPart::TopRight:
  931. case RectPart::BottomLeft:
  932. case RectPart::BottomRight: _floatPlayerCorner = uncheckedCorner; break;
  933. }
  934. _thirdSectionInfoEnabled = thirdSectionInfoEnabled;
  935. _dialogsWithChatWidthRatio = dialogsWithChatWidthRatio;
  936. _dialogsNoChatWidthRatio = (dialogsWithChatWidthRatio > 0)
  937. ? dialogsWithChatWidthRatio
  938. : dialogsNoChatWidthRatio;
  939. _thirdColumnWidth = thirdColumnWidth;
  940. _thirdSectionExtendedBy = thirdSectionExtendedBy;
  941. if (_thirdSectionInfoEnabled) {
  942. _tabbedSelectorSectionEnabled = false;
  943. }
  944. _notifyFromAll = (notifyFromAll == 1);
  945. _nativeWindowFrame = (nativeWindowFrame == 1);
  946. _systemDarkModeEnabled = (systemDarkModeEnabled == 1);
  947. _groupCallPushToTalk = (groupCallPushToTalk == 1);
  948. _groupCallPushToTalkShortcut = groupCallPushToTalkShortcut;
  949. _groupCallPushToTalkDelay = groupCallPushToTalkDelay;
  950. _disableCallsLegacy = (disableCallsLegacy == 1);
  951. if (!windowPosition.isEmpty()) {
  952. _windowPosition = Deserialize(windowPosition);
  953. }
  954. _recentEmojiPreload = std::move(recentEmojiPreload);
  955. _emojiVariants = std::move(emojiVariants);
  956. _disableOpenGL = (disableOpenGL == 1);
  957. Ui::GL::ForceDisable(_disableOpenGL);
  958. _groupCallNoiseSuppression = (groupCallNoiseSuppression == 1);
  959. const auto uncheckedWorkMode = static_cast<WorkMode>(workMode);
  960. switch (uncheckedWorkMode) {
  961. case WorkMode::WindowAndTray:
  962. case WorkMode::TrayOnly:
  963. case WorkMode::WindowOnly: _workMode = uncheckedWorkMode; break;
  964. }
  965. _hiddenGroupCallTooltips = [&] {
  966. using Tooltip = Calls::Group::StickedTooltip;
  967. return Tooltip(0)
  968. | ((hiddenGroupCallTooltips & int(Tooltip::Camera))
  969. ? Tooltip::Camera
  970. : Tooltip(0))
  971. | ((hiddenGroupCallTooltips & int(Tooltip::Microphone))
  972. ? Tooltip::Microphone
  973. : Tooltip(0));
  974. }();
  975. _photoEditorBrush = photoEditorBrush;
  976. const auto uncheckedCloseBehavior = static_cast<CloseBehavior>(closeBehavior);
  977. switch (uncheckedCloseBehavior) {
  978. case CloseBehavior::CloseToTaskbar:
  979. case CloseBehavior::RunInBackground:
  980. case CloseBehavior::Quit: _closeBehavior = uncheckedCloseBehavior; break;
  981. }
  982. _customDeviceModel = customDeviceModel;
  983. _accountsOrder = accountsOrder;
  984. const auto uncheckedPlayerRepeatMode = static_cast<Media::RepeatMode>(playerRepeatMode);
  985. switch (uncheckedPlayerRepeatMode) {
  986. case Media::RepeatMode::None:
  987. case Media::RepeatMode::One:
  988. case Media::RepeatMode::All: _playerRepeatMode = uncheckedPlayerRepeatMode; break;
  989. }
  990. const auto uncheckedPlayerOrderMode = static_cast<Media::OrderMode>(playerOrderMode);
  991. switch (uncheckedPlayerOrderMode) {
  992. case Media::OrderMode::Default:
  993. case Media::OrderMode::Reverse:
  994. case Media::OrderMode::Shuffle: _playerOrderMode = uncheckedPlayerOrderMode; break;
  995. }
  996. _macWarnBeforeQuit = (macWarnBeforeQuit == 1);
  997. _hardwareAcceleratedVideo = (hardwareAcceleratedVideo == 1);
  998. {
  999. using Quick = HistoryView::DoubleClickQuickAction;
  1000. const auto uncheckedChatQuickAction = static_cast<Quick>(
  1001. chatQuickAction);
  1002. switch (uncheckedChatQuickAction) {
  1003. case Quick::None:
  1004. case Quick::Reply:
  1005. case Quick::React: _chatQuickAction = uncheckedChatQuickAction; break;
  1006. }
  1007. }
  1008. _suggestAnimatedEmoji = (suggestAnimatedEmoji == 1);
  1009. _cornerReaction = (cornerReaction == 1);
  1010. { // Parse the legacy translation setting.
  1011. if (legacySkipTranslationForLanguage == 0) {
  1012. _translateButtonEnabled = false;
  1013. } else if (legacySkipTranslationForLanguage == 1) {
  1014. _translateButtonEnabled = true;
  1015. } else {
  1016. _translateButtonEnabled = (legacySkipTranslationForLanguage > 0);
  1017. skipTranslationLanguages.push_back({
  1018. QLocale::Language(std::abs(legacySkipTranslationForLanguage))
  1019. });
  1020. }
  1021. _skipTranslationLanguages = std::move(skipTranslationLanguages);
  1022. }
  1023. _rememberedDeleteMessageOnlyForYou = (rememberedDeleteMessageOnlyForYou == 1);
  1024. _translateChatEnabled = (translateChatEnabled == 1);
  1025. _translateToRaw = int(QLocale::Language(translateToRaw));
  1026. _windowTitleContent = WindowTitleContent{
  1027. .hideChatName = (hideChatName == 1),
  1028. .hideAccountName = (hideAccountName == 1),
  1029. .hideTotalUnread = (hideTotalUnread == 1),
  1030. };
  1031. if (!mediaViewPosition.isEmpty()) {
  1032. _mediaViewPosition = Deserialize(mediaViewPosition);
  1033. if (!_mediaViewPosition.w && !_mediaViewPosition.maximized) {
  1034. _mediaViewPosition = { .maximized = 2 };
  1035. }
  1036. }
  1037. _ignoreBatterySaving = (ignoreBatterySaving == 1);
  1038. _macRoundIconDigest = macRoundIconDigest ? macRoundIconDigest : std::optional<uint64>();
  1039. _storiesClickTooltipHidden = (storiesClickTooltipHidden == 1);
  1040. _recentEmojiSkip = std::move(recentEmojiSkip);
  1041. _trayIconMonochrome = (trayIconMonochrome == 1);
  1042. _ttlVoiceClickTooltipHidden = (ttlVoiceClickTooltipHidden == 1);
  1043. if (!ivPosition.isEmpty()) {
  1044. _ivPosition = Deserialize(ivPosition);
  1045. }
  1046. _customFontFamily = customFontFamily;
  1047. _systemUnlockEnabled = (systemUnlockEnabled == 1);
  1048. _weatherInCelsius = !weatherInCelsius
  1049. ? std::optional<bool>()
  1050. : (weatherInCelsius == 1);
  1051. _tonsiteStorageToken = tonsiteStorageToken;
  1052. _ivZoom = ivZoom;
  1053. _skipToastsInFocus = (skipToastsInFocus == 1);
  1054. _recordVideoMessages = (recordVideoMessages == 1);
  1055. _videoQuality = DeserializeVideoQuality(videoQuality);
  1056. _chatFiltersHorizontal = (chatFiltersHorizontal == 1);
  1057. _quickDialogAction = Dialogs::Ui::QuickDialogAction(quickDialogAction);
  1058. }
  1059. QString Settings::getSoundPath(const QString &key) const {
  1060. auto it = _soundOverrides.find(key);
  1061. if (it != _soundOverrides.end()) {
  1062. return it->second;
  1063. }
  1064. return u":/sounds/"_q + key + u".mp3"_q;
  1065. }
  1066. void Settings::setTabbedSelectorSectionEnabled(bool enabled) {
  1067. _tabbedSelectorSectionEnabled = enabled;
  1068. if (enabled) {
  1069. setThirdSectionInfoEnabled(false);
  1070. }
  1071. setTabbedReplacedWithInfo(false);
  1072. }
  1073. rpl::producer<bool> Settings::tabbedReplacedWithInfoValue() const {
  1074. return _tabbedReplacedWithInfoValue.events_starting_with(
  1075. tabbedReplacedWithInfo());
  1076. }
  1077. void Settings::setThirdSectionInfoEnabled(bool enabled) {
  1078. if (_thirdSectionInfoEnabled != enabled) {
  1079. _thirdSectionInfoEnabled = enabled;
  1080. if (enabled) {
  1081. setTabbedSelectorSectionEnabled(false);
  1082. }
  1083. setTabbedReplacedWithInfo(false);
  1084. _thirdSectionInfoEnabledValue.fire_copy(enabled);
  1085. }
  1086. }
  1087. rpl::producer<bool> Settings::thirdSectionInfoEnabledValue() const {
  1088. return _thirdSectionInfoEnabledValue.events_starting_with(
  1089. thirdSectionInfoEnabled());
  1090. }
  1091. void Settings::setTabbedReplacedWithInfo(bool enabled) {
  1092. if (_tabbedReplacedWithInfo != enabled) {
  1093. _tabbedReplacedWithInfo = enabled;
  1094. _tabbedReplacedWithInfoValue.fire_copy(enabled);
  1095. }
  1096. }
  1097. void Settings::updateDialogsWidthRatio(float64 ratio, bool nochat) {
  1098. const auto changeWithChat = !nochat
  1099. || (dialogsWithChatWidthRatio() > 0)
  1100. || _dialogsWidthSetToZeroWithoutChat;
  1101. const auto changedWithChat = changeWithChat
  1102. && (dialogsWithChatWidthRatio() != ratio);
  1103. const auto changeNoChat = nochat
  1104. || (dialogsWithChatWidthRatio() != ratio);
  1105. const auto changedNoChat = changeNoChat
  1106. && (dialogsNoChatWidthRatio() != ratio);
  1107. if (changedWithChat) {
  1108. _dialogsWidthSetToZeroWithoutChat = nochat && !(ratio > 0);
  1109. _dialogsWithChatWidthRatio = ratio;
  1110. }
  1111. if (changedNoChat) {
  1112. _dialogsNoChatWidthRatio = ratio;
  1113. }
  1114. }
  1115. float64 Settings::dialogsWidthRatio(bool nochat) const {
  1116. const auto withchat = dialogsWithChatWidthRatio();
  1117. return (!nochat || withchat > 0) ? withchat : dialogsNoChatWidthRatio();
  1118. }
  1119. float64 Settings::dialogsWithChatWidthRatio() const {
  1120. return _dialogsWithChatWidthRatio.current();
  1121. }
  1122. rpl::producer<float64> Settings::dialogsWithChatWidthRatioChanges() const {
  1123. return _dialogsWithChatWidthRatio.changes();
  1124. }
  1125. float64 Settings::dialogsNoChatWidthRatio() const {
  1126. return _dialogsNoChatWidthRatio.current();
  1127. }
  1128. rpl::producer<float64> Settings::dialogsNoChatWidthRatioChanges() const {
  1129. return _dialogsNoChatWidthRatio.changes();
  1130. }
  1131. void Settings::setThirdColumnWidth(int width) {
  1132. _thirdColumnWidth = width;
  1133. }
  1134. QString Settings::deviceModel() const {
  1135. const auto custom = customDeviceModel();
  1136. return custom.isEmpty() ? Platform::DeviceModelPretty() : custom;
  1137. }
  1138. rpl::producer<QString> Settings::deviceModelChanges() const {
  1139. return customDeviceModelChanges() | rpl::map([=] {
  1140. return deviceModel();
  1141. });
  1142. }
  1143. rpl::producer<QString> Settings::deviceModelValue() const {
  1144. return customDeviceModelValue() | rpl::map([=] {
  1145. return deviceModel();
  1146. });
  1147. }
  1148. int Settings::thirdColumnWidth() const {
  1149. return _thirdColumnWidth.current();
  1150. }
  1151. rpl::producer<int> Settings::thirdColumnWidthChanges() const {
  1152. return _thirdColumnWidth.changes();
  1153. }
  1154. const std::vector<RecentEmoji> &Settings::recentEmoji() const {
  1155. if (!_recentEmojiResolved) {
  1156. _recentEmojiResolved = true;
  1157. resolveRecentEmoji();
  1158. }
  1159. return _recentEmoji;
  1160. }
  1161. void Settings::resolveRecentEmoji() const {
  1162. const auto haveAlready = [&](RecentEmojiId id) {
  1163. return ranges::contains(
  1164. _recentEmoji,
  1165. id,
  1166. [](const RecentEmoji &data) { return data.id; });
  1167. };
  1168. auto testCount = 0;
  1169. auto nonTestCount = 0;
  1170. if (!_recentEmojiPreload.empty()) {
  1171. _recentEmoji.reserve(_recentEmojiPreload.size());
  1172. for (const auto &[id, rating] : base::take(_recentEmojiPreload)) {
  1173. auto length = int();
  1174. const auto emoji = Ui::Emoji::Find(id, &length);
  1175. if (emoji && length == id.size()) {
  1176. if (!haveAlready({ emoji })) {
  1177. _recentEmoji.push_back({ { emoji }, rating });
  1178. }
  1179. } else if (const auto document = ParseRecentEmojiDocument(id)) {
  1180. if (!haveAlready({ *document })) {
  1181. _recentEmoji.push_back({ { *document }, rating });
  1182. if (document->test) {
  1183. ++testCount;
  1184. } else {
  1185. ++nonTestCount;
  1186. }
  1187. }
  1188. }
  1189. }
  1190. _recentEmojiPreload.clear();
  1191. }
  1192. const auto specialCount = std::max(testCount, nonTestCount);
  1193. for (const auto emoji : Ui::Emoji::GetDefaultRecent()) {
  1194. if (_recentEmoji.size() >= specialCount + kRecentEmojiLimit) {
  1195. break;
  1196. } else if (_recentEmojiSkip.contains(emoji->id())) {
  1197. continue;
  1198. } else if (!haveAlready({ emoji })) {
  1199. _recentEmoji.push_back({ { emoji }, 1 });
  1200. }
  1201. }
  1202. }
  1203. void Settings::incrementRecentEmoji(RecentEmojiId id) {
  1204. resolveRecentEmoji();
  1205. if (const auto emoji = std::get_if<EmojiPtr>(&id.data)) {
  1206. _recentEmojiSkip.remove((*emoji)->id());
  1207. }
  1208. auto i = _recentEmoji.begin(), e = _recentEmoji.end();
  1209. for (; i != e; ++i) {
  1210. if (i->id == id) {
  1211. ++i->rating;
  1212. if (i->rating > 0x8000) {
  1213. for (auto j = _recentEmoji.begin(); j != e; ++j) {
  1214. if (j->rating > 1) {
  1215. j->rating /= 2;
  1216. } else {
  1217. j->rating = 1;
  1218. }
  1219. }
  1220. }
  1221. for (; i != _recentEmoji.begin(); --i) {
  1222. if ((i - 1)->rating > i->rating) {
  1223. break;
  1224. }
  1225. std::swap(*i, *(i - 1));
  1226. }
  1227. break;
  1228. }
  1229. }
  1230. if (i == e) {
  1231. _recentEmoji.push_back({ id, 1 });
  1232. for (i = _recentEmoji.end() - 1; i != _recentEmoji.begin(); --i) {
  1233. if ((i - 1)->rating > i->rating) {
  1234. break;
  1235. }
  1236. std::swap(*i, *(i - 1));
  1237. }
  1238. auto testCount = 0;
  1239. auto nonTestCount = 0;
  1240. for (const auto &emoji : _recentEmoji) {
  1241. const auto id = &emoji.id.data;
  1242. if (const auto document = std::get_if<RecentEmojiDocument>(id)) {
  1243. if (document->test) {
  1244. ++testCount;
  1245. } else {
  1246. ++nonTestCount;
  1247. }
  1248. }
  1249. }
  1250. const auto specialCount = std::max(testCount, nonTestCount);
  1251. while (_recentEmoji.size() >= specialCount + kRecentEmojiLimit) {
  1252. _recentEmoji.pop_back();
  1253. }
  1254. }
  1255. _recentEmojiUpdated.fire({});
  1256. _saveDelayed.fire({});
  1257. }
  1258. void Settings::hideRecentEmoji(RecentEmojiId id) {
  1259. resolveRecentEmoji();
  1260. _recentEmoji.erase(
  1261. ranges::remove(_recentEmoji, id, &RecentEmoji::id),
  1262. end(_recentEmoji));
  1263. if (const auto emoji = std::get_if<EmojiPtr>(&id.data)) {
  1264. for (const auto always : Ui::Emoji::GetDefaultRecent()) {
  1265. if (always == *emoji) {
  1266. _recentEmojiSkip.emplace(always->id());
  1267. break;
  1268. }
  1269. }
  1270. }
  1271. _recentEmojiUpdated.fire({});
  1272. _saveDelayed.fire({});
  1273. }
  1274. void Settings::resetRecentEmoji() {
  1275. resolveRecentEmoji();
  1276. _recentEmoji.clear();
  1277. _recentEmojiSkip.clear();
  1278. _recentEmojiPreload.clear();
  1279. _recentEmojiResolved = false;
  1280. _recentEmojiUpdated.fire({});
  1281. _saveDelayed.fire({});
  1282. }
  1283. void Settings::setLegacyRecentEmojiPreload(
  1284. QVector<QPair<QString, ushort>> data) {
  1285. if (!_recentEmojiPreload.empty() || data.isEmpty()) {
  1286. return;
  1287. }
  1288. _recentEmojiPreload.reserve(data.size());
  1289. for (const auto &[id, rating] : data) {
  1290. _recentEmojiPreload.push_back({ id, rating });
  1291. }
  1292. }
  1293. EmojiPtr Settings::lookupEmojiVariant(EmojiPtr emoji) const {
  1294. if (emoji->hasVariants()) {
  1295. const auto i = _emojiVariants.find(emoji->nonColoredId());
  1296. if (i != end(_emojiVariants)) {
  1297. return emoji->variant(i->second);
  1298. }
  1299. const auto j = _emojiVariants.find(QString());
  1300. if (j != end(_emojiVariants)) {
  1301. return emoji->variant(j->second);
  1302. }
  1303. }
  1304. return emoji;
  1305. }
  1306. bool Settings::hasChosenEmojiVariant(EmojiPtr emoji) const {
  1307. return _emojiVariants.contains(QString())
  1308. || _emojiVariants.contains(emoji->nonColoredId());
  1309. }
  1310. void Settings::saveEmojiVariant(EmojiPtr emoji) {
  1311. Expects(emoji->hasVariants());
  1312. _emojiVariants[emoji->nonColoredId()] = emoji->variantIndex(emoji);
  1313. _saveDelayed.fire({});
  1314. }
  1315. void Settings::saveAllEmojiVariants(EmojiPtr emoji) {
  1316. Expects(emoji->hasVariants());
  1317. _emojiVariants.clear();
  1318. _emojiVariants[QString()] = emoji->variantIndex(emoji);
  1319. _saveDelayed.fire({});
  1320. }
  1321. void Settings::setLegacyEmojiVariants(QMap<QString, int> data) {
  1322. if (!_emojiVariants.empty() || data.isEmpty()) {
  1323. return;
  1324. }
  1325. _emojiVariants.reserve(data.size());
  1326. for (auto i = data.begin(), e = data.end(); i != e; ++i) {
  1327. _emojiVariants.emplace(i.key(), i.value());
  1328. }
  1329. }
  1330. void Settings::resetOnLastLogout() {
  1331. _adaptiveForWide = true;
  1332. _moderateModeEnabled = false;
  1333. _songVolume = kDefaultVolume;
  1334. _videoVolume = kDefaultVolume;
  1335. _askDownloadPath = false;
  1336. _downloadPath = QString();
  1337. _downloadPathBookmark = QByteArray();
  1338. _soundNotify = true;
  1339. _desktopNotify = true;
  1340. _flashBounceNotify = true;
  1341. _notifyView = NotifyView::ShowPreview;
  1342. //_nativeNotifications = std::nullopt;
  1343. //_skipToastsInFocus = false;
  1344. //_notificationsCount = 3;
  1345. //_notificationsCorner = ScreenCorner::BottomRight;
  1346. _includeMutedCounter = true;
  1347. _includeMutedCounterFolders = true;
  1348. _countUnreadMessages = true;
  1349. _notifyAboutPinned = true;
  1350. //_autoLock = 3600;
  1351. //_playbackDeviceId = QString();
  1352. //_captureDeviceId = QString();
  1353. //_cameraDeviceId = QString();
  1354. //_callPlaybackDeviceId = QString();
  1355. //_callCaptureDeviceId = QString();
  1356. //_callOutputVolume = 100;
  1357. //_callInputVolume = 100;
  1358. //_callAudioDuckingEnabled = true;
  1359. _disableCallsLegacy = false;
  1360. _groupCallPushToTalk = false;
  1361. _groupCallPushToTalkShortcut = QByteArray();
  1362. _groupCallPushToTalkDelay = 20;
  1363. _groupCallNoiseSuppression = false;
  1364. //_themesAccentColors = Window::Theme::AccentColors();
  1365. _lastSeenWarningSeen = false;
  1366. _sendFilesWay = Ui::SendFilesWay();
  1367. //_sendSubmitWay = Ui::InputSubmitSettings::Enter;
  1368. _soundOverrides = {};
  1369. _noWarningExtensions.clear();
  1370. _ipRevealWarning = true;
  1371. _loopAnimatedStickers = true;
  1372. _largeEmoji = true;
  1373. _replaceEmoji = true;
  1374. _suggestEmoji = true;
  1375. _suggestStickersByEmoji = true;
  1376. _suggestAnimatedEmoji = true;
  1377. _spellcheckerEnabled = true;
  1378. _videoPlaybackSpeed = PlaybackSpeed();
  1379. _voicePlaybackSpeed = PlaybackSpeed();
  1380. //_videoPipGeometry = QByteArray();
  1381. _dictionariesEnabled = std::vector<int>();
  1382. _autoDownloadDictionaries = true;
  1383. _mainMenuAccountsShown = true;
  1384. _tabbedSelectorSectionEnabled = false; // per-window
  1385. _floatPlayerColumn = Window::Column::Second; // per-window
  1386. _floatPlayerCorner = RectPart::TopRight; // per-window
  1387. _thirdSectionInfoEnabled = true; // per-window
  1388. _thirdSectionExtendedBy = -1; // per-window
  1389. _dialogsWithChatWidthRatio = DefaultDialogsWidthRatio(); // per-window
  1390. _dialogsNoChatWidthRatio = DefaultDialogsWidthRatio(); // per-window
  1391. _thirdColumnWidth = kDefaultThirdColumnWidth; // p-w
  1392. _notifyFromAll = true;
  1393. _tabbedReplacedWithInfo = false; // per-window
  1394. _hiddenGroupCallTooltips = 0;
  1395. _storiesClickTooltipHidden = false;
  1396. _ttlVoiceClickTooltipHidden = false;
  1397. _ivZoom = 100;
  1398. _recordVideoMessages = false;
  1399. _videoQuality = {};
  1400. _chatFiltersHorizontal = false;
  1401. _quickDialogAction = Dialogs::Ui::QuickDialogAction::Disabled;
  1402. _recentEmojiPreload.clear();
  1403. _recentEmoji.clear();
  1404. _emojiVariants.clear();
  1405. _accountsOrder.clear();
  1406. }
  1407. bool Settings::ThirdColumnByDefault() {
  1408. return Platform::IsMacStoreBuild();
  1409. }
  1410. float64 Settings::DefaultDialogsWidthRatio() {
  1411. return ThirdColumnByDefault()
  1412. ? kDefaultBigDialogsWidthRatio
  1413. : kDefaultDialogsWidthRatio;
  1414. }
  1415. qint32 Settings::SerializePlaybackSpeed(PlaybackSpeed speed) {
  1416. using namespace Media;
  1417. const auto value = int(base::SafeRound(
  1418. std::clamp(speed.value, kSpeedMin, kSpeedMax) * 100));
  1419. return speed.enabled ? value : -value;
  1420. }
  1421. auto Settings::DeserializePlaybackSpeed(qint32 speed) -> PlaybackSpeed {
  1422. using namespace Media;
  1423. auto enabled = true;
  1424. const auto validate = [&](float64 result) {
  1425. return PlaybackSpeed{
  1426. .value = (result == 1.) ? kSpedUpDefault : result,
  1427. .enabled = enabled && (result != 1.),
  1428. };
  1429. };
  1430. if (speed >= 0 && speed < 10) {
  1431. // The old values in settings.
  1432. return validate((std::clamp(speed, 0, 6) + 2) / 4.);
  1433. } else if (speed < 0) {
  1434. speed = -speed;
  1435. enabled = false;
  1436. }
  1437. return validate(std::clamp(speed / 100., kSpeedMin, kSpeedMax));
  1438. }
  1439. bool Settings::nativeNotifications() const {
  1440. return _nativeNotifications.value_or(
  1441. Platform::Notifications::ByDefault());
  1442. }
  1443. void Settings::setNativeNotifications(bool value) {
  1444. _nativeNotifications = (value == Platform::Notifications::ByDefault())
  1445. ? std::nullopt
  1446. : std::make_optional(value);
  1447. }
  1448. bool Settings::skipToastsInFocus() const {
  1449. return _skipToastsInFocus;
  1450. }
  1451. void Settings::setSkipToastsInFocus(bool value) {
  1452. _skipToastsInFocus = value;
  1453. }
  1454. void Settings::setTranslateButtonEnabled(bool value) {
  1455. _translateButtonEnabled = value;
  1456. }
  1457. bool Settings::translateButtonEnabled() const {
  1458. return _translateButtonEnabled;
  1459. }
  1460. void Settings::setTranslateChatEnabled(bool value) {
  1461. _translateChatEnabled = value;
  1462. }
  1463. bool Settings::translateChatEnabled() const {
  1464. return _translateChatEnabled.current();
  1465. }
  1466. rpl::producer<bool> Settings::translateChatEnabledValue() const {
  1467. return _translateChatEnabled.value();
  1468. }
  1469. [[nodiscard]] const std::vector<LanguageId> &DefaultSkipLanguages() {
  1470. using namespace Platform;
  1471. static auto Result = [&] {
  1472. auto list = std::vector<LanguageId>();
  1473. list.push_back({ LanguageId::FromName(Lang::Id()) });
  1474. const auto systemId = LanguageId::FromName(SystemLanguage());
  1475. if (list.back() != systemId) {
  1476. list.push_back(systemId);
  1477. }
  1478. Ensures(!list.empty());
  1479. return list;
  1480. }();
  1481. return Result;
  1482. }
  1483. [[nodiscard]] std::vector<LanguageId> NonEmptySkipList(
  1484. std::vector<LanguageId> list) {
  1485. return list.empty() ? DefaultSkipLanguages() : list;
  1486. }
  1487. void Settings::setTranslateTo(LanguageId id) {
  1488. _translateToRaw = int(id.value);
  1489. }
  1490. LanguageId Settings::translateTo() const {
  1491. if (const auto raw = _translateToRaw.current()) {
  1492. return { QLocale::Language(raw) };
  1493. }
  1494. return DefaultSkipLanguages().front();
  1495. }
  1496. rpl::producer<LanguageId> Settings::translateToValue() const {
  1497. return _translateToRaw.value() | rpl::map([=](int raw) {
  1498. return raw
  1499. ? LanguageId{ QLocale::Language(raw) }
  1500. : DefaultSkipLanguages().front();
  1501. }) | rpl::distinct_until_changed();
  1502. }
  1503. void Settings::setSkipTranslationLanguages(
  1504. std::vector<LanguageId> languages) {
  1505. _skipTranslationLanguages = std::move(languages);
  1506. }
  1507. auto Settings::skipTranslationLanguages() const -> std::vector<LanguageId> {
  1508. return NonEmptySkipList(_skipTranslationLanguages.current());
  1509. }
  1510. auto Settings::skipTranslationLanguagesValue() const
  1511. -> rpl::producer<std::vector<LanguageId>> {
  1512. return _skipTranslationLanguages.value() | rpl::map(NonEmptySkipList);
  1513. }
  1514. void Settings::setRememberedDeleteMessageOnlyForYou(bool value) {
  1515. _rememberedDeleteMessageOnlyForYou = value;
  1516. }
  1517. bool Settings::rememberedDeleteMessageOnlyForYou() const {
  1518. return _rememberedDeleteMessageOnlyForYou;
  1519. }
  1520. int Settings::ivZoom() const {
  1521. return _ivZoom.current();
  1522. }
  1523. rpl::producer<int> Settings::ivZoomValue() const {
  1524. return _ivZoom.value();
  1525. }
  1526. void Settings::setIvZoom(int value) {
  1527. #ifdef Q_OS_WIN
  1528. constexpr auto kMin = 25;
  1529. constexpr auto kMax = 500;
  1530. #else
  1531. constexpr auto kMin = 30;
  1532. constexpr auto kMax = 200;
  1533. #endif
  1534. _ivZoom = std::clamp(value, kMin, kMax);
  1535. }
  1536. Media::VideoQuality Settings::videoQuality() const {
  1537. return _videoQuality;
  1538. }
  1539. void Settings::setVideoQuality(Media::VideoQuality value) {
  1540. _videoQuality = value;
  1541. }
  1542. bool Settings::chatFiltersHorizontal() const {
  1543. return _chatFiltersHorizontal.current();
  1544. }
  1545. rpl::producer<bool> Settings::chatFiltersHorizontalChanges() const {
  1546. return _chatFiltersHorizontal.changes();
  1547. }
  1548. void Settings::setChatFiltersHorizontal(bool value) {
  1549. _chatFiltersHorizontal = value;
  1550. }
  1551. Dialogs::Ui::QuickDialogAction Settings::quickDialogAction() const {
  1552. return _quickDialogAction;
  1553. }
  1554. void Settings::setQuickDialogAction(Dialogs::Ui::QuickDialogAction action) {
  1555. _quickDialogAction = action;
  1556. }
  1557. } // namespace Core