OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ios/chrome/browser/reading_list/reading_list_model_impl.h" | 5 #include "ios/chrome/browser/reading_list/reading_list_model_impl.h" |
6 | 6 |
7 #include "base/bind.h" | |
8 #include "components/prefs/pref_service.h" | |
7 #include "ios/chrome/browser/reading_list/reading_list_model_storage.h" | 9 #include "ios/chrome/browser/reading_list/reading_list_model_storage.h" |
10 #include "ios/chrome/browser/reading_list/reading_list_pref_names.h" | |
8 #include "url/gurl.h" | 11 #include "url/gurl.h" |
9 | 12 |
10 ReadingListModelImpl::ReadingListModelImpl() : ReadingListModelImpl(NULL) {} | 13 ReadingListModelImpl::ReadingListModelImpl() |
14 : ReadingListModelImpl(NULL, NULL) {} | |
11 | 15 |
12 ReadingListModelImpl::ReadingListModelImpl( | 16 ReadingListModelImpl::ReadingListModelImpl( |
13 std::unique_ptr<ReadingListModelStorage> storage) | 17 std::unique_ptr<ReadingListModelStorage> storage, |
14 : hasUnseen_(false) { | 18 PrefService* pref_service) |
19 : pref_service_(pref_service), | |
20 has_unseen_(false), | |
21 loaded_(false), | |
22 weak_ptr_factory_(this) { | |
15 if (storage) { | 23 if (storage) { |
16 storageLayer_ = std::move(storage); | 24 storage_layer_ = std::move(storage); |
17 read_ = storageLayer_->LoadPersistentReadList(); | 25 storage_layer_->SetReadingListModel(this); |
18 unread_ = storageLayer_->LoadPersistentUnreadList(); | 26 storage_layer_->LoadPersistentLists(); |
19 hasUnseen_ = storageLayer_->LoadPersistentHasUnseen(); | 27 } else { |
28 loaded_ = true; | |
20 } | 29 } |
21 loaded_ = true; | 30 has_unseen_ = LoadPersistentHasUnseen(); |
22 } | 31 } |
23 ReadingListModelImpl::~ReadingListModelImpl() {} | 32 ReadingListModelImpl::~ReadingListModelImpl() {} |
24 | 33 |
34 void ReadingListModelImpl::ModelLoaded( | |
35 std::unique_ptr<ReadingListEntries> unread, | |
36 std::unique_ptr<ReadingListEntries> read) { | |
37 read_ = std::move(read); | |
38 unread_ = std::move(unread); | |
39 loaded_ = true; | |
40 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | |
41 ReadingListModelLoaded(this)); | |
42 } | |
43 | |
25 void ReadingListModelImpl::Shutdown() { | 44 void ReadingListModelImpl::Shutdown() { |
26 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 45 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
27 ReadingListModelBeingDeleted(this)); | 46 ReadingListModelBeingDeleted(this)); |
28 loaded_ = false; | 47 loaded_ = false; |
29 } | 48 } |
30 | 49 |
31 bool ReadingListModelImpl::loaded() const { | 50 bool ReadingListModelImpl::loaded() const { |
32 return loaded_; | 51 return loaded_; |
33 } | 52 } |
34 | 53 |
35 size_t ReadingListModelImpl::unread_size() const { | 54 size_t ReadingListModelImpl::unread_size() const { |
36 DCHECK(loaded()); | 55 if (!loaded()) |
37 return unread_.size(); | 56 return 0; |
57 return unread_->size(); | |
38 } | 58 } |
39 | 59 |
40 size_t ReadingListModelImpl::read_size() const { | 60 size_t ReadingListModelImpl::read_size() const { |
41 DCHECK(loaded()); | 61 if (!loaded()) |
42 return read_.size(); | 62 return 0; |
63 return read_->size(); | |
43 } | 64 } |
44 | 65 |
45 bool ReadingListModelImpl::HasUnseenEntries() const { | 66 bool ReadingListModelImpl::HasUnseenEntries() const { |
46 DCHECK(loaded()); | 67 if (!loaded()) |
47 return unread_size() && hasUnseen_; | 68 return false; |
69 return unread_size() && has_unseen_; | |
48 } | 70 } |
49 | 71 |
50 void ReadingListModelImpl::ResetUnseenEntries() { | 72 void ReadingListModelImpl::ResetUnseenEntries() { |
51 DCHECK(loaded()); | 73 DCHECK(loaded()); |
52 hasUnseen_ = false; | 74 has_unseen_ = false; |
53 if (storageLayer_ && !IsPerformingBatchUpdates()) | 75 if (!IsPerformingBatchUpdates()) |
54 storageLayer_->SavePersistentHasUnseen(false); | 76 SavePersistentHasUnseen(false); |
55 } | 77 } |
56 | 78 |
57 // Returns a specific entry. | 79 // Returns a specific entry. |
58 const ReadingListEntry& ReadingListModelImpl::GetUnreadEntryAtIndex( | 80 const ReadingListEntry& ReadingListModelImpl::GetUnreadEntryAtIndex( |
59 size_t index) const { | 81 size_t index) const { |
60 DCHECK(loaded()); | 82 DCHECK(loaded()); |
61 return unread_[index]; | 83 return unread_->at(index); |
62 } | 84 } |
63 | 85 |
64 const ReadingListEntry& ReadingListModelImpl::GetReadEntryAtIndex( | 86 const ReadingListEntry& ReadingListModelImpl::GetReadEntryAtIndex( |
65 size_t index) const { | 87 size_t index) const { |
66 DCHECK(loaded()); | 88 DCHECK(loaded()); |
67 return read_[index]; | 89 return read_->at(index); |
68 } | 90 } |
69 | 91 |
70 bool ReadingListModelImpl::CallbackEntryURL( | 92 bool ReadingListModelImpl::CallbackEntryURL( |
71 const GURL& url, | 93 const GURL& url, |
72 base::Callback<void(const ReadingListEntry&)> callback) const { | 94 base::Callback<void(const ReadingListEntry&)> callback) const { |
73 DCHECK(loaded()); | 95 DCHECK(loaded()); |
74 ReadingListEntry entry(url, std::string()); | 96 ReadingListEntry entry(url, std::string()); |
75 auto resultUnread = std::find(unread_.begin(), unread_.end(), entry); | 97 auto resultUnread = std::find(unread_->begin(), unread_->end(), entry); |
76 if (resultUnread != unread_.end()) { | 98 if (resultUnread != unread_->end()) { |
77 callback.Run(*resultUnread); | 99 callback.Run(*resultUnread); |
78 return true; | 100 return true; |
79 } | 101 } |
80 | 102 |
81 auto resultRead = std::find(read_.begin(), read_.end(), entry); | 103 auto resultRead = std::find(read_->begin(), read_->end(), entry); |
82 if (resultRead != read_.end()) { | 104 if (resultRead != read_->end()) { |
83 callback.Run(*resultRead); | 105 callback.Run(*resultRead); |
84 return true; | 106 return true; |
85 } | 107 } |
86 return false; | 108 return false; |
87 } | 109 } |
88 | 110 |
89 void ReadingListModelImpl::RemoveEntryByUrl(const GURL& url) { | 111 void ReadingListModelImpl::RemoveEntryByUrl(const GURL& url) { |
90 DCHECK(loaded()); | 112 DCHECK(loaded()); |
91 const ReadingListEntry entry(url, std::string()); | 113 const ReadingListEntry entry(url, std::string()); |
92 | 114 |
93 auto result = std::find(unread_.begin(), unread_.end(), entry); | 115 auto result = std::find(unread_->begin(), unread_->end(), entry); |
94 if (result != unread_.end()) { | 116 if (result != unread_->end()) { |
95 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 117 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
96 ReadingListWillRemoveUnreadEntry( | 118 ReadingListWillRemoveUnreadEntry( |
97 this, std::distance(unread_.begin(), result))); | 119 this, std::distance(unread_->begin(), result))); |
98 unread_.erase(result); | 120 unread_->erase(result); |
99 if (storageLayer_ && !IsPerformingBatchUpdates()) | 121 |
100 storageLayer_->SavePersistentUnreadList(unread_); | 122 if (storage_layer_) { |
123 storage_layer_->RemoveEntry(*result); | |
124 } | |
125 | |
101 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 126 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
102 ReadingListDidApplyChanges(this)); | 127 ReadingListDidApplyChanges(this)); |
103 return; | 128 return; |
104 } | 129 } |
105 | 130 |
106 result = std::find(read_.begin(), read_.end(), entry); | 131 result = std::find(read_->begin(), read_->end(), entry); |
107 if (result != read_.end()) { | 132 if (result != read_->end()) { |
108 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 133 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
109 ReadingListWillRemoveReadEntry( | 134 ReadingListWillRemoveReadEntry( |
110 this, std::distance(read_.begin(), result))); | 135 this, std::distance(read_->begin(), result))); |
111 read_.erase(result); | 136 read_->erase(result); |
112 if (storageLayer_ && !IsPerformingBatchUpdates()) | 137 |
113 storageLayer_->SavePersistentReadList(read_); | 138 if (storage_layer_) { |
139 storage_layer_->RemoveEntry(*result); | |
140 } | |
141 | |
114 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 142 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
115 ReadingListDidApplyChanges(this)); | 143 ReadingListDidApplyChanges(this)); |
116 return; | 144 return; |
117 } | 145 } |
118 } | 146 } |
119 | 147 |
120 const ReadingListEntry& ReadingListModelImpl::AddEntry( | 148 const ReadingListEntry& ReadingListModelImpl::AddEntry( |
121 const GURL& url, | 149 const GURL& url, |
122 const std::string& title) { | 150 const std::string& title) { |
123 DCHECK(loaded()); | 151 DCHECK(loaded()); |
124 RemoveEntryByUrl(url); | 152 RemoveEntryByUrl(url); |
125 ReadingListEntry entry(url, title); | 153 ReadingListEntry entry(url, title); |
126 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 154 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
127 ReadingListWillAddUnreadEntry(this, entry)); | 155 ReadingListWillAddUnreadEntry(this, entry)); |
128 unread_.insert(unread_.begin(), std::move(entry)); | 156 unread_->insert(unread_->begin(), std::move(entry)); |
129 hasUnseen_ = true; | 157 has_unseen_ = true; |
130 if (storageLayer_ && !IsPerformingBatchUpdates()) { | 158 SavePersistentHasUnseen(true); |
131 storageLayer_->SavePersistentUnreadList(unread_); | 159 if (storage_layer_) { |
132 storageLayer_->SavePersistentHasUnseen(true); | 160 storage_layer_->SaveEntry(entry, false); |
gambard
2016/09/28 16:19:47
You cannot do this. The entry has just been moved.
| |
133 } | 161 } |
162 | |
134 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 163 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
135 ReadingListDidApplyChanges(this)); | 164 ReadingListDidApplyChanges(this)); |
136 return *unread_.begin(); | 165 return *unread_->begin(); |
137 } | 166 } |
138 | 167 |
139 void ReadingListModelImpl::MarkReadByURL(const GURL& url) { | 168 void ReadingListModelImpl::MarkReadByURL(const GURL& url) { |
140 DCHECK(loaded()); | 169 DCHECK(loaded()); |
141 ReadingListEntry entry(url, std::string()); | 170 ReadingListEntry entry(url, std::string()); |
142 auto result = std::find(unread_.begin(), unread_.end(), entry); | 171 auto result = std::find(unread_->begin(), unread_->end(), entry); |
143 if (result == unread_.end()) | 172 if (result == unread_->end()) |
144 return; | 173 return; |
145 | 174 |
175 storage_layer_->SaveEntry(entry, true); | |
146 FOR_EACH_OBSERVER( | 176 FOR_EACH_OBSERVER( |
147 ReadingListModelObserver, observers_, | 177 ReadingListModelObserver, observers_, |
148 ReadingListWillMoveEntry(this, std::distance(unread_.begin(), result))); | 178 ReadingListWillMoveEntry(this, std::distance(unread_->begin(), result))); |
149 | 179 |
150 read_.insert(read_.begin(), std::move(*result)); | 180 result->MarkEntryUpdated(); |
151 unread_.erase(result); | 181 if (storage_layer_) { |
182 storage_layer_->SaveEntry(*result, true); | |
183 } | |
152 | 184 |
153 if (storageLayer_ && !IsPerformingBatchUpdates()) { | 185 read_->insert(read_->begin(), std::move(*result)); |
154 storageLayer_->SavePersistentUnreadList(unread_); | 186 unread_->erase(result); |
gambard
2016/09/28 16:19:47
You moved result. Are you sure this will work?
Olivier
2016/09/28 17:03:37
Done.
| |
155 storageLayer_->SavePersistentReadList(read_); | 187 |
156 } | |
157 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 188 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
158 ReadingListDidApplyChanges(this)); | 189 ReadingListDidApplyChanges(this)); |
159 } | 190 } |
160 | 191 |
161 void ReadingListModelImpl::SetEntryTitle(const GURL& url, | 192 void ReadingListModelImpl::SetEntryTitle(const GURL& url, |
162 const std::string& title) { | 193 const std::string& title) { |
163 DCHECK(loaded()); | 194 DCHECK(loaded()); |
164 const ReadingListEntry entry(url, std::string()); | 195 const ReadingListEntry entry(url, std::string()); |
165 | 196 |
166 auto result = std::find(unread_.begin(), unread_.end(), entry); | 197 auto result = std::find(unread_->begin(), unread_->end(), entry); |
167 if (result != unread_.end()) { | 198 if (result != unread_->end()) { |
168 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 199 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
169 ReadingListWillUpdateUnreadEntry( | 200 ReadingListWillUpdateUnreadEntry( |
170 this, std::distance(unread_.begin(), result))); | 201 this, std::distance(unread_->begin(), result))); |
171 result->SetTitle(title); | 202 result->SetTitle(title); |
172 if (storageLayer_ && !IsPerformingBatchUpdates()) | 203 |
173 storageLayer_->SavePersistentUnreadList(unread_); | 204 if (storage_layer_) { |
205 storage_layer_->SaveEntry(*result, false); | |
206 } | |
174 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 207 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
175 ReadingListDidApplyChanges(this)); | 208 ReadingListDidApplyChanges(this)); |
176 return; | 209 return; |
177 } | 210 } |
178 | 211 |
179 result = std::find(read_.begin(), read_.end(), entry); | 212 result = std::find(read_->begin(), read_->end(), entry); |
180 if (result != read_.end()) { | 213 if (result != read_->end()) { |
181 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 214 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
182 ReadingListWillUpdateReadEntry( | 215 ReadingListWillUpdateReadEntry( |
183 this, std::distance(read_.begin(), result))); | 216 this, std::distance(read_->begin(), result))); |
184 result->SetTitle(title); | 217 result->SetTitle(title); |
185 if (storageLayer_ && !IsPerformingBatchUpdates()) | 218 if (storage_layer_) { |
186 storageLayer_->SavePersistentReadList(read_); | 219 storage_layer_->SaveEntry(*result, true); |
220 } | |
187 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 221 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
188 ReadingListDidApplyChanges(this)); | 222 ReadingListDidApplyChanges(this)); |
189 return; | 223 return; |
190 } | 224 } |
191 } | 225 } |
192 | 226 |
193 void ReadingListModelImpl::SetEntryDistilledURL(const GURL& url, | 227 void ReadingListModelImpl::SetEntryDistilledURL(const GURL& url, |
194 const GURL& distilled_url) { | 228 const GURL& distilled_url) { |
195 DCHECK(loaded()); | 229 DCHECK(loaded()); |
196 const ReadingListEntry entry(url, std::string()); | 230 const ReadingListEntry entry(url, std::string()); |
197 | 231 |
198 auto result = std::find(unread_.begin(), unread_.end(), entry); | 232 auto result = std::find(unread_->begin(), unread_->end(), entry); |
199 if (result != unread_.end()) { | 233 if (result != unread_->end()) { |
200 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 234 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
201 ReadingListWillUpdateUnreadEntry( | 235 ReadingListWillUpdateUnreadEntry( |
202 this, std::distance(unread_.begin(), result))); | 236 this, std::distance(unread_->begin(), result))); |
203 result->SetDistilledURL(distilled_url); | 237 result->SetDistilledURL(distilled_url); |
204 if (storageLayer_ && !IsPerformingBatchUpdates()) | 238 if (storage_layer_) { |
205 storageLayer_->SavePersistentUnreadList(unread_); | 239 storage_layer_->SaveEntry(*result, false); |
240 } | |
206 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 241 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
207 ReadingListDidApplyChanges(this)); | 242 ReadingListDidApplyChanges(this)); |
208 return; | 243 return; |
209 } | 244 } |
210 | 245 |
211 result = std::find(read_.begin(), read_.end(), entry); | 246 result = std::find(read_->begin(), read_->end(), entry); |
212 if (result != read_.end()) { | 247 if (result != read_->end()) { |
213 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 248 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
214 ReadingListWillUpdateReadEntry( | 249 ReadingListWillUpdateReadEntry( |
215 this, std::distance(read_.begin(), result))); | 250 this, std::distance(read_->begin(), result))); |
216 result->SetDistilledURL(distilled_url); | 251 result->SetDistilledURL(distilled_url); |
217 if (storageLayer_ && !IsPerformingBatchUpdates()) | 252 if (storage_layer_) { |
218 storageLayer_->SavePersistentReadList(read_); | 253 storage_layer_->SaveEntry(*result, true); |
254 } | |
219 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 255 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
220 ReadingListDidApplyChanges(this)); | 256 ReadingListDidApplyChanges(this)); |
221 return; | 257 return; |
222 } | 258 } |
223 } | 259 } |
224 | 260 |
225 void ReadingListModelImpl::SetEntryDistilledState( | 261 void ReadingListModelImpl::SetEntryDistilledState( |
226 const GURL& url, | 262 const GURL& url, |
227 ReadingListEntry::DistillationState state) { | 263 ReadingListEntry::DistillationState state) { |
228 DCHECK(loaded()); | 264 DCHECK(loaded()); |
229 const ReadingListEntry entry(url, std::string()); | 265 const ReadingListEntry entry(url, std::string()); |
230 | 266 |
231 auto result = std::find(unread_.begin(), unread_.end(), entry); | 267 auto result = std::find(unread_->begin(), unread_->end(), entry); |
232 if (result != unread_.end()) { | 268 if (result != unread_->end()) { |
233 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 269 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
234 ReadingListWillUpdateUnreadEntry( | 270 ReadingListWillUpdateUnreadEntry( |
235 this, std::distance(unread_.begin(), result))); | 271 this, std::distance(unread_->begin(), result))); |
236 result->SetDistilledState(state); | 272 result->SetDistilledState(state); |
237 if (storageLayer_ && !IsPerformingBatchUpdates()) | 273 if (storage_layer_) { |
238 storageLayer_->SavePersistentUnreadList(unread_); | 274 storage_layer_->SaveEntry(*result, false); |
275 } | |
239 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 276 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
240 ReadingListDidApplyChanges(this)); | 277 ReadingListDidApplyChanges(this)); |
241 return; | 278 return; |
242 } | 279 } |
243 | 280 |
244 result = std::find(read_.begin(), read_.end(), entry); | 281 result = std::find(read_->begin(), read_->end(), entry); |
245 if (result != read_.end()) { | 282 if (result != read_->end()) { |
246 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 283 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
247 ReadingListWillUpdateReadEntry( | 284 ReadingListWillUpdateReadEntry( |
248 this, std::distance(read_.begin(), result))); | 285 this, std::distance(read_->begin(), result))); |
249 result->SetDistilledState(state); | 286 result->SetDistilledState(state); |
250 if (storageLayer_ && !IsPerformingBatchUpdates()) | 287 if (storage_layer_) { |
251 storageLayer_->SavePersistentReadList(read_); | 288 storage_layer_->SaveEntry(*result, true); |
289 } | |
252 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, | 290 FOR_EACH_OBSERVER(ReadingListModelObserver, observers_, |
253 ReadingListDidApplyChanges(this)); | 291 ReadingListDidApplyChanges(this)); |
254 return; | 292 return; |
255 } | 293 } |
256 }; | 294 }; |
257 | 295 |
258 void ReadingListModelImpl::EndBatchUpdates() { | 296 void ReadingListModelImpl::LeavingBatchUpdates() { |
259 ReadingListModel::EndBatchUpdates(); | 297 ReadingListModel::EnteringBatchUpdates(); |
260 if (IsPerformingBatchUpdates() || !storageLayer_) { | 298 if (storage_layer_) { |
299 SavePersistentHasUnseen(has_unseen_); | |
300 storage_layer_->CommitTransaction(); | |
301 } | |
302 } | |
303 | |
304 void ReadingListModelImpl::EnteringBatchUpdates() { | |
305 if (storage_layer_) { | |
306 storage_layer_->BeginTransaction(); | |
307 } | |
308 ReadingListModel::EnteringBatchUpdates(); | |
309 } | |
310 | |
311 void ReadingListModelImpl::SavePersistentHasUnseen(bool has_unseen) { | |
312 if (!pref_service_) { | |
261 return; | 313 return; |
262 } | 314 } |
263 storageLayer_->SavePersistentUnreadList(unread_); | 315 pref_service_->SetBoolean(reading_list::prefs::kReadingListHasUnseenEntries, |
264 storageLayer_->SavePersistentReadList(read_); | 316 has_unseen); |
265 storageLayer_->SavePersistentHasUnseen(hasUnseen_); | |
266 } | 317 } |
318 | |
319 bool ReadingListModelImpl::LoadPersistentHasUnseen() { | |
320 if (!pref_service_) { | |
321 return false; | |
322 } | |
323 return pref_service_->GetBoolean( | |
324 reading_list::prefs::kReadingListHasUnseenEntries); | |
325 } | |
OLD | NEW |