This repository has been archived by the owner on Jan 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c596515
commit 1a6d601
Showing
33 changed files
with
1,566 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
using HistoryManager.Apps; | ||
using HistoryViewer.Infrastructure.Image; | ||
using HistoryViewer.Models; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using System.Windows.Media; | ||
using System.Windows.Media.Imaging; | ||
|
||
namespace HistoryViewer.Infrastructure | ||
{ | ||
internal static class AppInfoModelBuilder | ||
{ | ||
#region Fields | ||
|
||
private static readonly string[] ImageExtensions = | ||
{ | ||
".png", | ||
".jpg", | ||
".jpeg", | ||
".gif", | ||
".bmp", | ||
".tiff", | ||
".ico" | ||
}; | ||
|
||
private static ImageCache ImageCache = ImageCache.Instance; | ||
|
||
#endregion Fields | ||
|
||
#region Enums | ||
|
||
private enum ImageType | ||
{ | ||
File, | ||
Folder, | ||
Data, | ||
ImageFile, | ||
Error, | ||
Cache | ||
} | ||
|
||
#endregion Enums | ||
|
||
#region Methods | ||
|
||
private static ImageSource GetImage(string path) | ||
{ | ||
var img = LoadImage(path); | ||
ImageCache[path] = img; | ||
return img; | ||
} | ||
|
||
private static ImageSource LoadImage(string path) | ||
{ | ||
ImageSource image = null; | ||
ImageType type = ImageType.Error; | ||
try | ||
{ | ||
if (string.IsNullOrEmpty(path)) | ||
{ | ||
// return new ImageResult(ImageCache[Constant.ErrorIcon], ImageType.Error); | ||
} | ||
if (ImageCache.ContainsKey(path)) | ||
{ | ||
return ImageCache[path]; | ||
} | ||
|
||
if (path?.StartsWith("data:", StringComparison.OrdinalIgnoreCase) ?? false) | ||
{ | ||
var imageSource = new BitmapImage(new Uri(path)); | ||
imageSource.Freeze(); | ||
return imageSource; | ||
} | ||
|
||
if (!Path.IsPathRooted(path)) | ||
{ | ||
path = Path.Combine(Constant.ProgramDirectory, "Images", Path.GetFileName(path)); | ||
} | ||
|
||
if (Directory.Exists(path)) | ||
{ | ||
/* Directories can also have thumbnails instead of shell icons. | ||
* Generating thumbnails for a bunch of folders while scrolling through | ||
* results from Everything makes a big impact on performance and | ||
* Wox responsibility. | ||
* - Solution: just load the icon | ||
*/ | ||
type = ImageType.Folder; | ||
image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize, | ||
Constant.ThumbnailSize, ThumbnailOptions.IconOnly); | ||
} | ||
else if (File.Exists(path)) | ||
{ | ||
var extension = Path.GetExtension(path).ToLower(); | ||
if (ImageExtensions.Contains(extension)) | ||
{ | ||
type = ImageType.ImageFile; | ||
/* Although the documentation for GetImage on MSDN indicates that | ||
* if a thumbnail is available it will return one, this has proved to not | ||
* be the case in many situations while testing. | ||
* - Solution: explicitly pass the ThumbnailOnly flag | ||
*/ | ||
image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize, | ||
Constant.ThumbnailSize, ThumbnailOptions.ThumbnailOnly); | ||
} | ||
else | ||
{ | ||
type = ImageType.File; | ||
image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize, | ||
Constant.ThumbnailSize, ThumbnailOptions.None); | ||
} | ||
} | ||
//else | ||
//{ | ||
// image = ImageCache[Constant.ErrorIcon]; | ||
// path = Constant.ErrorIcon; | ||
//} | ||
|
||
if (type != ImageType.Error) | ||
{ | ||
image.Freeze(); | ||
} | ||
} | ||
catch (System.Exception e) | ||
{ | ||
Trace.WriteLine($"|ImageLoader.Load|Failed to get thumbnail for {path} - {e}"); | ||
type = ImageType.Error; | ||
//image = ImageCache[Constant.ErrorIcon]; | ||
//ImageCache[path] = image; | ||
} | ||
return image; | ||
} | ||
|
||
public static void Initialize() | ||
{ | ||
Task.Run(() => | ||
{ | ||
ImageCache.GetKeys().AsParallel().ForAll(x => | ||
{ | ||
GetImage(x); | ||
}); | ||
}); | ||
} | ||
|
||
public static IEnumerable<AppInfoModel> ToModel(this IEnumerable<AppInfo> src) | ||
{ | ||
var dst = new List<AppInfoModel>(); | ||
foreach (var item in src) | ||
{ | ||
if (!item.IsEmpty) | ||
{ | ||
var d = new AppInfoModel( | ||
path: item.Path, | ||
name: item.Name, | ||
image: GetImage(item.Path) | ||
); | ||
dst.Add(d); | ||
} | ||
} | ||
|
||
return dst; | ||
} | ||
|
||
#endregion Methods | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
using Newtonsoft.Json; | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Configuration; | ||
using System.IO; | ||
using System.Windows.Media; | ||
|
||
namespace HistoryViewer.Infrastructure | ||
{ | ||
public class ImageCache | ||
{ | ||
#region Fields | ||
|
||
private static ImageCache _instance = null; | ||
private readonly ConcurrentDictionary<string, ImageSource> _cache = new ConcurrentDictionary<string, ImageSource>(); | ||
|
||
#endregion Fields | ||
|
||
#region Constructors | ||
|
||
private ImageCache() | ||
{ | ||
} | ||
|
||
private ImageCache(IEnumerable<string> keys) | ||
{ | ||
} | ||
|
||
#endregion Constructors | ||
|
||
#region Properties | ||
|
||
private static string ImageCachePath => Environment.ExpandEnvironmentVariables(ConfigurationManager.AppSettings["ImageCache"]); | ||
|
||
public static ImageCache Instance | ||
{ | ||
get | ||
{ | ||
if (_instance != null) { return _instance; } | ||
else if (File.Exists(ImageCachePath)) | ||
{ | ||
_instance = new ImageCache(GetKeys()); | ||
return _instance; | ||
} | ||
else | ||
{ | ||
_instance = new ImageCache(); | ||
return _instance; | ||
} | ||
} | ||
} | ||
|
||
public IEnumerable<string> Keys => _cache?.Keys ?? new string[] { }; | ||
|
||
#endregion Properties | ||
|
||
#region Indexers | ||
|
||
public ImageSource this[string path] | ||
{ | ||
get => _cache[path]; | ||
set => _cache[path] = value; | ||
} | ||
|
||
#endregion Indexers | ||
|
||
#region Methods | ||
|
||
public static IEnumerable<string> GetKeys() | ||
{ | ||
var json = File.ReadAllText(ImageCachePath); | ||
var keys = JsonConvert.DeserializeObject<IEnumerable<string>>(json); | ||
return keys; | ||
} | ||
|
||
public static void Save() | ||
{ | ||
if (_instance != null) | ||
{ | ||
var json = JsonConvert.SerializeObject(_instance._cache.Keys, Formatting.Indented); | ||
File.WriteAllText(ImageCachePath, json); | ||
} | ||
} | ||
|
||
public bool ContainsKey(string key) | ||
{ | ||
var contains = _cache.ContainsKey(key); | ||
return contains; | ||
} | ||
|
||
#endregion Methods | ||
} | ||
} |
Oops, something went wrong.