diff --git a/Assets/screenshot.png b/Assets/screenshot.png index b5c954a..470e74b 100644 Binary files a/Assets/screenshot.png and b/Assets/screenshot.png differ diff --git a/Helper Applications/PDF2J/PDF2J.csproj b/Helper Applications/PDF2J/PDF2J.csproj index a8066c0..5e130db 100644 --- a/Helper Applications/PDF2J/PDF2J.csproj +++ b/Helper Applications/PDF2J/PDF2J.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/Helper Applications/TouchDeviceManager/Touch Device Manager.csproj b/Helper Applications/TouchDeviceManager/Touch Device Manager.csproj index ab6d8c0..592982d 100644 --- a/Helper Applications/TouchDeviceManager/Touch Device Manager.csproj +++ b/Helper Applications/TouchDeviceManager/Touch Device Manager.csproj @@ -32,7 +32,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + all diff --git a/README.md b/README.md index c9f3a83..562ab62 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ # SimpleJournal -![Lines Of Code](https://tokei.rs/b1/github/andyld97/SimpleJournal) ![GitHub](https://img.shields.io/github/license/andyld97/SimpleJournal) ![GitHub issues](https://img.shields.io/github/issues/andyld97/SimpleJournal) ![GitHub all releases](https://img.shields.io/github/downloads/andyld97/SimpleJournal/total) @@ -11,7 +10,7 @@ ## Welcome -Welcome to the offical GitHub-Repo of SimpleJournal. SimpleJournal is a simple tool similar to OneNote or Windows Journal. The idea came from my best friend (Daniel S.) a few years ago ([see more details](https://simplejournal.ca-soft.net/en/about)) and since then SimpleJournal has evolved to a useful App which is also available in the Micorosft Store! +Welcome to the offical GitHub-Repo of SimpleJournal. SimpleJournal is a simple tool similar to OneNote or Windows Journal. The idea came from my best friend (Daniel S.) in 2018 ([see more details](https://simplejournal.ca-soft.net/en/about)) and since then SimpleJournal has evolved to a useful App which is also available in the Micorosft Store! English badge @@ -20,8 +19,16 @@ Welcome to the offical GitHub-Repo of SimpleJournal. SimpleJournal is a simple t ## Info -There are two versions of SimpleJournal due to compability issues, e.g. like supporting older versions of Windows. So we have the `normal version` which is running also on Windows 7 and the `store version`. If you want to download the non-store version [click here.](https://simplejournal.ca-soft.net/en/download) -Due to store-restrictions both versions are different: The normal version supports more features than the other, so therefore there are different builds: `UWP` and `Normal`. As you might have noticed that SimpleJournal is written in `WPF` (`.NET 8`), the Store-Version is not a real UWP-App. It is converted with the `Desktop Bridge` (`MSIX Packaging Tool`) +There are two versions of **SimpleJournal**, mainly due to compatibility requirements (for example, support for older Windows versions). + +- **Normal version** – runs on Windows 7 and later +- **Store version** – distributed via the Microsoft Store + +If you want to download the non-Store version, [click here](https://simplejournal.ca-soft.net/en/download). + +Because of Microsoft Store restrictions, the two versions differ in functionality. The **Normal version** supports more features, which is why there are two distinct builds: `Normal` and `UWP`. + +Although SimpleJournal is written in **WPF** (`.NET 10`), the Store version is **not** a native UWP application. It is packaged using the **Desktop Bridge** via the **MSIX Packaging Tool**. ### Features & Version Matrix @@ -40,11 +47,14 @@ Due to store-restrictions both versions are different: The normal version suppor - (*2) For PDF Support (since `v05.0.2`) it is required to install `Ghostscript` (see `PDF Support`) ## What is `Disable Touch` -This is a small solution making SimpleJournal more usable on devices which support touch input (not only pen input). A page in SimpleJournal is based on the WPF `InkCanvas` which doesn't makes a difference according to the input source, so if you'll write via mouse, touch or pen this control cannot distinguish which input you have used respectively I wasn't able to differentiate it in the control (the newer `InkCanvas` from UWP Framework can do this). The problem is if you are writing with a pen while you put down your hand on your touch screen, both inputs are recognized and drawn and that leads to annoying results. -To prevent this I came up with a soultion which completely disables your touch screen based on `devcon`. This works the same way as your device manager do, as if you click on `Disable Device`. This is implemented as an option in the settings and it's not activated in the default settings. To enhance the usability your touch screen will be deactivated on the startup of SimpleJournal and will be reactivated if you close the last instance of SimpleJournal. +This is a small solution that makes SimpleJournal more usable on devices that support touch input (not only pen input). A page in SimpleJournal is based on the WPF `InkCanvas`, which does not differentiate between input sources. Whether you write using a mouse, touch, or pen, the control treats all inputs the same. I was not able to reliably distinguish the input source within WPF’s `InkCanvas` (the newer `InkCanvas` in the UWP framework can do this). + +The problem occurs when you write with a pen while resting your hand on a touch screen: both inputs are detected and rendered, resulting in unwanted strokes. + +To prevent this, I implemented a solution that completely disables touch input using `devcon`. This works the same way as disabling a device via the Windows Device Manager. The feature is available as a settings option and is disabled by default. When enabled, the touch screen is deactivated on SimpleJournal startup and automatically reactivated when the last running instance of SimpleJournal is closed. + +For the non-Store version, I also provide a small [tool](https://simplejournal.ca-soft.net/download.php?tdm=1) that allows you to manually enable or disable the touch screen. This feature is only integrated into the non-Store version because it requires administrator privileges, and currently there is no supported way to request elevated privileges from a Microsoft Store app. -For the non-store version I created a simple [tool](https://simplejournal.ca-soft.net/download.php?tdm=1) which you can use for en/disabling your touch screen. -The reason why this feature is only integrated in the non-store version is, that this feature requires administrator privileges and currently I don't know how to aquire administrator privileges in the Store app! ## PDF Support ### Requirements @@ -57,7 +67,7 @@ In order to support pdf files SimpleJournal creates a journal out of the given p Converting large pdf files takes some time and require much computing power, so for low-end systems there is `PDF2J`. It's an ASP.NET-Core project with a little ticket managment system and the ability to convert the pdf file to a compatible journal. Of course it's also integrated into SimpleJournal (default host: http://cas-server2.ddns.net:8080) so you can also use this API. Don't worry after it's finished converting your document, your document (ticket) will be deleted! But anyways for advanced users there is also a possiblity to host this api on your own on Windows or Linux! (but remember that Ghostscript must be installed on that server too!) ### Limit: 100 Pages per document -Either using SimpleJournal itself or the converter api there is a limit of 100 pages per document. For large documents (`> 100 pages`) multiple journals gets created. This limition is to reduce the amount of memory the programm uses when displaying large documents. +Either using SimpleJournal itself or the converter api: There is a limit of 100 pages per document. For large documents (`> 100 pages`) multiple journals will be created. This limition is to reduce the amount of memory the programm uses when displaying large documents. To simplify the workflow regarding large PDF-documents, you can navigate between these documents. At the top you can load the previous document (if available) and at the bottom you can load the next document (if available). This can also be disabeld in the settings dialog. ## Build @@ -66,4 +76,4 @@ In order to work with form or text-recognition you need to compile `Analyzer` an ## Thanks to - Daniel S. for the great ideas and testing! - Stefan E. for the great ideas and testing! -- Elmo for the dutch translation! +- Elmo for the dutch translation! \ No newline at end of file diff --git a/Shared Libraries/SimpleJournal.Common/SimpleJournal.Common.csproj b/Shared Libraries/SimpleJournal.Common/SimpleJournal.Common.csproj index 63123a2..f443cc6 100644 --- a/Shared Libraries/SimpleJournal.Common/SimpleJournal.Common.csproj +++ b/Shared Libraries/SimpleJournal.Common/SimpleJournal.Common.csproj @@ -30,6 +30,6 @@ all - + \ No newline at end of file diff --git a/Shared Libraries/SimpleJournal.Common/Strings.cs b/Shared Libraries/SimpleJournal.Common/Strings.cs index 762d50b..c79090d 100644 --- a/Shared Libraries/SimpleJournal.Common/Strings.cs +++ b/Shared Libraries/SimpleJournal.Common/Strings.cs @@ -4,12 +4,12 @@ namespace SimpleJournal.Common { public static class Strings { - public const string Version = "0.7.0.0"; - public const string StoreVersion = "1.700.0.0"; + public const string Version = "0.7.1.0"; + public const string StoreVersion = "1.710.0.0"; public const string Copyright = "Copyright © 2018-2025"; #if UWPNEW || NORMAL - public static readonly DateTime ReleaseDate = new DateTime(2025, 11, 15, 12, 0, 0); + public static readonly DateTime ReleaseDate = new DateTime(2025, 12, 27, 12, 0, 0); #else public static readonly DateTime ReleaseDate = DateTime.Now; #endif diff --git a/Shared Libraries/SimpleJournal.Documents.PDF/SimpleJournal.Documents.PDF.csproj b/Shared Libraries/SimpleJournal.Documents.PDF/SimpleJournal.Documents.PDF.csproj index 23696b0..ca4f4fe 100644 --- a/Shared Libraries/SimpleJournal.Documents.PDF/SimpleJournal.Documents.PDF.csproj +++ b/Shared Libraries/SimpleJournal.Documents.PDF/SimpleJournal.Documents.PDF.csproj @@ -25,8 +25,8 @@ - - + + diff --git a/Shared Libraries/SimpleJournal.Documents/Journal.cs b/Shared Libraries/SimpleJournal.Documents/Journal.cs index e5c2a37..94c6ce8 100644 --- a/Shared Libraries/SimpleJournal.Documents/Journal.cs +++ b/Shared Libraries/SimpleJournal.Documents/Journal.cs @@ -1,8 +1,8 @@ using SimpleJournal.Common; -using System.ComponentModel; -using System.Xml.Serialization; using SimpleJournal.Common.Helper; using SimpleJournal.Documents.Pattern; +using System.ComponentModel; +using System.Xml.Serialization; namespace SimpleJournal.Documents { @@ -73,16 +73,12 @@ public static async Task LoadJournalMetaAsync(string path) try { - using (System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.Open)) - { - using (System.IO.Compression.ZipArchive zipArchive = new System.IO.Compression.ZipArchive(fs, System.IO.Compression.ZipArchiveMode.Read, false)) - { - var entry = zipArchive.GetEntry("journal.xml"); - var data = await entry.ReadZipEntryAsync(); + using System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.Open); + using System.IO.Compression.ZipArchive zipArchive = new System.IO.Compression.ZipArchive(fs, System.IO.Compression.ZipArchiveMode.Read, false); + var entry = zipArchive.GetEntry("journal.xml"); + var data = await entry.ReadZipEntryAsync(); - return Serialization.ReadBytes(data, Serialization.Mode.XML); - } - } + return Serialization.ReadBytes(data, Serialization.Mode.XML); } catch { @@ -99,7 +95,7 @@ public static async Task LoadJournalMetaAsync(string path) /// The directory where old documents will be stored /// If true, no error message is shown /// - public static async Task LoadJournalAsync(string path, string backupDirectory, bool quiet = false) + public static async Task LoadJournalAsync(string path, string backupDirectory, bool quiet = false) { try { @@ -134,102 +130,106 @@ public static async Task LoadJournalAsync(string path, string backupDir var result = Serialization.ReadString(xmlData, System.Text.Encoding.UTF8); if (result != null) - return result; + return new JournalLoadResult() { Journal = result, State = LoadState.Success }; } else { // ... otherwise load it as a zip file bool fail = false; - using (System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.Open)) + using System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.Open); + using System.IO.Compression.ZipArchive zipArchive = new System.IO.Compression.ZipArchive(fs, System.IO.Compression.ZipArchiveMode.Read, false); + Dictionary journalPages = []; + Dictionary pdfJournalPages = []; + Dictionary images = []; + Journal journal = new Journal(); + + bool isOldBinaryJournal = zipArchive.Entries.Any(e => e.Name == "info.bin"); + + if (isOldBinaryJournal) + return new JournalLoadResult(LoadState.IncompatibleVersion); + + foreach (var currentEntry in zipArchive.Entries) { - using (System.IO.Compression.ZipArchive zipArchive = new System.IO.Compression.ZipArchive(fs, System.IO.Compression.ZipArchiveMode.Read, false)) - { - Dictionary journalPages = new Dictionary(); - Dictionary pdfJournalPages = new Dictionary(); - Dictionary images = new Dictionary(); - Journal journal = new Journal(); + byte[] data = await currentEntry.ReadZipEntryAsync(); + string pageNumber = currentEntry.Name.Replace("page", string.Empty).Replace(".png", string.Empty).Replace(".pdf", string.Empty).Replace(".xml", string.Empty); - foreach (var currentEntry in zipArchive.Entries) + if (currentEntry.Name == "journal.xml") + { + string xmlData = System.Text.Encoding.UTF8.GetString(data); + // Correct old documents misspelled pattern! + xmlData = xmlData.Replace("Chequeued", "Chequered"); + journal = Serialization.ReadString(xmlData, System.Text.Encoding.UTF8); + } + else if (int.TryParse(pageNumber, out int page)) + { + if (currentEntry.Name.EndsWith(".png")) { - byte[] data = await currentEntry.ReadZipEntryAsync(); - string pageNumber = currentEntry.Name.Replace("page", string.Empty).Replace(".png", string.Empty).Replace(".pdf", string.Empty).Replace(".xml", string.Empty); - - if (currentEntry.Name == "journal.xml") - { - string xmlData = System.Text.Encoding.UTF8.GetString(data); - // Correct old documents misspelled pattern! - xmlData = xmlData.Replace("Chequeued", "Chequered"); - journal = Serialization.ReadString(xmlData, System.Text.Encoding.UTF8); - } - else if (int.TryParse(pageNumber, out int page)) - { - if (currentEntry.Name.EndsWith(".png")) - { - // image for pdf page - images.Add(page, data); - } - else if (currentEntry.Name.EndsWith(".pdf")) - { - // pdf page - pdfJournalPages.Add(page, Serialization.ReadBytes(data, Serialization.Mode.XML)); - } - else if (currentEntry.Name.EndsWith(".xml")) - { - // normal page - string xmlData = System.Text.Encoding.UTF8.GetString(data); - - // Correct old documents misspelled pattern! - xmlData = xmlData.Replace("Chequeued", "Chequered"); - journalPages.Add(page, Serialization.ReadString(xmlData, System.Text.Encoding.UTF8)); - } - } - else - { - fail = true; - break; - } + // image for pdf page + images.Add(page, data); } - - if (fail) - throw new ArgumentException("pageParser failed"); - - // Merge dictionaries - // Step 1) Add images to PdFJournalPages (if any) - foreach (var image in images.Keys) + else if (currentEntry.Name.EndsWith(".pdf")) { - var currentPage = pdfJournalPages[image]; - currentPage.PageBackground = images[image]; + // pdf page + pdfJournalPages.Add(page, Serialization.ReadBytes(data, Serialization.Mode.XML)); } - - // Step 2) Merge pages in the correct order (huh?) - int oldCount = journalPages.Count + pdfJournalPages.Count; - int count = 0; - journal.Pages.Clear(); - for (int i = 0; i < oldCount; i++) + else if (currentEntry.Name.EndsWith(".xml")) { - if (pdfJournalPages.ContainsKey(i)) - journal.Pages.Add(pdfJournalPages[i]); - else if (journalPages.ContainsKey(i)) - journal.Pages.Add(journalPages[i]); + // normal page + string xmlData = System.Text.Encoding.UTF8.GetString(data); - count++; + // Correct old documents misspelled pattern! + xmlData = xmlData.Replace("Chequeued", "Chequered"); + journalPages.Add(page, Serialization.ReadString(xmlData, System.Text.Encoding.UTF8)); } + } + else + { + fail = true; + break; + } + } - if (oldCount != count) - throw new Exception("Invalid or corrupt file, cannot load data!"); + if (fail) + return new JournalLoadResult(LoadState.UnsupportedVersionOrCorrupt); - return journal; - } + // Merge dictionaries + // Step 1) Add images to PdFJournalPages (if any) + foreach (var image in images.Keys) + { + var currentPage = pdfJournalPages[image]; + currentPage.PageBackground = images[image]; } + + // Step 2) Merge pages in the correct order (huh?) + int oldCount = journalPages.Count + pdfJournalPages.Count; + int count = 0; + journal.Pages.Clear(); + for (int i = 0; i < oldCount; i++) + { + if (pdfJournalPages.TryGetValue(i, out PdfJournalPage? value)) + journal.Pages.Add(value); + else if (journalPages.TryGetValue(i, out JournalPage? value1)) + journal.Pages.Add(value1); + + count++; + } + + if (oldCount != count) + return new JournalLoadResult(LoadState.InvalidOrCorruptFile); + + return new JournalLoadResult(journal, LoadState.Success); } } catch (Exception e) { if (!quiet) + { OnErrorOccurred?.Invoke(e.Message, "load"); + return new JournalLoadResult(LoadState.UnknownError) { SupressErrorMessage = true, ErrorMessage = e.Message }; + } } - return null; + return new JournalLoadResult(LoadState.InvalidOrCorruptFile); } public async Task UpdateJournalMetaAsync(string filePath, bool forceUpdate) @@ -241,39 +241,35 @@ public async Task UpdateJournalMetaAsync(string filePath, bool forceUpdate try { // Update Journal - using (System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open)) - { - using (System.IO.Compression.ZipArchive zipArchive = new System.IO.Compression.ZipArchive(fs, System.IO.Compression.ZipArchiveMode.Update, false)) - { - var entry = zipArchive.GetEntry("journal.xml"); + using System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open); + using System.IO.Compression.ZipArchive zipArchive = new System.IO.Compression.ZipArchive(fs, System.IO.Compression.ZipArchiveMode.Update, false); + var entry = zipArchive.GetEntry("journal.xml"); - // Delete entry first to prevent that no old content will stay there! - if (entry != null) - entry.Delete(); - - entry = zipArchive.CreateEntry("journal.xml"); - - using var stream = entry.Open(); - var jrn = new Journal() - { - ProcessID = this.ProcessID, - IsBackup = this.IsBackup, - OriginalPath = this.OriginalPath, - PreviousDocumentIndex = this.PreviousDocumentIndex, - NextDocumentIndex = this.NextDocumentIndex, - ChequeredPattern = (ChequeredPattern)this.ChequeredPattern?.Clone(), - DottedPattern = (DottedPattern)this.DottedPattern?.Clone(), - RuledPattern = (RuledPattern)this.RuledPattern?.Clone(), - }; + // Delete entry first to prevent that no old content will stay there! + if (entry != null) + entry.Delete(); - // This is just for counting the pages - foreach (var page in Pages) - jrn.Pages.Add(new JournalPage()); + entry = zipArchive.CreateEntry("journal.xml"); - var data = Serialization.SaveToBytes(jrn, Serialization.Mode.XML); - await stream.WriteAsync(data, 0, data.Length); - } - } + using var stream = entry.Open(); + var jrn = new Journal() + { + ProcessID = this.ProcessID, + IsBackup = this.IsBackup, + OriginalPath = this.OriginalPath, + PreviousDocumentIndex = this.PreviousDocumentIndex, + NextDocumentIndex = this.NextDocumentIndex, + ChequeredPattern = (ChequeredPattern)this.ChequeredPattern?.Clone(), + DottedPattern = (DottedPattern)this.DottedPattern?.Clone(), + RuledPattern = (RuledPattern)this.RuledPattern?.Clone(), + }; + + // This is just for counting the pages + foreach (var page in Pages) + jrn.Pages.Add(new JournalPage()); + + var data = Serialization.SaveToBytes(jrn, Serialization.Mode.XML); + await stream.WriteAsync(data); return true; } @@ -311,75 +307,71 @@ public async Task SaveAsync(string filePath, bool quiet = false, bool hide using (System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Create)) { // or update - using (System.IO.Compression.ZipArchive zipArchive = new System.IO.Compression.ZipArchive(fs, System.IO.Compression.ZipArchiveMode.Create, false)) + using System.IO.Compression.ZipArchive zipArchive = new System.IO.Compression.ZipArchive(fs, System.IO.Compression.ZipArchiveMode.Create, false); + int pgCount = 0; + foreach (var page in Pages) { - int pgCount = 0; - foreach (var page in Pages) + if (page is PdfJournalPage pdf) { - if (page is PdfJournalPage pdf) + var pageEntry = zipArchive.CreateEntry($"pages/page{pgCount}.pdf", System.IO.Compression.CompressionLevel.Optimal); + + // Background will be saved separately + PdfJournalPage pdfJournalPage = new PdfJournalPage { - var pageEntry = zipArchive.CreateEntry($"pages/page{pgCount}.pdf", System.IO.Compression.CompressionLevel.Optimal); - - // Background will be saved separately - PdfJournalPage pdfJournalPage = new PdfJournalPage - { - Data = pdf.Data, - JournalResources = pdf.JournalResources, - Orientation = pdf.Orientation, - PageFormat = pdf.PageFormat, - PaperPattern = pdf.PaperPattern, - PageBackground = null - }; - - using (System.IO.Stream stream = pageEntry.Open()) - { - var data = Serialization.SaveToBytes(pdfJournalPage, Serialization.Mode.XML); - await stream.WriteAsync(data, 0, data.Length); - } - - // Save background - var imgEntry = zipArchive.CreateEntry($"pages/page{pgCount}.png", System.IO.Compression.CompressionLevel.Optimal); - using (System.IO.Stream stream = imgEntry.Open()) - { - await stream.WriteAsync(pdf.PageBackground, 0, pdf.PageBackground.Length); - } - } - else + Data = pdf.Data, + JournalResources = pdf.JournalResources, + Orientation = pdf.Orientation, + PageFormat = pdf.PageFormat, + PaperPattern = pdf.PaperPattern, + PageBackground = null + }; + + using (System.IO.Stream stream = pageEntry.Open()) { - var pageEntry = zipArchive.CreateEntry($"pages/page{pgCount}.xml", System.IO.Compression.CompressionLevel.Optimal); - using (System.IO.Stream stream = pageEntry.Open()) - { - var data = Serialization.SaveToBytes(page, Serialization.Mode.XML); - await stream.WriteAsync(data, 0, data.Length); - } + var data = Serialization.SaveToBytes(pdfJournalPage, Serialization.Mode.XML); + await stream.WriteAsync(data); } - pgCount++; + // Save background + var imgEntry = zipArchive.CreateEntry($"pages/page{pgCount}.png", System.IO.Compression.CompressionLevel.Optimal); + using (System.IO.Stream stream = imgEntry.Open()) + { + await stream.WriteAsync(pdf.PageBackground.AsMemory(0, pdf.PageBackground.Length)); + } } - - // Write journal infos - var info = zipArchive.CreateEntry("journal.xml"); - using (System.IO.Stream stream = info.Open()) + else { - var jrn = new Journal() - { - ProcessID = this.ProcessID, - IsBackup = this.IsBackup, - OriginalPath = this.OriginalPath, - PreviousDocumentIndex = this.PreviousDocumentIndex, - NextDocumentIndex = this.NextDocumentIndex, - ChequeredPattern = (ChequeredPattern)this.ChequeredPattern?.Clone(), - DottedPattern = (DottedPattern)this.DottedPattern?.Clone(), - RuledPattern = (RuledPattern)this.RuledPattern?.Clone(), - }; + var pageEntry = zipArchive.CreateEntry($"pages/page{pgCount}.xml", System.IO.Compression.CompressionLevel.Optimal); + using System.IO.Stream stream = pageEntry.Open(); + var data = Serialization.SaveToBytes(page, Serialization.Mode.XML); + await stream.WriteAsync(data); + } - // This is just for counting the pages - foreach (var page in Pages) - jrn.Pages.Add(new JournalPage()); + pgCount++; + } - var data = Serialization.SaveToBytes(jrn, Serialization.Mode.XML); - await stream.WriteAsync(data, 0, data.Length); - } + // Write journal infos + var info = zipArchive.CreateEntry("journal.xml"); + using (System.IO.Stream stream = info.Open()) + { + var jrn = new Journal() + { + ProcessID = this.ProcessID, + IsBackup = this.IsBackup, + OriginalPath = this.OriginalPath, + PreviousDocumentIndex = this.PreviousDocumentIndex, + NextDocumentIndex = this.NextDocumentIndex, + ChequeredPattern = (ChequeredPattern)this.ChequeredPattern?.Clone(), + DottedPattern = (DottedPattern)this.DottedPattern?.Clone(), + RuledPattern = (RuledPattern)this.RuledPattern?.Clone(), + }; + + // This is just for counting the pages + foreach (var page in Pages) + jrn.Pages.Add(new JournalPage()); + + var data = Serialization.SaveToBytes(jrn, Serialization.Mode.XML); + await stream.WriteAsync(data); } } @@ -391,7 +383,7 @@ public async Task SaveAsync(string filePath, bool quiet = false, bool hide retVal = true; - // Old method - only XML Serialization + // (wirklich uralt, deprecated) Old method - only XML Serialization //Serialization.Serialization.Save(filePath, this, Serialization.Serialization.Mode.XML); } catch (Exception e) diff --git a/Shared Libraries/SimpleJournal.Documents/JournalLoadResult.cs b/Shared Libraries/SimpleJournal.Documents/JournalLoadResult.cs new file mode 100644 index 0000000..91d65b9 --- /dev/null +++ b/Shared Libraries/SimpleJournal.Documents/JournalLoadResult.cs @@ -0,0 +1,38 @@ +namespace SimpleJournal.Documents +{ + public class JournalLoadResult + { + public Journal Journal { get; set; } + + public LoadState State { get; set; } + + public bool SupressErrorMessage { get; set; } = false; + + public string ErrorMessage { get; set; } + + public JournalLoadResult(Journal journal, LoadState state) + { + Journal = journal; + State = state; + } + + public JournalLoadResult(LoadState state) + { + State = state; + } + + public JournalLoadResult() + { + State = LoadState.UnknownError; + } + } + + public enum LoadState + { + Success, + InvalidOrCorruptFile, + IncompatibleVersion, + UnsupportedVersionOrCorrupt, + UnknownError + } +} diff --git a/Shared Libraries/SimpleJournal.Documents/JournalPage.cs b/Shared Libraries/SimpleJournal.Documents/JournalPage.cs index acf0001..ae02adc 100644 --- a/Shared Libraries/SimpleJournal.Documents/JournalPage.cs +++ b/Shared Libraries/SimpleJournal.Documents/JournalPage.cs @@ -29,7 +29,7 @@ public string Base64Data /// /// Additional data e.g images, text /// - public List JournalResources = new List(); + public List JournalResources = []; /// /// The format of the page (currently only A4 is possible) @@ -37,7 +37,7 @@ public string Base64Data public Format PageFormat { get; set; } = Format.A4; /// - /// The pattern of the page (i.e. chequered) (TODO: *** Should be renamed to PageType or PaperType) + /// The pattern of the page (i.e. chequered) (Could be renamed to PageType or PaperType but that would require old documents to convert ...) /// public PaperType PaperPattern { get; set; } = PaperType.Chequered; diff --git a/SimpleJournal/Consts.cs b/SimpleJournal/Consts.cs index a6c5c17..fa291f0 100644 --- a/SimpleJournal/Consts.cs +++ b/SimpleJournal/Consts.cs @@ -42,7 +42,7 @@ public static class Consts /// /// The .NET version which was used to compile SJ /// - public static readonly Version CompiledDotnetVersion = new Version(10, 0, 0); + public static readonly Version CompiledDotnetVersion = new Version(10, 0, 1); /// /// Polling interval for NotificationService diff --git a/SimpleJournal/Dialogs/RecoverAutoBackupFileDialog.xaml.cs b/SimpleJournal/Dialogs/RecoverAutoBackupFileDialog.xaml.cs index 7523a3d..1fc624b 100644 --- a/SimpleJournal/Dialogs/RecoverAutoBackupFileDialog.xaml.cs +++ b/SimpleJournal/Dialogs/RecoverAutoBackupFileDialog.xaml.cs @@ -210,7 +210,11 @@ private async Task RecoverFile(BackupDataItem backupDataItem, bool openA try { // Load journal - var journal = await Journal.LoadJournalAsync(backupDataItem.FileInfo.FullName, Consts.BackupDirectory, true); + var loadJournalResult = await Journal.LoadJournalAsync(backupDataItem.FileInfo.FullName, Consts.BackupDirectory, true); + if (loadJournalResult.State != LoadState.Success) + return string.Empty; + + var journal = loadJournalResult.Journal; if (journal == null) return string.Empty; diff --git a/SimpleJournal/MainWindow.xaml.cs b/SimpleJournal/MainWindow.xaml.cs index a468fa5..e409c9f 100644 --- a/SimpleJournal/MainWindow.xaml.cs +++ b/SimpleJournal/MainWindow.xaml.cs @@ -3540,7 +3540,32 @@ private async Task LoadJournalAsnyc(string fileName) throw new Exception(string.Format(Properties.Resources.strFileNotFound, fileName)); dialog.Show(); - currentJournal = await Journal.LoadJournalAsync(fileName, Consts.BackupDirectory); + var result = await Journal.LoadJournalAsync(fileName, Consts.BackupDirectory); + currentJournal = result.Journal; + + if (result.State != LoadState.Success) + { + if (result.SupressErrorMessage) + { + dialog.Close(); + return; + } + else + { + string localizedErrorMessage = string.Empty; + + switch (result.State) + { + case LoadState.IncompatibleVersion: localizedErrorMessage = SimpleJournal.Properties.Resources.strJournalLoadError_IncompatibleVersion; break; + case LoadState.InvalidOrCorruptFile: localizedErrorMessage = SimpleJournal.Properties.Resources.strJournalLoadError_InvalidOrCorruptFile; break; + case LoadState.UnsupportedVersionOrCorrupt: localizedErrorMessage = SimpleJournal.Properties.Resources.strJournalLoadError_UnsupportedVersionOrCorrupt; break; + case LoadState.UnknownError: localizedErrorMessage = string.Format(SimpleJournal.Properties.Resources.strJournalLoadError_UnknownError, result.ErrorMessage); break; + } + + MessageBox.Show(localizedErrorMessage, Properties.Resources.strFailedToLoadJournalTitle, MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + } if (currentJournal == null) { @@ -4181,7 +4206,20 @@ public void ApplyBackground() if (Settings.Instance.PageBackground != SimpleJournal.Common.Background.Custom) { string uri = $"pack://application:,,,/SimpleJournal;component/resources/backgrounds/{imageFileName}.jpg"; - ImageBrush imageBrush = new ImageBrush(new BitmapImage(new Uri(uri))) { Stretch = Stretch.UniformToFill }; + + var bitmap = new BitmapImage(); + bitmap.BeginInit(); + bitmap.UriSource = new Uri(uri); + bitmap.CacheOption = BitmapCacheOption.OnLoad; + bitmap.EndInit(); + bitmap.Freeze(); + + ImageBrush imageBrush = new ImageBrush(bitmap) + { + Stretch = Stretch.UniformToFill, + AlignmentY = AlignmentY.Top, // to prevent jump of the background if the save status bar is shown! + AlignmentX = AlignmentX.Center + }; mainScrollView.Background = imageBrush; } else diff --git a/SimpleJournal/Properties/Resources.Designer.cs b/SimpleJournal/Properties/Resources.Designer.cs index a5e9efc..1eee8e1 100644 --- a/SimpleJournal/Properties/Resources.Designer.cs +++ b/SimpleJournal/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace SimpleJournal.Properties { // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { @@ -1883,6 +1883,44 @@ public static string strJournalIsAlreadyOpenedTitle { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die This journal was created with an older version of SimpleJournal that is no longer supported. Please open the document using SimpleJournal 0.4.9.1 or contact support@code-a-software.net for assistance with recovery! ähnelt. + /// + public static string strJournalLoadError_IncompatibleVersion { + get { + return ResourceManager.GetString("strJournalLoadError_IncompatibleVersion", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die This journal cannot be loaded because it is invalid or corrupted. ähnelt. + /// + public static string strJournalLoadError_InvalidOrCorruptFile { + get { + return ResourceManager.GetString("strJournalLoadError_InvalidOrCorruptFile", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Failed to load journal: + /// + ///{0} ähnelt. + /// + public static string strJournalLoadError_UnknownError { + get { + return ResourceManager.GetString("strJournalLoadError_UnknownError", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Unsupported or corrupted document format. Maybe this journal was created with an older version of SimpleJournal! ähnelt. + /// + public static string strJournalLoadError_UnsupportedVersionOrCorrupt { + get { + return ResourceManager.GetString("strJournalLoadError_UnsupportedVersionOrCorrupt", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die There must be at least one page in the journal! ähnelt. /// diff --git a/SimpleJournal/Properties/Resources.de.resx b/SimpleJournal/Properties/Resources.de.resx index 565d858..ebcd8f1 100644 --- a/SimpleJournal/Properties/Resources.de.resx +++ b/SimpleJournal/Properties/Resources.de.resx @@ -2283,4 +2283,18 @@ Klicken Sie auf NEIN um die Änderungen zu verwerfen und ein neues Journal zu er Ihre Daten werden nicht an Dritte übermittelt, sondern nur dazu verwendet, um Ihnen antworten zu können! Weitere Informationen finden Sie in der + + Dieses Journal wurde mit einer älteren Version von SimpleJournal erstellt, die nicht mehr unterstützt wird. Bitte öffnen Sie das Dokument mit SimpleJournal 0.4.9.1 oder wenden Sie sich an support@code-a-software.net, um Hilfe bei der Wiederherstellung zu erhalten! + + + Dieses Journal kann nicht geladen werden, da sie ungültig oder beschädigt ist. + + + Nicht unterstütztes oder beschädigtes Dokumentformat. Möglicherweise wurde dieses Journal mit einer älteren Version von SimpleJournal erstellt! + + + Fehler beim Laden des Journals: + +{0} + \ No newline at end of file diff --git a/SimpleJournal/Properties/Resources.nl.resx b/SimpleJournal/Properties/Resources.nl.resx index 9d0280e..f97eb92 100644 --- a/SimpleJournal/Properties/Resources.nl.resx +++ b/SimpleJournal/Properties/Resources.nl.resx @@ -1863,4 +1863,18 @@ Klik op NEE om de wijzigingen te negeren en een nieuw journaal aan te maken of k Uw gegevens worden niet doorgegeven aan derden, maar alleen gebruikt om u te antwoorden! Meer informatie kunt u vinden in de + + Dit dagboek is gemaakt met een oudere versie van SimpleJournal die niet langer wordt ondersteund. Open het document met SimpleJournal 0.4.9.1 of neem contact op met support@code-a-software.net voor hulp bij het herstellen! + + + Dit journaal kan niet worden geladen omdat het ongeldig of beschadigd is. + + + Niet-ondersteunde of beschadigde documentindeling. Misschien is dit dagboek gemaakt met een oudere versie van SimpleJournal! + + + Kan journaal niet laden: + +{0} + \ No newline at end of file diff --git a/SimpleJournal/Properties/Resources.resx b/SimpleJournal/Properties/Resources.resx index 0181945..028b372 100644 --- a/SimpleJournal/Properties/Resources.resx +++ b/SimpleJournal/Properties/Resources.resx @@ -2433,4 +2433,18 @@ Click on NO to discard the changes and create a new journal or click on Cancel t Your data will not be shared with third parties, but will only be used to reply to you! Further information can be found in the + + This journal was created with an older version of SimpleJournal that is no longer supported. Please open the document using SimpleJournal 0.4.9.1 or contact support@code-a-software.net for assistance with recovery! + + + This journal cannot be loaded because it is invalid or corrupted. + + + Unsupported or corrupted document format. Maybe this journal was created with an older version of SimpleJournal! + + + Failed to load journal: + +{0} + \ No newline at end of file diff --git a/SimpleJournal/SimpleJournal.csproj b/SimpleJournal/SimpleJournal.csproj index b871323..87c425f 100644 --- a/SimpleJournal/SimpleJournal.csproj +++ b/SimpleJournal/SimpleJournal.csproj @@ -282,12 +282,12 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + - + diff --git a/Store Packages/ReferencePackage (SimpleJournal) (88) (1.710.0.0) (27.12.25).msix b/Store Packages/ReferencePackage (SimpleJournal) (88) (1.710.0.0) (27.12.25).msix new file mode 100644 index 0000000..d637e17 Binary files /dev/null and b/Store Packages/ReferencePackage (SimpleJournal) (88) (1.710.0.0) (27.12.25).msix differ