| 238 | } |
| 239 | |
| 240 | void Stories::apply(const MTPDupdateStory &data) { |
| 241 | if (GetEnhancedBool("hide_stories")) { |
| 242 | return; |
| 243 | } |
| 244 | const auto peerId = peerFromMTP(data.vpeer()); |
| 245 | const auto peer = _owner->peer(peerId); |
| 246 | const auto now = base::unixtime::now(); |
| 247 | const auto idDates = parseAndApply(peer, data.vstory(), now); |
| 248 | if (!idDates) { |
| 249 | return; |
| 250 | } |
| 251 | const auto expired = (idDates.expires <= now); |
| 252 | if (expired) { |
| 253 | applyExpired({ peerId, idDates.id }); |
| 254 | return; |
| 255 | } |
| 256 | const auto i = _all.find(peerId); |
| 257 | if (i == end(_all)) { |
| 258 | requestPeerStories(peer); |
| 259 | return; |
| 260 | } else if (i->second.ids.contains(idDates)) { |
| 261 | return; |
| 262 | } |
| 263 | const auto wasInfo = i->second.info(); |
| 264 | i->second.ids.emplace(idDates); |
| 265 | const auto nowInfo = i->second.info(); |
| 266 | if (peer->isSelf() && i->second.readTill < idDates.id) { |
| 267 | _readTill[peerId] = i->second.readTill = idDates.id; |
| 268 | } |
| 269 | if (wasInfo == nowInfo) { |
| 270 | return; |
| 271 | } |
| 272 | const auto refreshInList = [&](StorySourcesList list) { |
| 273 | auto &sources = _sources[static_cast<int>(list)]; |
| 274 | const auto i = ranges::find( |
| 275 | sources, |
| 276 | peerId, |
| 277 | &StoriesSourceInfo::id); |
| 278 | if (i != end(sources)) { |
| 279 | *i = nowInfo; |
| 280 | sort(list); |
| 281 | } |
| 282 | }; |
| 283 | if (peer->hasStoriesHidden()) { |
| 284 | refreshInList(StorySourcesList::Hidden); |
| 285 | } else { |
| 286 | refreshInList(StorySourcesList::NotHidden); |
| 287 | } |
| 288 | _sourceChanged.fire_copy(peerId); |
| 289 | updatePeerStoriesState(peer); |
| 290 | } |
| 291 | |
| 292 | void Stories::apply(const MTPDupdateReadStories &data) { |
| 293 | if (GetEnhancedBool("hide_stories")) { |
no test coverage detected