@@ -49,9 +49,11 @@ public FlowLauncherJsonStorageTopMostRecord()
4949 if ( oldTopMostRecord == null || oldTopMostRecord . records . IsEmpty ) return ;
5050 foreach ( var record in oldTopMostRecord . records )
5151 {
52- _topMostRecord . records . AddOrUpdate ( record . Key , new ConcurrentBag < Record > { record . Value } , ( key , oldValue ) =>
52+ var newValue = new ConcurrentQueue < Record > ( ) ;
53+ newValue . Enqueue ( record . Value ) ;
54+ _topMostRecord . records . AddOrUpdate ( record . Key , newValue , ( key , oldValue ) =>
5355 {
54- oldValue . Add ( record . Value ) ;
56+ oldValue . Enqueue ( record . Value ) ;
5557 return oldValue ;
5658 } ) ;
5759 }
@@ -84,6 +86,11 @@ public bool IsTopMost(Result result)
8486 return _topMostRecord . IsTopMost ( result ) ;
8587 }
8688
89+ public int GetTopMostIndex ( Result result )
90+ {
91+ return _topMostRecord . GetTopMostIndex ( result ) ;
92+ }
93+
8794 public void Remove ( Result result )
8895 {
8996 _topMostRecord . Remove ( result ) ;
@@ -156,8 +163,8 @@ internal void AddOrUpdate(Result result)
156163 internal class MultipleTopMostRecord
157164 {
158165 [ JsonInclude ]
159- [ JsonConverter ( typeof ( ConcurrentDictionaryConcurrentBagConverter ) ) ]
160- public ConcurrentDictionary < string , ConcurrentBag < Record > > records { get ; private set ; } = new ( ) ;
166+ [ JsonConverter ( typeof ( ConcurrentDictionaryConcurrentQueueConverter ) ) ]
167+ public ConcurrentDictionary < string , ConcurrentQueue < Record > > records { get ; private set ; } = new ( ) ;
161168
162169 internal bool IsTopMost ( Result result )
163170 {
@@ -173,6 +180,32 @@ internal bool IsTopMost(Result result)
173180 return value . Any ( record => record . Equals ( result ) ) ;
174181 }
175182
183+ internal int GetTopMostIndex ( Result result )
184+ {
185+ // origin query is null when user select the context menu item directly of one item from query list
186+ // in this case, we do not need to check if the result is top most
187+ if ( records . IsEmpty || result . OriginQuery == null ||
188+ ! records . TryGetValue ( result . OriginQuery . RawQuery , out var value ) )
189+ {
190+ return - 1 ;
191+ }
192+
193+ // since this dictionary should be very small (or empty) going over it should be pretty fast.
194+ // since the latter items should be more recent, we should return the smaller index for score to subtract
195+ // which can make them more topmost
196+ // A, B, C => 2, 1, 0 => (max - 2), (max - 1), (max - 0)
197+ var index = 0 ;
198+ foreach ( var record in value )
199+ {
200+ if ( record . Equals ( result ) )
201+ {
202+ return value . Count - 1 - index ;
203+ }
204+ index ++ ;
205+ }
206+ return - 1 ;
207+ }
208+
176209 internal void Remove ( Result result )
177210 {
178211 // origin query is null when user select the context menu item directly of one item from query list
@@ -183,17 +216,17 @@ internal void Remove(Result result)
183216 return ;
184217 }
185218
186- // remove the record from the bag
187- var bag = new ConcurrentQueue < Record > ( value . Where ( r => ! r . Equals ( result ) ) ) ;
188- if ( bag . IsEmpty )
219+ // remove the record from the queue
220+ var queue = new ConcurrentQueue < Record > ( value . Where ( r => ! r . Equals ( result ) ) ) ;
221+ if ( queue . IsEmpty )
189222 {
190- // if the bag is empty, remove the bag from the dictionary
223+ // if the queue is empty, remove the queue from the dictionary
191224 records . TryRemove ( result . OriginQuery . RawQuery , out _ ) ;
192225 }
193226 else
194227 {
195- // change the bag in the dictionary
196- records [ result . OriginQuery . RawQuery ] = new ConcurrentBag < Record > ( bag ) ;
228+ // change the queue in the dictionary
229+ records [ result . OriginQuery . RawQuery ] = queue ;
197230 }
198231 }
199232
@@ -215,40 +248,38 @@ internal void AddOrUpdate(Result result)
215248 } ;
216249 if ( ! records . TryGetValue ( result . OriginQuery . RawQuery , out var value ) )
217250 {
218- // create a new bag if it does not exist
219- value = new ConcurrentBag < Record > ( )
220- {
221- record
222- } ;
251+ // create a new queue if it does not exist
252+ value = new ConcurrentQueue < Record > ( ) ;
253+ value . Enqueue ( record ) ;
223254 records . TryAdd ( result . OriginQuery . RawQuery , value ) ;
224255 }
225256 else
226257 {
227- // add or update the record in the bag
228- var bag = new ConcurrentQueue < Record > ( value . Where ( r => ! r . Equals ( result ) ) ) ; // make sure we don't have duplicates
229- bag . Enqueue ( record ) ;
230- records [ result . OriginQuery . RawQuery ] = new ConcurrentBag < Record > ( bag ) ;
258+ // add or update the record in the queue
259+ var queue = new ConcurrentQueue < Record > ( value . Where ( r => ! r . Equals ( result ) ) ) ; // make sure we don't have duplicates
260+ queue . Enqueue ( record ) ;
261+ records [ result . OriginQuery . RawQuery ] = queue ;
231262 }
232263 }
233264 }
234265
235266 /// <summary>
236- /// Because ConcurrentBag does not support serialization, we need to convert it to a List
267+ /// Because ConcurrentQueue does not support serialization, we need to convert it to a List
237268 /// </summary>
238- internal class ConcurrentDictionaryConcurrentBagConverter : JsonConverter < ConcurrentDictionary < string , ConcurrentBag < Record > > >
269+ internal class ConcurrentDictionaryConcurrentQueueConverter : JsonConverter < ConcurrentDictionary < string , ConcurrentQueue < Record > > >
239270 {
240- public override ConcurrentDictionary < string , ConcurrentBag < Record > > Read ( ref Utf8JsonReader reader , Type typeToConvert , JsonSerializerOptions options )
271+ public override ConcurrentDictionary < string , ConcurrentQueue < Record > > Read ( ref Utf8JsonReader reader , Type typeToConvert , JsonSerializerOptions options )
241272 {
242273 var dictionary = JsonSerializer . Deserialize < Dictionary < string , List < Record > > > ( ref reader , options ) ;
243- var concurrentDictionary = new ConcurrentDictionary < string , ConcurrentBag < Record > > ( ) ;
274+ var concurrentDictionary = new ConcurrentDictionary < string , ConcurrentQueue < Record > > ( ) ;
244275 foreach ( var kvp in dictionary )
245276 {
246- concurrentDictionary . TryAdd ( kvp . Key , new ConcurrentBag < Record > ( kvp . Value ) ) ;
277+ concurrentDictionary . TryAdd ( kvp . Key , new ConcurrentQueue < Record > ( kvp . Value ) ) ;
247278 }
248279 return concurrentDictionary ;
249280 }
250281
251- public override void Write ( Utf8JsonWriter writer , ConcurrentDictionary < string , ConcurrentBag < Record > > value , JsonSerializerOptions options )
282+ public override void Write ( Utf8JsonWriter writer , ConcurrentDictionary < string , ConcurrentQueue < Record > > value , JsonSerializerOptions options )
252283 {
253284 var dict = new Dictionary < string , List < Record > > ( ) ;
254285 foreach ( var kvp in value )
0 commit comments