Improved settings
This commit is contained in:
parent
2fa5170f28
commit
95ae8335a1
36 changed files with 1755 additions and 805 deletions
|
|
@ -4,6 +4,8 @@ using System.ComponentModel;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using Dinah.Core;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace FileManager
|
||||
{
|
||||
|
|
@ -31,12 +33,18 @@ namespace FileManager
|
|||
*/
|
||||
#endregion
|
||||
|
||||
private PersistentDictionary persistentDictionary { get; }
|
||||
private PersistentDictionary persistentDictionary;
|
||||
|
||||
[Description("Location of the configuration file where these settings are saved. Please do not edit this file directly while Libation is running.")]
|
||||
public string Filepath => Path.Combine(Path.GetDirectoryName(Exe.FileLocationOnDisk), "Settings.json");
|
||||
public bool IsComplete
|
||||
=> File.Exists(APPSETTINGS_JSON)
|
||||
&& Directory.Exists(LibationFiles)
|
||||
&& Directory.Exists(Books)
|
||||
&& File.Exists(SettingsJsonPath)
|
||||
&& !string.IsNullOrWhiteSpace(LocaleCountryCode)
|
||||
&& !string.IsNullOrWhiteSpace(DownloadsInProgressEnum)
|
||||
&& !string.IsNullOrWhiteSpace(DecryptInProgressEnum);
|
||||
|
||||
[Description("[Advanced. Leave alone in most cases.] Your user-specific key used to decrypt your audible files (*.aax) into audio files you can use anywhere (*.m4b)")]
|
||||
[Description("Your user-specific key used to decrypt your audible files (*.aax) into audio files you can use anywhere (*.m4b). Leave alone in most cases")]
|
||||
public string DecryptKey
|
||||
{
|
||||
get => persistentDictionary[nameof(DecryptKey)];
|
||||
|
|
@ -50,17 +58,21 @@ namespace FileManager
|
|||
set => persistentDictionary[nameof(Books)] = value;
|
||||
}
|
||||
|
||||
public string WinTemp { get; } = Path.Combine(Path.GetTempPath(), "Libation");
|
||||
public static string AppDir { get; } = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Exe.FileLocationOnDisk), LIBATION_FILES));
|
||||
public static string MyDocs { get; } = Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), LIBATION_FILES));
|
||||
public static string WinTemp { get; } = Path.GetFullPath(Path.Combine(Path.GetTempPath(), "Libation"));
|
||||
|
||||
[Description("Location for storage of program-created files")]
|
||||
public string LibationFiles
|
||||
private Dictionary<string, string> wellKnownPaths { get; } = new Dictionary<string, string>
|
||||
{
|
||||
get => persistentDictionary[nameof(LibationFiles)];
|
||||
set => persistentDictionary[nameof(LibationFiles)] = value;
|
||||
}
|
||||
["AppDir"] = AppDir,
|
||||
["MyDocs"] = MyDocs,
|
||||
["WinTemp"] = WinTemp
|
||||
};
|
||||
private Dictionary<string, string> cache { get; } = new Dictionary<string, string>();
|
||||
|
||||
// default setting and directory creation occur in class responsible for files.
|
||||
// config class is only responsible for path. not responsible for setting defaults, dir validation, or dir creation
|
||||
// exceptions: appsettings.json, LibationFiles dir, Settings.json
|
||||
|
||||
// temp/working dir(s) should be outside of dropbox
|
||||
[Description("Temporary location of files while they're in process of being downloaded.\r\nWhen download is complete, the final file will be in [LibationFiles]\\DownloadsFinal")]
|
||||
|
|
@ -78,49 +90,114 @@ namespace FileManager
|
|||
set => persistentDictionary[nameof(DecryptInProgressEnum)] = value;
|
||||
}
|
||||
|
||||
public string LocaleCountryCode
|
||||
{
|
||||
get => persistentDictionary[nameof(LocaleCountryCode)];
|
||||
set => persistentDictionary[nameof(LocaleCountryCode)] = value;
|
||||
}
|
||||
public string LocaleCountryCode
|
||||
{
|
||||
get => persistentDictionary[nameof(LocaleCountryCode)];
|
||||
set => persistentDictionary[nameof(LocaleCountryCode)] = value;
|
||||
}
|
||||
|
||||
// note: any potential file manager static ctors can't compensate if storage dir is changed at run time via settings. this is partly bad architecture. but the side effect is desirable. if changing LibationFiles location: restart app
|
||||
|
||||
// singleton stuff
|
||||
public static Configuration Instance { get; } = new Configuration();
|
||||
private Configuration()
|
||||
{
|
||||
// load json values into memory
|
||||
persistentDictionary = new PersistentDictionary(Filepath);
|
||||
ensureDictionaryEntries();
|
||||
private Configuration() { }
|
||||
|
||||
// don't create dir. dir creation is the responsibility of places that use the dir
|
||||
if (string.IsNullOrWhiteSpace(LibationFiles))
|
||||
LibationFiles = Path.Combine(Path.GetDirectoryName(Exe.FileLocationOnDisk), "Libation");
|
||||
private const string APPSETTINGS_JSON = "appsettings.json";
|
||||
private const string LIBATION_FILES = "LibationFiles";
|
||||
|
||||
[Description("Location for storage of program-created files")]
|
||||
public string LibationFiles
|
||||
=> cache.ContainsKey(LIBATION_FILES)
|
||||
? cache[LIBATION_FILES]
|
||||
: getLibationFiles();
|
||||
private string getLibationFiles()
|
||||
{
|
||||
var value = getLiberationFilesSettingFromJson();
|
||||
|
||||
if (wellKnownPaths.ContainsKey(value))
|
||||
value = wellKnownPaths[value];
|
||||
|
||||
// must write here before SettingsJsonPath in next step tries to read from dictionary
|
||||
cache[LIBATION_FILES] = value;
|
||||
|
||||
// load json values into memory. create if not exists
|
||||
persistentDictionary = new PersistentDictionary(SettingsJsonPath);
|
||||
persistentDictionary.EnsureEntries<Configuration>();
|
||||
|
||||
return value;
|
||||
}
|
||||
private string getLiberationFilesSettingFromJson()
|
||||
{
|
||||
static string createSettingsJson()
|
||||
{
|
||||
var dir = "AppDir";
|
||||
File.WriteAllText(APPSETTINGS_JSON, new JObject { { LIBATION_FILES, dir } }.ToString(Formatting.Indented));
|
||||
return dir;
|
||||
}
|
||||
|
||||
if (!File.Exists(APPSETTINGS_JSON))
|
||||
return createSettingsJson();
|
||||
|
||||
var appSettingsContents = File.ReadAllText(APPSETTINGS_JSON);
|
||||
|
||||
JObject jObj;
|
||||
try
|
||||
{
|
||||
jObj = JObject.Parse(appSettingsContents);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return createSettingsJson();
|
||||
}
|
||||
|
||||
if (!jObj.ContainsKey(LIBATION_FILES))
|
||||
return createSettingsJson();
|
||||
|
||||
var value = jObj[LIBATION_FILES].Value<string>();
|
||||
return value;
|
||||
}
|
||||
|
||||
private string SettingsJsonPath => Path.Combine(LibationFiles, "Settings.json");
|
||||
|
||||
public static string GetDescription(string propertyName)
|
||||
{
|
||||
var attribute = typeof(Configuration)
|
||||
.GetProperty(propertyName)
|
||||
?.GetCustomAttributes(typeof(DescriptionAttribute), true)
|
||||
.SingleOrDefault()
|
||||
as DescriptionAttribute;
|
||||
var attribute = typeof(Configuration)
|
||||
.GetProperty(propertyName)
|
||||
?.GetCustomAttributes(typeof(DescriptionAttribute), true)
|
||||
.SingleOrDefault()
|
||||
as DescriptionAttribute;
|
||||
|
||||
return attribute?.Description;
|
||||
}
|
||||
|
||||
private void ensureDictionaryEntries()
|
||||
{
|
||||
var stringProperties = getDictionaryProperties().Select(p => p.Name).ToList();
|
||||
var missingKeys = stringProperties.Except(persistentDictionary.Keys).ToArray();
|
||||
persistentDictionary.AddKeys(missingKeys);
|
||||
return attribute?.Description;
|
||||
}
|
||||
|
||||
private IEnumerable<System.Reflection.PropertyInfo> dicPropertiesCache;
|
||||
private IEnumerable<System.Reflection.PropertyInfo> getDictionaryProperties()
|
||||
public bool TrySetLibationFiles(string directory)
|
||||
{
|
||||
if (dicPropertiesCache == null)
|
||||
dicPropertiesCache = PersistentDictionary.GetPropertiesToPersist(this.GetType());
|
||||
return dicPropertiesCache;
|
||||
if (!Directory.Exists(directory) && !wellKnownPaths.ContainsKey(directory))
|
||||
return false;
|
||||
|
||||
// if moving from default, delete old settings file and dir (if empty)
|
||||
if (LibationFiles.EqualsInsensitive(AppDir))
|
||||
{
|
||||
File.Delete(SettingsJsonPath);
|
||||
System.Threading.Thread.Sleep(100);
|
||||
if (!Directory.EnumerateDirectories(AppDir).Any() && !Directory.EnumerateFiles(AppDir).Any())
|
||||
Directory.Delete(AppDir);
|
||||
}
|
||||
|
||||
|
||||
cache.Remove(LIBATION_FILES);
|
||||
|
||||
|
||||
var contents = File.ReadAllText(APPSETTINGS_JSON);
|
||||
var jObj = JObject.Parse(contents);
|
||||
|
||||
jObj[LIBATION_FILES] = directory;
|
||||
|
||||
var output = JsonConvert.SerializeObject(jObj, Formatting.Indented);
|
||||
File.WriteAllText(APPSETTINGS_JSON, output);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue