Skip to content

Commit 7d04ce3

Browse files
committed
Defer sticker reads via InvokeQueued chain for faster first paint
Instead of reading all sticker sets synchronously in crl::on_main, chain each read step via InvokeQueued so that paint events can be processed between heavy file reads. This moves first paint from ~2807ms to ~1294ms by allowing the UI to render before sticker loading completes.
1 parent 46758a8 commit 7d04ce3

File tree

1 file changed

+57
-16
lines changed

1 file changed

+57
-16
lines changed

‎Telegram/SourceFiles/main/main_session.cpp‎

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,62 @@ Session::Session(
181181
_selfUserpicView = view.cloud;
182182
}, lifetime());
183183

184+
// Storage::Account uses Main::Account::session() in those methods.
185+
// So they can't be called during Main::Session construction.
186+
// They are deferred via crl::on_main which fires after the
187+
// constructor returns and _session is set.
188+
//
189+
// Steps are chained via InvokeQueued so that paint events
190+
// can be processed between heavy file reads.
191+
const auto steps = std::make_shared<std::vector<Fn<void()>>>();
192+
const auto runNext = std::make_shared<Fn<void()>>();
193+
*runNext = crl::guard(this, [=] {
194+
if (steps->empty()) {
195+
return;
196+
}
197+
auto step = std::move(steps->front());
198+
steps->erase(steps->begin());
199+
step();
200+
if (!steps->empty()) {
201+
InvokeQueued(
202+
QCoreApplication::instance(),
203+
*runNext);
204+
}
205+
});
206+
steps->push_back([=] {
207+
local().readInstalledStickers();
208+
});
209+
steps->push_back([=] {
210+
local().readInstalledMasks();
211+
});
212+
steps->push_back([=] {
213+
local().readInstalledCustomEmoji();
214+
});
215+
steps->push_back([=] {
216+
data().stickers().notifyUpdated(Data::StickersType::Stickers);
217+
data().stickers().notifyUpdated(Data::StickersType::Masks);
218+
data().stickers().notifyUpdated(Data::StickersType::Emoji);
219+
});
220+
steps->push_back([=] {
221+
local().readFeaturedStickers();
222+
});
223+
steps->push_back([=] {
224+
local().readFeaturedCustomEmoji();
225+
});
226+
steps->push_back([=] {
227+
local().readRecentStickers();
228+
local().readRecentMasks();
229+
local().readFavedStickers();
230+
local().readSavedGifs();
231+
});
232+
steps->push_back([=] {
233+
data().stickers().notifyUpdated(Data::StickersType::Stickers);
234+
data().stickers().notifyUpdated(Data::StickersType::Masks);
235+
data().stickers().notifyUpdated(Data::StickersType::Emoji);
236+
data().stickers().notifySavedGifsUpdated();
237+
DEBUG_LOG(("Init: Account stored data load finished."));
238+
});
239+
184240
crl::on_main(this, [=] {
185241
using Flag = Data::PeerUpdate::Flag;
186242
changes().peerUpdates(
@@ -211,22 +267,7 @@ Session::Session(
211267
saveSettingsDelayed();
212268
}
213269

214-
// Storage::Account uses Main::Account::session() in those methods.
215-
// So they can't be called during Main::Session construction.
216-
local().readInstalledStickers();
217-
local().readInstalledMasks();
218-
local().readInstalledCustomEmoji();
219-
local().readFeaturedStickers();
220-
local().readFeaturedCustomEmoji();
221-
local().readRecentStickers();
222-
local().readRecentMasks();
223-
local().readFavedStickers();
224-
local().readSavedGifs();
225-
data().stickers().notifyUpdated(Data::StickersType::Stickers);
226-
data().stickers().notifyUpdated(Data::StickersType::Masks);
227-
data().stickers().notifyUpdated(Data::StickersType::Emoji);
228-
data().stickers().notifySavedGifsUpdated();
229-
DEBUG_LOG(("Init: Account stored data load finished."));
270+
InvokeQueued(QCoreApplication::instance(), *runNext);
230271
});
231272

232273
#ifndef TDESKTOP_DISABLE_SPELLCHECK

0 commit comments

Comments
 (0)