1
- using System . Collections . Generic ;
1
+ using System ;
2
+ using System . Collections . Concurrent ;
3
+ using System . Collections . Generic ;
2
4
using System . IO ;
3
5
using System . Text . Json ;
4
- using System ;
6
+ using System . Threading . Tasks ;
5
7
using Flow . Launcher . Plugin . BrowserBookmark . Models ;
6
8
using Microsoft . Data . Sqlite ;
7
9
@@ -156,19 +158,24 @@ private void LoadFaviconsFromDb(string dbPath, List<Bookmark> bookmarks)
156
158
157
159
try
158
160
{
159
- using var connection = new SqliteConnection ( $ "Data Source= { tempDbPath } " ) ;
160
- connection . Open ( ) ;
161
+ // Since some bookmarks may have same favorite icon id, we need to record them to avoid duplicates
162
+ var savedPaths = new ConcurrentDictionary < string , bool > ( ) ;
161
163
162
- foreach ( var bookmark in bookmarks )
164
+ // Get favicons based on bookmarks concurrently
165
+ Parallel . ForEach ( bookmarks . ToArray ( ) , bookmark =>
163
166
{
167
+ // Use read-only connection to avoid locking issues
168
+ var connection = new SqliteConnection ( $ "Data Source={ tempDbPath } ;Mode=ReadOnly") ;
169
+ connection . Open ( ) ;
170
+
164
171
try
165
172
{
166
173
var url = bookmark . Url ;
167
- if ( string . IsNullOrEmpty ( url ) ) continue ;
174
+ if ( string . IsNullOrEmpty ( url ) ) return ;
168
175
169
176
// Extract domain from URL
170
177
if ( ! Uri . TryCreate ( url , UriKind . Absolute , out Uri uri ) )
171
- continue ;
178
+ return ;
172
179
173
180
var domain = uri . Host ;
174
181
@@ -186,28 +193,36 @@ ORDER BY b.width DESC
186
193
187
194
using var reader = cmd . ExecuteReader ( ) ;
188
195
if ( ! reader . Read ( ) || reader . IsDBNull ( 1 ) )
189
- continue ;
196
+ return ;
190
197
191
198
var iconId = reader . GetInt64 ( 0 ) . ToString ( ) ;
192
199
var imageData = ( byte [ ] ) reader [ "image_data" ] ;
193
200
194
201
if ( imageData is not { Length : > 0 } )
195
- continue ;
202
+ return ;
196
203
197
204
var faviconPath = Path . Combine ( _faviconCacheDir , $ "chromium_{ domain } _{ iconId } .png") ;
198
- SaveBitmapData ( imageData , faviconPath ) ;
205
+
206
+ // Filter out duplicate favorite icons
207
+ if ( savedPaths . TryAdd ( faviconPath , true ) )
208
+ {
209
+ SaveBitmapData ( imageData , faviconPath ) ;
210
+ }
199
211
200
212
bookmark . FaviconPath = faviconPath ;
201
213
}
202
214
catch ( Exception ex )
203
215
{
204
216
Main . _context . API . LogException ( ClassName , $ "Failed to extract bookmark favicon: { bookmark . Url } ", ex ) ;
205
217
}
206
- }
207
-
208
- // https://github.com/dotnet/efcore/issues/26580
209
- SqliteConnection . ClearPool ( connection ) ;
210
- connection . Close ( ) ;
218
+ finally
219
+ {
220
+ // https://github.com/dotnet/efcore/issues/26580
221
+ SqliteConnection . ClearPool ( connection ) ;
222
+ connection . Close ( ) ;
223
+ connection . Dispose ( ) ;
224
+ }
225
+ } ) ;
211
226
}
212
227
catch ( Exception ex )
213
228
{
0 commit comments