Skip to content

Commit 0709ae7

Browse files
authored
Merge pull request #16 from nelinory/development
Development
2 parents 5098106 + e3d513f commit 0709ae7

39 files changed

Lines changed: 952 additions & 237 deletions

App.xaml.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ public partial class App
6161
services.AddScoped<ViewModels.AboutViewModel>();
6262
services.AddScoped<Views.Pages.DashboardPage>();
6363
services.AddScoped<ViewModels.DashboardViewModel>();
64+
services.AddScoped<Views.Pages.ExplorerPage>();
65+
services.AddScoped<ViewModels.ExplorerViewModel>();
6466
services.AddScoped<Views.Pages.SettingsPage>();
6567
services.AddScoped<ViewModels.SettingsViewModel>();
6668
services.AddScoped<Views.Pages.SyncPage>();
@@ -91,6 +93,8 @@ private async void OnStartup(object sender, StartupEventArgs e)
9193

9294
SetupUnhandledExceptionHandling();
9395

96+
DiagnosticLogger.Log($"Sdc {ApplicationManager.GetAssemblyVersion()} started...");
97+
9498
await _host.StartAsync();
9599
}
96100

@@ -99,6 +103,8 @@ private async void OnStartup(object sender, StartupEventArgs e)
99103
/// </summary>
100104
private async void OnExit(object sender, ExitEventArgs e)
101105
{
106+
DiagnosticLogger.Log($"Sdc {ApplicationManager.GetAssemblyVersion()} exited...");
107+
102108
// flush all log items before exit
103109
Log.CloseAndFlush();
104110

@@ -136,11 +142,20 @@ private static void ConfigureLogging()
136142
{
137143
// configure logging
138144
Log.Logger = new LoggerConfiguration()
139-
.WriteTo.File(Path.Combine(_logsPath, "Sdc-.log"),
140-
restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information,
145+
.MinimumLevel.Information()
146+
.Enrich.FromLogContext()
147+
.WriteTo.Logger(p => p
148+
.Filter.ByExcluding(p => p.Properties.ContainsKey("IsDiag"))
149+
.WriteTo.File(Path.Combine(_logsPath, "Sdc-.log"),
141150
outputTemplate: "{Timestamp:MM/dd/yyyy HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
142151
rollingInterval: RollingInterval.Day,
143-
retainedFileCountLimit: 7)
152+
retainedFileCountLimit: 7))
153+
.WriteTo.Logger(p => p
154+
.Filter.ByIncludingOnly(p => p.Properties.ContainsKey("IsDiag"))
155+
.WriteTo.File(Path.Combine(_logsPath, "Sdc-Diag-.log"),
156+
outputTemplate: "{Timestamp:MM/dd/yyyy HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}",
157+
rollingInterval: RollingInterval.Day,
158+
retainedFileCountLimit: 7))
144159
.CreateLogger();
145160
}
146161

AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// app, or any theme specific resource dictionaries)
1111
)]
1212

13-
[assembly: AssemblyVersion("0.2.*")]
13+
[assembly: AssemblyVersion("0.3.*")]
1414
[assembly: AssemblyTitle("Supernote Desktop Client")]
1515
[assembly: AssemblyProduct("Supernote Desktop Client")]
1616
[assembly: AssemblyCopyright("Copyright © nelinory 2023")]

Core/ApplicationManager.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
3+
namespace SupernoteDesktopClient.Core
4+
{
5+
public static class ApplicationManager
6+
{
7+
public static string GetAssemblyVersion()
8+
{
9+
Version versionObject = System.Reflection.Assembly.GetEntryAssembly().GetName().Version;
10+
11+
return $"v{versionObject.Major}.{versionObject.Minor}.{versionObject.Build}";
12+
}
13+
}
14+
}

Core/ArchiveManager.cs

Lines changed: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using Serilog;
2-
using System;
1+
using System;
32
using System.Collections.ObjectModel;
43
using System.IO;
54
using System.IO.Compression;
@@ -14,80 +13,59 @@ public static void Archive(string backupFolder, string archiveFolder, int maxArc
1413
string currentDateTime = String.Format("{0:yyyyMMdd_HHmmss}", DateTime.Now);
1514
string archiveFileName = $"{currentDateTime}_{Path.GetFileName(backupFolder)}.zip";
1615

17-
if (ExecuteArchive(backupFolder, Path.Combine(archiveFolder, archiveFileName)) == true)
16+
if (CreateArchive(backupFolder, Path.Combine(archiveFolder, archiveFileName)) == true)
1817
PurgeOldArchives(archiveFolder, Path.GetFileName(backupFolder), maxArchivesToKeep);
1918
}
2019

21-
public static ObservableCollection<Models.FileAttributes> GetArchivesList(string archiveFolder)
20+
public static ObservableCollection<Models.ArchiveFileAttributes> GetArchivesList(string archiveFolder)
2221
{
23-
ObservableCollection<Models.FileAttributes> archiveFiles = new ObservableCollection<Models.FileAttributes>();
22+
ObservableCollection<Models.ArchiveFileAttributes> archiveFiles = new ObservableCollection<Models.ArchiveFileAttributes>();
2423

25-
try
24+
if (String.IsNullOrWhiteSpace(archiveFolder) == false && Directory.Exists(archiveFolder) == true)
2625
{
27-
if (String.IsNullOrWhiteSpace(archiveFolder) == false && Directory.Exists(archiveFolder) == true)
26+
var directory = new DirectoryInfo(archiveFolder);
27+
foreach (FileInfo fileInfo in directory.GetFiles().OrderByDescending(p => p.CreationTime))
2828
{
29-
var directory = new DirectoryInfo(archiveFolder);
30-
foreach (FileInfo fileInfo in directory.GetFiles().OrderByDescending(p => p.CreationTime))
31-
{
32-
archiveFiles.Add(new Models.FileAttributes(fileInfo.Name, fileInfo.DirectoryName, fileInfo.LastWriteTime, fileInfo.Length));
33-
}
29+
archiveFiles.Add(new Models.ArchiveFileAttributes(fileInfo.Name, fileInfo.DirectoryName, fileInfo.LastWriteTime, fileInfo.Length));
3430
}
3531
}
36-
catch (Exception ex)
37-
{
38-
Log.Error("Error while getting list of all archives: {EX}", ex);
39-
}
4032

4133
return archiveFiles;
4234
}
4335

44-
private static bool ExecuteArchive(string backupFolder, string archiveFileName)
36+
private static bool CreateArchive(string backupFolder, string archiveFileName)
4537
{
4638
bool success = false;
4739

48-
try
40+
if (Directory.Exists(backupFolder) == true && Directory.GetFiles(backupFolder, "*", SearchOption.AllDirectories).Length > 0)
4941
{
50-
if (Directory.Exists(backupFolder) == true && Directory.GetFiles(backupFolder, "*", SearchOption.AllDirectories).Length > 0)
51-
{
52-
FileSystemManager.EnsureFolderExists(archiveFileName);
42+
FileSystemManager.EnsureFolderExists(archiveFileName);
5343

54-
ZipFile.CreateFromDirectory(backupFolder, archiveFileName, CompressionLevel.Fastest, false);
44+
ZipFile.CreateFromDirectory(backupFolder, archiveFileName, CompressionLevel.Fastest, false);
5545

56-
success = true;
57-
}
58-
}
59-
catch (Exception ex)
60-
{
61-
Log.Error("Error while executing archive: {EX}", ex);
46+
success = true;
6247
}
6348

6449
return success;
6550
}
6651

6752
private static void PurgeOldArchives(string archiveFolder, string archiveFilePattern, int maxArchivesToKeep)
6853
{
69-
try
54+
if (Directory.Exists(archiveFolder) == true)
7055
{
71-
if (Directory.Exists(archiveFolder) == true)
56+
string[] archiveFileNames = Directory.GetFiles(archiveFolder, $"*{archiveFilePattern}.zip");
57+
if (archiveFileNames.Length > maxArchivesToKeep)
7258
{
73-
string[] archiveFileNames = Directory.GetFiles(archiveFolder, $"*{archiveFilePattern}.zip");
74-
if (archiveFileNames.Length > maxArchivesToKeep)
75-
{
76-
Array.Sort(archiveFileNames, StringComparer.InvariantCulture);
59+
Array.Sort(archiveFileNames, StringComparer.InvariantCulture);
7760

78-
int filesToDelete = archiveFileNames.Length - maxArchivesToKeep;
79-
for (int i = 0; i < filesToDelete; i++)
80-
{
81-
if (File.Exists(archiveFileNames[i]) == true)
82-
File.Delete(archiveFileNames[i]);
83-
}
61+
int filesToDelete = archiveFileNames.Length - maxArchivesToKeep;
62+
for (int i = 0; i < filesToDelete; i++)
63+
{
64+
if (File.Exists(archiveFileNames[i]) == true)
65+
File.Delete(archiveFileNames[i]);
8466
}
8567
}
8668
}
87-
catch (Exception ex)
88-
{
89-
Log.Error("Error while purging old archives: {EX}", ex);
90-
}
9169
}
9270
}
9371
}

Core/DiagnosticLogger.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Serilog.Context;
2+
using System.Runtime.CompilerServices;
3+
4+
namespace SupernoteDesktopClient.Core
5+
{
6+
static class DiagnosticLogger
7+
{
8+
public static void Log(string messageTemplate, [CallerMemberName] string callerName = "", params object[] args)
9+
{
10+
if (SettingsManager.Instance.Settings.General.DiagnosticLogEnabled == true)
11+
{
12+
using (LogContext.PushProperty("IsDiag", 1))
13+
{
14+
Serilog.Log.Information($"Caller: {callerName} - " + messageTemplate, args);
15+
}
16+
}
17+
}
18+
}
19+
}

Core/Enums.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System;
2+
3+
namespace SupernoteDesktopClient.Core
4+
{
5+
public enum FileAttribute : uint
6+
{
7+
Directory = 16,
8+
File = 256
9+
}
10+
11+
public enum IconSize : short
12+
{
13+
Small,
14+
Large
15+
}
16+
17+
public enum ItemState : short
18+
{
19+
Undefined,
20+
Open,
21+
Close
22+
}
23+
24+
public enum ItemType
25+
{
26+
Drive,
27+
Folder,
28+
File
29+
}
30+
31+
[Flags]
32+
public enum ShellAttribute : uint
33+
{
34+
LargeIcon = 0, // 0x000000000
35+
SmallIcon = 1, // 0x000000001
36+
OpenIcon = 2, // 0x000000002
37+
ShellIconSize = 4, // 0x000000004
38+
Pidl = 8, // 0x000000008
39+
UseFileAttributes = 16, // 0x000000010
40+
AddOverlays = 32, // 0x000000020
41+
OverlayIndex = 64, // 0x000000040
42+
Others = 128,
43+
Icon = 256, // 0x000000100
44+
DisplayName = 512, // 0x000000200
45+
TypeName = 1024, // 0x000000400
46+
Attributes = 2048, // 0x000000800
47+
IconLocation = 4096, // 0x000001000
48+
ExeType = 8192, // 0x000002000
49+
SystemIconIndex = 16384, // 0x000004000
50+
LinkOverlay = 32768, // 0x000008000
51+
Selected = 65536, // 0x000010000
52+
AttributeSpecified = 131072 // 0x000020000
53+
}
54+
}

Core/FileSystemManager.cs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,20 @@
1-
using Serilog;
2-
using System;
1+
using System;
32
using System.IO;
4-
using System.Reflection;
53

64
namespace SupernoteDesktopClient.Core
75
{
86
public static class FileSystemManager
97
{
108
public static void ForceDeleteDirectory(string path)
119
{
12-
try
13-
{
14-
var directory = new DirectoryInfo(path) { Attributes = FileAttributes.Normal };
15-
16-
foreach (var info in directory.GetFileSystemInfos("*", SearchOption.AllDirectories))
17-
{
18-
info.Attributes = FileAttributes.Normal;
19-
}
10+
var directory = new DirectoryInfo(path) { Attributes = FileAttributes.Normal };
2011

21-
directory.Delete(true);
22-
}
23-
catch (Exception ex)
12+
foreach (var info in directory.GetFileSystemInfos("*", SearchOption.AllDirectories))
2413
{
25-
Log.Error("Error while deleting directory: {EX}", ex);
14+
info.Attributes = FileAttributes.Normal;
2615
}
16+
17+
directory.Delete(true);
2718
}
2819

2920
public static void EnsureFolderExists(string fileName)
@@ -36,7 +27,12 @@ public static void EnsureFolderExists(string fileName)
3627

3728
public static string GetApplicationFolder()
3829
{
39-
return Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location);
30+
return AppDomain.CurrentDomain.BaseDirectory;
31+
}
32+
33+
public static string GetApplicationDeviceFolder()
34+
{
35+
return Path.Combine(GetApplicationFolder(), @"Device");
4036
}
4137

4238
public static DateTime? GetFolderCreateDateTime(string folder)

Core/ImageManager.cs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using SupernoteDesktopClient.Core.Win32Api;
2+
using System.Collections.Generic;
3+
using System.Drawing;
4+
using System.IO;
5+
using System.Windows.Interop;
6+
using System.Windows.Media;
7+
using System.Windows.Media.Imaging;
8+
9+
namespace SupernoteDesktopClient.Core
10+
{
11+
public static class ImageManager
12+
{
13+
private static object _syncObject = new object();
14+
private static Dictionary<string, ImageSource> _imageSourceCache = new Dictionary<string, ImageSource>();
15+
16+
public static ImageSource GetImageSource(string filename)
17+
{
18+
return GetImageSourceFromCache(filename, new Size(24, 24), ItemType.File, ItemState.Undefined);
19+
}
20+
21+
public static ImageSource GetImageSource(string directory, ItemState folderType)
22+
{
23+
return GetImageSourceFromCache(directory, new Size(24, 24), ItemType.Folder, folderType);
24+
}
25+
26+
private static ImageSource GetFileImageSource(string filename, Size size)
27+
{
28+
using (var icon = NativeMethods.GetIcon(Path.GetExtension(filename), ItemType.File, IconSize.Large, ItemState.Undefined))
29+
{
30+
return Imaging.CreateBitmapSourceFromHIcon(icon.Handle,
31+
System.Windows.Int32Rect.Empty,
32+
BitmapSizeOptions.FromWidthAndHeight(size.Width, size.Height));
33+
}
34+
}
35+
36+
private static ImageSource GetDirectoryImageSource(string directory, Size size, ItemState folderType)
37+
{
38+
using (var icon = NativeMethods.GetIcon(directory, ItemType.Folder, IconSize.Large, folderType))
39+
{
40+
return Imaging.CreateBitmapSourceFromHIcon(icon.Handle,
41+
System.Windows.Int32Rect.Empty,
42+
BitmapSizeOptions.FromWidthAndHeight(size.Width, size.Height));
43+
}
44+
}
45+
46+
private static ImageSource GetImageSourceFromCache(string itemName, Size itemSize, ItemType itemType, ItemState itemState)
47+
{
48+
string cacheKey = $"{(itemType is ItemType.Folder ? ItemType.Folder : Path.GetExtension(itemName))}#{itemSize.Width}#{itemSize.Height}";
49+
50+
ImageSource returnValue;
51+
_imageSourceCache.TryGetValue(cacheKey, out returnValue);
52+
53+
if (returnValue == null)
54+
{
55+
lock (_syncObject)
56+
{
57+
_imageSourceCache.TryGetValue(cacheKey, out returnValue);
58+
59+
if (returnValue == null)
60+
{
61+
if (itemType is ItemType.Folder)
62+
returnValue = GetDirectoryImageSource(itemName, itemSize, itemState);
63+
else
64+
returnValue = GetFileImageSource(itemName, itemSize);
65+
66+
if (returnValue != null)
67+
_imageSourceCache.Add(cacheKey, returnValue);
68+
}
69+
}
70+
}
71+
72+
return returnValue;
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)