├── .github └── CONTRIBUTING.md ├── .gitignore ├── CHANGELOG.md ├── GitVersion.yml ├── LICENSE ├── README.md ├── Resources ├── Noterium_icon.ico ├── Noterium_icon.pdn └── Noterium_icon.png ├── docs ├── Index.md ├── _config.yml ├── mainwindow1.png └── mainwindow1_light.png └── src ├── .nuget ├── NuGet.Config ├── NuGet.exe └── NuGet.targets ├── LICENSE-3RD-PARTY.txt ├── Noterium.Core ├── AppSettings.cs ├── Constants │ ├── ApplicationConstants.cs │ ├── Colours.cs │ ├── DefaultTagColors.cs │ ├── File.cs │ └── NoteViewModes.cs ├── DataCarriers │ ├── Library.cs │ ├── Note.cs │ ├── NoteBook.cs │ ├── NoteClipboardData.cs │ ├── NoteFile.cs │ ├── Settings.cs │ ├── Tag.cs │ └── TextHistory.cs ├── DropBox │ └── DataStore.cs ├── Exceptions │ └── SaveException.cs ├── Helpers │ ├── ClipboardHelper.cs │ ├── CollectionHelpers.cs │ ├── ExceptionHelpers.cs │ ├── FileHelpers.cs │ ├── FlashWindowHelper.cs │ ├── GuiHelper.cs │ ├── JsonHelper.cs │ ├── MimeType.cs │ ├── Reflection.cs │ ├── StringHelper.cs │ └── SystemHelper.cs ├── Hub.cs ├── IDataStore.cs ├── Interfaces │ └── ISortable.cs ├── Noterium.Core.csproj ├── Properties │ ├── Annotations.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ └── Resources.sv.resx ├── Resources │ └── Thumbs.db ├── Search │ └── SearchManager.cs ├── Security │ ├── AESGCM.cs │ └── EncryptionManager.cs ├── Services │ ├── ClipboardHtmlHelper.cs │ └── TextClipper.cs ├── Storage.cs ├── StorageType.cs ├── TagManager.cs ├── Utilities │ └── FileSecurity.cs ├── app.config └── packages.config ├── Noterium.sln ├── Noterium ├── App.config ├── App.xaml ├── App.xaml.cs ├── Code │ ├── AttachedProperties │ │ ├── HyperlinkExtensions.cs │ │ ├── RichTextboxAssistant.cs │ │ └── ScrollSpeed.cs │ ├── Behaviors │ │ └── DataGridBehavior.cs │ ├── BoundObservableCollection.cs │ ├── Commands │ │ ├── CustomCommandInvoker.cs │ │ ├── NoteFileCommand.cs │ │ └── SimpleCommand.cs │ ├── Controls │ │ └── BindingProxy.cs │ ├── Converters │ │ ├── BindingNullConverter.cs │ │ ├── BindingNullToVisibilityConverter.cs │ │ ├── BooleanConverter.cs │ │ ├── BooleanToVisibilityConverter.cs │ │ ├── MultiValueBindingConverter.cs │ │ ├── StaticResourceConverter.cs │ │ └── XamlTextToFlowDocumentConverter.cs │ ├── Data │ │ └── DocumentEntitiy.cs │ ├── Extensions │ │ └── SecureStringExtensions.cs │ ├── Helpers │ │ ├── DialogHelpers.cs │ │ └── NoteMathHelper.cs │ ├── Interfaces │ │ ├── IMainMenuItem.cs │ │ └── INoteMenuItem.cs │ ├── ListViewDragDrop │ │ └── MouseUtilities.cs │ ├── Markdown │ │ ├── LinkInlineRenderer.cs │ │ ├── TaskListRenderer.cs │ │ ├── TextToFlowDocumentConverter.cs │ │ └── WpfRenderer.cs │ └── Messages │ │ ├── ApplicationPartLoaded.cs │ │ ├── ApplicationUnlocked.cs │ │ ├── ChangeLibrary.cs │ │ ├── ChangeViewMode.cs │ │ ├── ConfigureControlsForParnetType.cs │ │ ├── DeleteNote.cs │ │ ├── MenuItemType.cs │ │ ├── QuickMessage.cs │ │ ├── ReloadNoteMenuList.cs │ │ ├── SelectNote.cs │ │ ├── SelectedNoteChanged.cs │ │ └── UpdateNoteList.cs ├── Components │ ├── AuthenticationForm.xaml │ ├── AuthenticationForm.xaml.cs │ ├── NoteMenu │ │ ├── NoteMenu.xaml │ │ └── NoteMenu.xaml.cs │ └── NotebookMenu │ │ ├── NotebookMenu.xaml │ │ └── NotebookMenu.xaml.cs ├── Controls │ ├── AdornedControl │ │ ├── AdornedControl.cs │ │ ├── AdornerPlacement.cs │ │ └── FrameworkElementAdorner.cs │ ├── BaseUserControl.cs │ ├── Behaviors │ │ ├── AvalonEditBehavior.cs │ │ ├── BindableSelectedItemBehavior.cs │ │ └── PasteBehavior.cs │ ├── ColumnDefinitionExtended.cs │ ├── TokenizedTagControl.cs │ └── TokenizedTagItem.cs ├── LICENSE-3RD-PARTY.txt ├── MainWindow.cs ├── MainWindow.xaml ├── Noterium.csproj ├── Properties │ ├── Annotations.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Resources.sv.resx │ ├── Settings.Designer.cs │ ├── Settings.settings │ └── app.manifest ├── Resources │ ├── Entypo-license.txt │ ├── Entypo.ttf │ ├── Icons.xaml │ ├── IconsNonShared.xaml │ ├── NoteViewDocument.xaml │ ├── Styles.xaml │ ├── TokenizedTagControl.xaml │ ├── VSDark.xaml │ ├── VSLight.xaml │ ├── WindowsIcons-license.txt │ └── icon.xaml ├── Settings.cs ├── ViewModel │ ├── MainViewModel.cs │ └── ViewModelLocator.cs ├── ViewModels │ ├── AboutWindowViewModel.cs │ ├── AutoFilterViewModel.cs │ ├── BackupManagerViewModel.cs │ ├── LibraryViewModel.cs │ ├── LibrarysViewModel.cs │ ├── MainViewModel.cs │ ├── NoteEditorViewModel.cs │ ├── NoteFileViewModel.cs │ ├── NoteMenuViewModel.cs │ ├── NoteViewModel.cs │ ├── NoteViewerViewModel.cs │ ├── NotebookMenuViewModel.cs │ ├── NotebookViewModel.cs │ ├── NoteriumViewModelBase.cs │ ├── SettingsViewModel.cs │ ├── TagViewModel.cs │ ├── TopMainMenuItemViewModel.cs │ └── ViewModelLocator.cs ├── Views │ ├── Dialogs │ │ ├── AuthenticationWindow.xaml │ │ ├── AuthenticationWindow.xaml.cs │ │ ├── LoadingWindow.xaml │ │ ├── LoadingWindow.xaml.cs │ │ ├── StorageSelector.xaml │ │ └── StorageSelector.xaml.cs │ ├── Flyouts │ │ ├── Librarys.xaml │ │ ├── Librarys.xaml.cs │ │ ├── Settings.xaml │ │ └── Settings.xaml.cs │ ├── NoteEditor.xaml │ ├── NoteEditor.xaml.cs │ ├── NoteView.xaml │ └── NoteView.xaml.cs ├── Windows │ ├── AboutWindow.xaml │ ├── AboutWindow.xaml.cs │ ├── BackupManager.xaml │ ├── BackupManager.xaml.cs │ ├── NoteEditor.xaml │ ├── NoteEditor.xaml.cs │ ├── TableEditor.xaml │ └── TableEditor.xaml.cs ├── icon.ico ├── icon_24.png └── packages.config ├── Setup ├── Product.wxs ├── Setup.wixproj ├── icon.ico └── license.rtf └── lib ├── CommonMark.NET ├── CommonMark.dll └── CommonMark.xml └── Markdig.Wpf ├── Markdig.Wpf.dll ├── Markdig.Wpf.pdb └── Markdig.Wpf.xml /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.0.3 2 | 3 | - Minor bugfixes 4 | 5 | # 0.0.2 6 | 7 | - Support for multiple librarys #3 8 | 9 | # 0.0.1 10 | 11 | - First release 12 | -------------------------------------------------------------------------------- /GitVersion.yml: -------------------------------------------------------------------------------- 1 | assembly-versioning-scheme: MajorMinorPatch 2 | mode: Mainline 3 | next-version: 0.3.0 4 | branches: 5 | master: 6 | mode: ContinuousDeployment 7 | tag: '' 8 | ignore: 9 | sha: [] 10 | 11 | 12 | sha: [] 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Viktor Ekblom 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Noterium 2 | An app for taking total control over your notes. 3 | 4 | [![issues](https://img.shields.io/github/issues/ekblom/noterium.svg?style=flat-square)](https://github.com/ekblom/noterium/issues) 5 | 6 | [![Github All Releases](https://img.shields.io/github/downloads/ekblom/noterium/total.svg?style=flat-square)](https://github.com/ekblom/noterium/releases) 7 | 8 | ![downloads](https://img.shields.io/github/license/ekblom/noterium.svg?style=flat-square) 9 | 10 | ## Features 11 | 12 | ### Application 13 | 14 | - Multiple librarys (e.g. one private and one for your work) 15 | - Light and Dark theme 16 | - Search all notes (inluding secure notes) 17 | - It's all backed upp daily (if you want) 18 | 19 | ### Notes 20 | 21 | - Write notes in [CommonMark](http://commonmark.org/) 22 | - Support for GitHub flavoured markdown, i.e. tables and task lists 23 | - Inline images stored as attachment 24 | - Attachment files linkable in the notes 25 | - Do task lists 26 | 27 | ### Secure notes 28 | - Secure your notes with encryption (using https://gist.github.com/4336842) 29 | - Auto lock application when inactive 30 | 31 | ### Cloud 32 | Store your files anywhere you want, i.e. in DropBox, Google Drive or just a folder on your hard drive. 33 | 34 | When using a cloud provider and using Noterium on multiple computers, Noterium will automatically sync the notes to reflect changes made on the other computer. 35 | 36 | ## Screenshots 37 | 38 | ![maindemowindow01](./docs/mainwindow1.png) 39 | 40 | ![maindemowindow01](./docs/mainwindow1_light.png) 41 | 42 | ## Contributing to this project 43 | 44 | Did you stumble upon a bug? Before reporting it to us, please check out the [FAQ](https://github.com/MahApps/MahApps.Metro/wiki/FAQ) to see if it is actually a bug. If you can not find anything related to your issue, feel free to report it to us in the issue tracker. 45 | 46 | If you've improved Noterium and think that other people would enjoy it, submit a pull request. Anyone and everyone is welcome to contribute. 47 | 48 | Please take a moment to review the [guidelines for contributing](.github/CONTRIBUTING.md). 49 | 50 | * [Bug reports](.github/CONTRIBUTING.md#bugs) 51 | * [Feature requests](.github/CONTRIBUTING.md#features) 52 | * [Pull requests](.github/CONTRIBUTING.md#pull-requests) 53 | 54 | You need [Visual Studio 2015 Community Edition]() to build the solution. 55 | 56 | ## Thanks to 57 | 58 | The team behind MahApps.Metro (https://github.com/MahApps/MahApps.Metro) 59 | 60 | And to @punker76 for https://github.com/punker76/gong-wpf-dragdrop 61 | 62 | ## Licence 63 | 64 | [MIT License (MIT)](./LICENSE) 65 | -------------------------------------------------------------------------------- /Resources/Noterium_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/Resources/Noterium_icon.ico -------------------------------------------------------------------------------- /Resources/Noterium_icon.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/Resources/Noterium_icon.pdn -------------------------------------------------------------------------------- /Resources/Noterium_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/Resources/Noterium_icon.png -------------------------------------------------------------------------------- /docs/Index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | #Noterium 6 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /docs/mainwindow1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/docs/mainwindow1.png -------------------------------------------------------------------------------- /docs/mainwindow1_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/docs/mainwindow1_light.png -------------------------------------------------------------------------------- /src/.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/src/.nuget/NuGet.exe -------------------------------------------------------------------------------- /src/LICENSE-3RD-PARTY.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/src/LICENSE-3RD-PARTY.txt -------------------------------------------------------------------------------- /src/Noterium.Core/AppSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.IO; 5 | using System.Runtime.Serialization; 6 | using Newtonsoft.Json; 7 | using Noterium.Core.DataCarriers; 8 | using Noterium.Core.Helpers; 9 | 10 | namespace Noterium.Core 11 | { 12 | [DataContract] 13 | public class AppSettings 14 | { 15 | private string _settingsFilePath; 16 | private FileSystemWatcher _watcher; 17 | public ObservableCollection Librarys { get; set; } = new ObservableCollection(); 18 | 19 | [DataMember] 20 | public string DefaultLibrary { get; set; } = string.Empty; 21 | 22 | [DataMember] 23 | public List LibraryFiles { get; set; } = new List(); 24 | 25 | public string SettingsFolder 26 | { 27 | get 28 | { 29 | var appdataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); 30 | var appFolder = Path.Combine(appdataFolder, "Viktor Ekblom", "Noterium"); 31 | return appFolder; 32 | } 33 | } 34 | 35 | public void Init() 36 | { 37 | if (!Directory.Exists(SettingsFolder)) 38 | Directory.CreateDirectory(SettingsFolder); 39 | 40 | _settingsFilePath = GetSettingsFilePath(); 41 | 42 | if (File.Exists(_settingsFilePath)) 43 | try 44 | { 45 | InitInstance(); 46 | 47 | _watcher = new FileSystemWatcher 48 | { 49 | Path = Path.GetDirectoryName(SettingsFolder), 50 | Filter = Path.GetFileName(_settingsFilePath), 51 | NotifyFilter = NotifyFilters.LastWrite 52 | }; 53 | _watcher.Changed += OnChanged; 54 | _watcher.EnableRaisingEvents = true; 55 | } 56 | catch (Exception e) 57 | { 58 | throw new InvalidConfigurationFileException(e); 59 | } 60 | } 61 | 62 | private void InitInstance() 63 | { 64 | var json = File.ReadAllText(_settingsFilePath); 65 | JsonConvert.PopulateObject(json, this); 66 | LoadLibrarys(); 67 | } 68 | 69 | private void OnChanged(object sender, FileSystemEventArgs e) 70 | { 71 | InitInstance(); 72 | } 73 | 74 | private void LoadLibrarys() 75 | { 76 | Librarys.Clear(); 77 | foreach (var libraryFile in LibraryFiles) 78 | if (File.Exists(libraryFile)) 79 | { 80 | var lib = FileHelpers.LoadObjectFromFile(new FileInfo(libraryFile)); 81 | if (lib != null) 82 | { 83 | lib.Default = lib.Name.Equals(DefaultLibrary); 84 | Librarys.Add(lib); 85 | } 86 | } 87 | } 88 | 89 | private string GetSettingsFilePath() 90 | { 91 | #if DEBUG 92 | const string configurationFileName = "configuration.debug.json"; 93 | #else 94 | const string configurationFileName = "configuration.json"; 95 | #endif 96 | 97 | return Path.Combine(SettingsFolder, configurationFileName); 98 | } 99 | 100 | public void Save() 101 | { 102 | lock (_settingsFilePath) 103 | { 104 | var json = this.ToJson(); 105 | 106 | if (_watcher != null) _watcher.EnableRaisingEvents = false; 107 | File.WriteAllText(_settingsFilePath, json); 108 | if (_watcher != null) _watcher.EnableRaisingEvents = true; 109 | } 110 | } 111 | 112 | public void LogFatal(string message) 113 | { 114 | var di = Directory.CreateDirectory(Path.Combine(SettingsFolder, "log")); 115 | var logFile = Path.Combine(di.FullName, $"noterium_fatal_error_{DateTime.Now.Ticks}.log"); 116 | File.WriteAllText(logFile, message); 117 | } 118 | } 119 | 120 | public class InvalidConfigurationFileException : Exception 121 | { 122 | public InvalidConfigurationFileException(Exception innerException = null) : base(string.Empty, innerException) 123 | { 124 | } 125 | } 126 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Constants/ApplicationConstants.cs: -------------------------------------------------------------------------------- 1 | namespace Noterium.Core.Constants 2 | { 3 | public static class ApplicationConstants 4 | { 5 | public static int DragThreshold = 5; 6 | } 7 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Constants/Colours.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace Noterium.Core.Constants 4 | { 5 | public static class Colours 6 | { 7 | public static Color Border = Color.FromArgb(139, 203, 232); //#E4F1FB 8 | public static Color Background = Color.FromArgb(193, 222, 236); //#CDE4F5 9 | public static Color DarkText = Color.FromArgb(73, 130, 194); //#B5D5EC 10 | public static Color GreyText = Color.FromArgb(102, 102, 102); //#9CC4E0 11 | public static Color LightText = Color.FromArgb(217, 220, 221); //#9CC4E0 12 | public static Color BackgroundHover = Color.FromArgb(239, 248, 254); //#84B1D1 13 | public static Color MainBackground = Color.FromArgb(249, 250, 251); //#84B1D1 14 | } 15 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Constants/DefaultTagColors.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Windows.Media; 3 | 4 | namespace Noterium.Core.Constants 5 | { 6 | public static class DefaultTagColors 7 | { 8 | public static List Colors = new List 9 | { 10 | Convert("#5dccaa"), 11 | Convert("#58c0ff"), 12 | Convert("#cd392f"), 13 | Convert("#cd392f"), 14 | Convert("#f36e4b"), 15 | Convert("#330099"), 16 | Convert("#e7d3e2"), 17 | Convert("#669999"), 18 | Convert("#313131"), 19 | Convert("#6cadff") 20 | }; 21 | 22 | private static Color Convert(string hex) 23 | { 24 | return (Color) ColorConverter.ConvertFromString(hex); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Constants/File.cs: -------------------------------------------------------------------------------- 1 | namespace Noterium.Core.Constants 2 | { 3 | public static class File 4 | { 5 | public const string ReminderFileExtension = "rmd"; 6 | public const string NoteFileExtension = "note"; 7 | public const string NotebookFileExtension = "book"; 8 | public const string NotebookStackFileExtension = "stack"; 9 | } 10 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Constants/NoteViewModes.cs: -------------------------------------------------------------------------------- 1 | namespace Noterium.Core.Constants 2 | { 3 | public enum NoteViewModes 4 | { 5 | Default, 6 | View, 7 | Split, 8 | Edit 9 | } 10 | } -------------------------------------------------------------------------------- /src/Noterium.Core/DataCarriers/Library.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.IO; 4 | using System.Runtime.CompilerServices; 5 | using System.Runtime.Serialization; 6 | using System.Windows; 7 | using Noterium.Core.Helpers; 8 | 9 | namespace Noterium.Core.DataCarriers 10 | { 11 | [DataContract] 12 | public class Library : IComparable, IComparable, IEquatable, INotifyPropertyChanged 13 | { 14 | private bool _default; 15 | private string _name; 16 | 17 | public Library() 18 | { 19 | _default = Hub.Instance.AppSettings.DefaultLibrary.Equals(Name); 20 | } 21 | 22 | [DataMember] 23 | public string Name 24 | { 25 | get => _name; 26 | set 27 | { 28 | // RenameFile(_name, value); 29 | _name = value; 30 | RaiseOnPropetyChanged(); 31 | } 32 | } 33 | 34 | public string FilePath => GetFileName(Name); 35 | 36 | [DataMember] 37 | public string Path { get; set; } 38 | 39 | [DataMember] 40 | public StorageType StorageType { get; set; } 41 | 42 | [DataMember] 43 | public double NoteColumnWidth { get; set; } = 250; 44 | 45 | [DataMember] 46 | public double NotebookColumnWidth { get; set; } = 205; 47 | 48 | [DataMember] 49 | public Size WindowSize { get; set; } = new Size(1024, 768); 50 | 51 | [DataMember] 52 | public WindowState WindowState { get; set; } = WindowState.Normal; 53 | 54 | public bool Default 55 | { 56 | get => _default; 57 | set 58 | { 59 | _default = value; 60 | RaiseOnPropetyChanged(); 61 | } 62 | } 63 | 64 | public int CompareTo(object obj) 65 | { 66 | return string.Compare(Name, obj.ToString(), StringComparison.Ordinal); 67 | } 68 | 69 | public int CompareTo(Note other) 70 | { 71 | return string.Compare(Name, other.Name, StringComparison.Ordinal); 72 | } 73 | 74 | public bool Equals(Note other) 75 | { 76 | return Name.Equals(other?.Name); 77 | } 78 | 79 | public event PropertyChangedEventHandler PropertyChanged; 80 | 81 | private void RenameFile(string from, string to) 82 | { 83 | var fileName = GetFileName(from); 84 | var toFileName = GetFileName(to); 85 | if (File.Exists(fileName) && !File.Exists(toFileName)) 86 | { 87 | var fi = new FileInfo(fileName); 88 | fi.MoveTo(toFileName); 89 | return; 90 | } 91 | 92 | if (File.Exists(fileName)) 93 | throw new LibraryExistsException(); 94 | } 95 | 96 | private string GetFileName(string name) 97 | { 98 | var validFileName = FileHelpers.GetValidFileName(name.ToLowerInvariant()); 99 | return System.IO.Path.Combine(Hub.Instance.AppSettings.SettingsFolder, $"{validFileName}.libcfg"); 100 | } 101 | 102 | private void RaiseOnPropetyChanged([CallerMemberName] string propertyName = null) 103 | { 104 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 105 | } 106 | 107 | public void Save() 108 | { 109 | FileHelpers.Save(this, FilePath); 110 | } 111 | 112 | public void Delete() 113 | { 114 | if (File.Exists(FilePath)) 115 | File.Delete(FilePath); 116 | } 117 | } 118 | 119 | internal class LibraryExistsException : Exception 120 | { 121 | } 122 | } -------------------------------------------------------------------------------- /src/Noterium.Core/DataCarriers/NoteBook.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Runtime.CompilerServices; 6 | using System.Runtime.Serialization; 7 | using Noterium.Core.Annotations; 8 | 9 | namespace Noterium.Core.DataCarriers 10 | { 11 | [DataContract] 12 | [DebuggerDisplay("{Name} - {ID} - {BaseHashCode}")] 13 | public class Notebook : IComparable, IComparable, IEquatable, IEqualityComparer, INotifyPropertyChanged 14 | { 15 | private readonly object _deleteLockObject = new object(); 16 | private readonly object _saveLockObject = new object(); 17 | private bool _deleted; 18 | private string _name; 19 | 20 | public Notebook() 21 | { 22 | ID = Guid.NewGuid(); 23 | } 24 | 25 | [DataMember] 26 | public Guid ID { get; set; } 27 | 28 | [DataMember] 29 | public string Name 30 | { 31 | get => _name; 32 | set 33 | { 34 | _name = value; 35 | OnPropertyChanged(); 36 | } 37 | } 38 | 39 | [DataMember] 40 | public DateTime Created { get; set; } 41 | 42 | public bool Deleted 43 | { 44 | get => _deleted; 45 | private set 46 | { 47 | _deleted = value; 48 | OnPropertyChanged(); 49 | } 50 | } 51 | 52 | public int BaseHashCode => base.GetHashCode(); 53 | 54 | public int CompareTo(object obj) 55 | { 56 | var other = obj as Notebook; 57 | if (other != null) return CompareTo(other); 58 | return -1; 59 | } 60 | 61 | public int CompareTo(Notebook other) 62 | { 63 | return ID.CompareTo(other.ID); 64 | } 65 | 66 | public bool Equals(Notebook x, Notebook y) 67 | { 68 | return x.ID == y.ID; 69 | } 70 | 71 | public int GetHashCode(Notebook obj) 72 | { 73 | return obj.ID.GetHashCode(); 74 | } 75 | 76 | public bool Equals(Notebook other) 77 | { 78 | return ID == other.ID; 79 | } 80 | 81 | public event PropertyChangedEventHandler PropertyChanged; 82 | 83 | [NotifyPropertyChangedInvocator] 84 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 85 | { 86 | var handler = PropertyChanged; 87 | handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 88 | } 89 | 90 | public void Save() 91 | { 92 | lock (_saveLockObject) 93 | { 94 | if (Deleted) 95 | return; 96 | 97 | Hub.Instance.Storage.SaveNotebook(this); 98 | } 99 | } 100 | 101 | public void Delete() 102 | { 103 | lock (_deleteLockObject) 104 | { 105 | if (!Deleted) 106 | { 107 | Hub.Instance.Storage.DeleteGroup(this); 108 | Deleted = true; 109 | } 110 | } 111 | } 112 | 113 | public override int GetHashCode() 114 | { 115 | return ID.GetHashCode(); 116 | } 117 | 118 | public override string ToString() 119 | { 120 | return string.Format("{0} - {{{1}}} - {2}", Name, ID, base.GetHashCode()); 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /src/Noterium.Core/DataCarriers/NoteClipboardData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Noterium.Core.DataCarriers 5 | { 6 | [Serializable] 7 | public class NoteClipboardData 8 | { 9 | public string Text { get; set; } 10 | public List Tags { get; set; } 11 | public List Files { get; set; } 12 | public string Name { get; set; } 13 | } 14 | 15 | [Serializable] 16 | public class ClipboardFile 17 | { 18 | public string Name { get; set; } 19 | public byte[] Data { get; set; } 20 | public string MimeType { get; set; } 21 | public string FileName { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Noterium.Core/DataCarriers/NoteFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Runtime.CompilerServices; 7 | using System.Runtime.Serialization; 8 | using System.Windows.Media.Imaging; 9 | using Microsoft.WindowsAPICodePack.Shell; 10 | using Noterium.Core.Annotations; 11 | using Noterium.Core.Helpers; 12 | 13 | namespace Noterium.Core.DataCarriers 14 | { 15 | [DataContract] 16 | public class NoteFile : INotifyPropertyChanged 17 | { 18 | private string _name; 19 | 20 | public NoteFile() 21 | { 22 | } 23 | 24 | public NoteFile(string fileName, string name, Guid owner) 25 | { 26 | FileName = fileName; 27 | Name = name; 28 | Owner = owner; 29 | } 30 | 31 | [DataMember(Order = 0)] 32 | public string FileName { get; set; } 33 | 34 | [DataMember(Order = 1)] 35 | public string Name 36 | { 37 | get => _name; 38 | set 39 | { 40 | _name = value; 41 | OnPropertyChanged(); 42 | } 43 | } 44 | 45 | [DataMember(Order = 2)] 46 | public Guid Owner { get; set; } 47 | 48 | public bool IsImage => MimeType.IsImageExtension(Path.GetExtension(FileName)); 49 | 50 | public string FullName => Hub.Instance.Storage.GetNoteFilePath(this); 51 | 52 | public BitmapSource Thumbnail 53 | { 54 | get 55 | { 56 | var shellFile = ShellFile.FromFilePath(FullName); 57 | if (shellFile != null) 58 | return shellFile.Thumbnail.BitmapSource; 59 | 60 | return null; 61 | } 62 | } 63 | 64 | public event PropertyChangedEventHandler PropertyChanged; 65 | 66 | public FileInfo GetFile() 67 | { 68 | var path = Hub.Instance.Storage.GetNoteFilePath(this); 69 | return new FileInfo(path); 70 | } 71 | 72 | public static NoteFile Create(string name, string mime, byte[] data, Note owner, string extension = null) 73 | { 74 | var folder = Hub.Instance.Storage.GetNoteFolderPath(owner.ID); 75 | var ext = extension ?? MimeType.GetDefaultExtension(mime); 76 | if (string.IsNullOrWhiteSpace(ext) && name != null && name.IndexOf(".", StringComparison.Ordinal) != -1) ext = name.Split('.')[1]; 77 | 78 | if (string.IsNullOrWhiteSpace(ext)) 79 | throw new Exception("Unable to get file extension."); 80 | 81 | var finalFileName = owner.ID + "_" + GetNewFilenumber(owner.Files.ToList()) + ext; 82 | var finalFilePath = folder + "\\" + finalFileName; 83 | try 84 | { 85 | File.WriteAllBytes(finalFilePath, data); 86 | 87 | var nf = new NoteFile(finalFileName, name ?? finalFileName, owner.ID); 88 | owner.Files.Add(nf); 89 | owner.Save(); 90 | return nf; 91 | } 92 | catch (Exception) 93 | { 94 | return null; 95 | } 96 | } 97 | 98 | public static string ProposeNoteFileName(string name, Note note) 99 | { 100 | var existingNoteFile = note.Files.FirstOrDefault(enf => enf.Name.Equals(name)); 101 | 102 | var count = 1; 103 | while (existingNoteFile != null) 104 | { 105 | var indexOfDot = name.IndexOf(".", StringComparison.Ordinal); 106 | name = name.Insert(indexOfDot, count.ToString()); 107 | 108 | existingNoteFile = note.Files.FirstOrDefault(enf => enf.Name.Equals(name)); 109 | } 110 | 111 | return name; 112 | } 113 | 114 | private static int GetNewFilenumber(List files) 115 | { 116 | if (!files.Any()) 117 | return 0; 118 | 119 | var numbers = files.ConvertAll(file => 120 | { 121 | var chunks = file.FileName.Split('_'); 122 | if (chunks.Length == 2) 123 | { 124 | chunks = chunks[1].Split('.'); 125 | int number; 126 | if (int.TryParse(chunks[0], out number)) 127 | return number; 128 | } 129 | 130 | return 0; 131 | }); 132 | 133 | return numbers.Max() + 1; 134 | } 135 | 136 | public void Delete() 137 | { 138 | var fi = GetFile(); 139 | if (fi.Exists) 140 | fi.Delete(); 141 | } 142 | 143 | public string GetAsImageMarkdown() 144 | { 145 | return $"![{Name}]({FileName})"; 146 | } 147 | 148 | [NotifyPropertyChangedInvocator] 149 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 150 | { 151 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 152 | } 153 | 154 | public string GetAsFileLink() 155 | { 156 | return $"[{Name}]({FileName})"; 157 | } 158 | } 159 | } -------------------------------------------------------------------------------- /src/Noterium.Core/DataCarriers/Tag.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.Serialization; 5 | using System.Windows.Media; 6 | using Newtonsoft.Json; 7 | using Noterium.Core.Annotations; 8 | 9 | namespace Noterium.Core.DataCarriers 10 | { 11 | public class Tag : INotifyPropertyChanged, IComparable, IComparable, IEquatable 12 | { 13 | private Color _color; 14 | private int _instances; 15 | private string _name; 16 | 17 | public Tag() 18 | { 19 | _color = Color.FromArgb(204, 17, 158, 218); 20 | } 21 | 22 | [DataMember] 23 | public string Name 24 | { 25 | get => _name; 26 | set 27 | { 28 | if (_name == null) 29 | _name = value.ToLower(); 30 | else 31 | throw new NotSupportedException("Cant change name of a tag."); 32 | } 33 | } 34 | 35 | [DataMember] 36 | public Color Color 37 | { 38 | get => _color; 39 | set 40 | { 41 | _color = value; 42 | OnPropertyChanged(); 43 | } 44 | } 45 | 46 | [JsonProperty("instances", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 47 | [DefaultValue(0)] 48 | [DataMember] 49 | public int Instances 50 | { 51 | get => _instances; 52 | set 53 | { 54 | _instances = value; 55 | OnPropertyChanged(); 56 | } 57 | } 58 | 59 | public int CompareTo(object obj) 60 | { 61 | return string.Compare(Name, ((Tag) obj).Name, StringComparison.CurrentCultureIgnoreCase); 62 | } 63 | 64 | public int CompareTo(Tag other) 65 | { 66 | return string.Compare(Name, other.Name, StringComparison.CurrentCultureIgnoreCase); 67 | } 68 | 69 | public bool Equals(Tag other) 70 | { 71 | return Name.Equals(other.Name, StringComparison.CurrentCultureIgnoreCase); 72 | } 73 | 74 | public event PropertyChangedEventHandler PropertyChanged; 75 | 76 | [NotifyPropertyChangedInvocator] 77 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 78 | { 79 | var handler = PropertyChanged; 80 | handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /src/Noterium.Core/DataCarriers/TextHistory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Noterium.Core.DataCarriers 4 | { 5 | public class TextHistory : IComparable, IComparable, IEquatable 6 | { 7 | public Guid ID { get; set; } 8 | public DateTime Date { get; set; } 9 | public string Text { get; set; } 10 | 11 | public int CompareTo(object obj) 12 | { 13 | var th = obj as TextHistory; 14 | if (th != null) 15 | return CompareTo(th); 16 | return -1; 17 | } 18 | 19 | public int CompareTo(TextHistory other) 20 | { 21 | return ID.CompareTo(other.ID); 22 | } 23 | 24 | public bool Equals(TextHistory other) 25 | { 26 | return ID == other.ID; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Exceptions/SaveException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Noterium.Core.Exceptions 4 | { 5 | public class SaveException : Exception 6 | { 7 | public SaveException(object unsavedObject) 8 | { 9 | UnsavedObject = unsavedObject; 10 | } 11 | 12 | public object UnsavedObject { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Helpers/ClipboardHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Drawing.Imaging; 4 | using System.IO; 5 | using System.Runtime.InteropServices; 6 | using System.Windows.Forms; 7 | 8 | namespace Noterium.Core.Helpers 9 | { 10 | public class ClipboardHelper 11 | { 12 | public static Image GetImageFromClipboard() 13 | { 14 | var dataObject = Clipboard.GetDataObject(); 15 | if (dataObject == null) 16 | return null; 17 | 18 | if (dataObject.GetDataPresent(DataFormats.Dib)) 19 | { 20 | var dib = ((MemoryStream) Clipboard.GetData(DataFormats.Dib)).ToArray(); 21 | var width = BitConverter.ToInt32(dib, 4); 22 | var height = BitConverter.ToInt32(dib, 8); 23 | var bpp = BitConverter.ToInt16(dib, 14); 24 | if (bpp == 32) 25 | { 26 | var gch = GCHandle.Alloc(dib, GCHandleType.Pinned); 27 | Bitmap bmp = null; 28 | try 29 | { 30 | var ptr = new IntPtr((long) gch.AddrOfPinnedObject() + 40); 31 | bmp = new Bitmap(width, height, width * 4, PixelFormat.Format32bppArgb, ptr); 32 | 33 | var newBmp = new Bitmap(bmp); 34 | newBmp.RotateFlip(RotateFlipType.Rotate180FlipX); 35 | return newBmp; 36 | } 37 | finally 38 | { 39 | gch.Free(); 40 | bmp?.Dispose(); 41 | } 42 | } 43 | } 44 | 45 | return Clipboard.ContainsImage() ? Clipboard.GetImage() : null; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Helpers/CollectionHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using System.Linq; 4 | 5 | namespace Noterium.Core.Helpers 6 | { 7 | public static class CollectionHelpers 8 | { 9 | public static void Sort(this ObservableCollection observable) where T : IComparable, IEquatable 10 | { 11 | var sorted = observable.OrderBy(x => x).ToList(); 12 | 13 | var ptr = 0; 14 | while (ptr < sorted.Count) 15 | if (!observable[ptr].Equals(sorted[ptr])) 16 | { 17 | var t = observable[ptr]; 18 | observable.RemoveAt(ptr); 19 | observable.Insert(sorted.IndexOf(t), t); 20 | } 21 | else 22 | { 23 | ptr++; 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Helpers/ExceptionHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Noterium.Core.Helpers 5 | { 6 | public static class ExceptionHelpers 7 | { 8 | public static string FlattenException(this Exception exception) 9 | { 10 | var stringBuilder = new StringBuilder(); 11 | 12 | while (exception != null) 13 | { 14 | stringBuilder.AppendLine(exception.Message); 15 | stringBuilder.AppendLine(exception.StackTrace); 16 | 17 | exception = exception.InnerException; 18 | } 19 | 20 | return stringBuilder.ToString(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Helpers/GuiHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace Noterium.Core.Helpers 5 | { 6 | public static class GuiHelper 7 | { 8 | public static double GetDistanceBetweenPoints(Point p, Point q) 9 | { 10 | double a = p.X - q.X; 11 | double b = p.Y - q.Y; 12 | var distance = Math.Sqrt(a * a + b * b); 13 | return distance; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Helpers/JsonHelper.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace Noterium.Core.Helpers 4 | { 5 | public static class JsonHelper 6 | { 7 | public static string ToJson(this object obj) 8 | { 9 | return JsonConvert.SerializeObject(obj, Formatting.Indented); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Helpers/MimeType.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Microsoft.Win32; 3 | 4 | namespace Noterium.Core.Helpers 5 | { 6 | public class MimeType 7 | { 8 | private static readonly byte[] BMP = {66, 77}; 9 | private static readonly byte[] GIF = {71, 73, 70, 56}; 10 | private static readonly byte[] ICO = {0, 0, 1, 0}; 11 | private static readonly byte[] JPG = {255, 216, 255}; 12 | private static readonly byte[] PNG = {137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82}; 13 | private static readonly byte[] TIFF = {73, 73, 42, 0}; 14 | 15 | public static string GetMimeType(byte[] file, string defaultMime = "application/octet-stream") 16 | { 17 | var mime = defaultMime; //DEFAULT UNKNOWN MIME TYPE 18 | 19 | if (file.Take(2).SequenceEqual(BMP)) 20 | mime = "image/bmp"; 21 | else if (file.Take(4).SequenceEqual(GIF)) 22 | mime = "image/gif"; 23 | else if (file.Take(4).SequenceEqual(ICO)) 24 | mime = "image/x-icon"; 25 | else if (file.Take(3).SequenceEqual(JPG)) 26 | mime = "image/jpeg"; 27 | else if (file.Take(16).SequenceEqual(PNG)) 28 | mime = "image/png"; 29 | else if (file.Take(4).SequenceEqual(TIFF)) mime = "image/tiff"; 30 | 31 | return mime; 32 | } 33 | 34 | public static string GetDefaultExtension(string mimeType) 35 | { 36 | var key = Registry.ClassesRoot.OpenSubKey(@"MIME\Database\Content Type\" + mimeType, false); 37 | var value = key?.GetValue("Extension", null); 38 | var result = value?.ToString() ?? string.Empty; 39 | 40 | return result; 41 | } 42 | 43 | public static bool IsImageExtension(string ext) 44 | { 45 | switch (ext) 46 | { 47 | case ".png": 48 | case ".jpg": 49 | case ".jpeg": 50 | case ".gif": 51 | case ".bmp": 52 | return true; 53 | } 54 | 55 | return false; 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Helpers/Reflection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace Noterium.Core.Helpers 5 | { 6 | public static class Reflection 7 | { 8 | /// 9 | /// Extension for 'Object' that copies the properties to a destination object. 10 | /// 11 | /// The source. 12 | /// The destination. 13 | public static void CopyProperties(this object source, object destination) 14 | { 15 | // If any this null throw an exception 16 | if (source == null || destination == null) 17 | throw new Exception("Source or/and Destination Objects are null"); 18 | // Getting the Types of the objects 19 | var typeDest = destination.GetType(); 20 | var typeSrc = source.GetType(); 21 | 22 | // Iterate the Properties of the source instance and 23 | // populate them from their desination counterparts 24 | var srcProps = typeSrc.GetProperties(); 25 | foreach (var srcProp in srcProps) 26 | { 27 | if (!srcProp.CanRead) continue; 28 | var targetProperty = typeDest.GetProperty(srcProp.Name); 29 | if (targetProperty == null) continue; 30 | if (!targetProperty.CanWrite) continue; 31 | 32 | var setMethod = targetProperty.GetSetMethod(true); 33 | if (setMethod != null && setMethod.IsPrivate) continue; 34 | 35 | setMethod = targetProperty.GetSetMethod(); 36 | if (setMethod == null || (setMethod.Attributes & MethodAttributes.Static) != 0) continue; 37 | if (!targetProperty.PropertyType.IsAssignableFrom(srcProp.PropertyType)) continue; 38 | // Passed all tests, lets set the value 39 | targetProperty.SetValue(destination, srcProp.GetValue(source, null), null); 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Helpers/StringHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | using System.Text; 3 | 4 | namespace Noterium.Core.Helpers 5 | { 6 | public static class StringHelper 7 | { 8 | public static string GetMD5Hash(this string s) 9 | { 10 | return CalculateMD5Hash(s); 11 | } 12 | 13 | public static string CalculateMD5Hash(string input) 14 | { 15 | // step 1, calculate MD5 hash from input 16 | var md5 = MD5.Create(); 17 | 18 | var inputBytes = Encoding.ASCII.GetBytes(input); 19 | var hash = md5.ComputeHash(inputBytes); 20 | 21 | // step 2, convert byte array to hex string 22 | var sb = new StringBuilder(); 23 | 24 | foreach (var t in hash) sb.Append(t.ToString("X2")); 25 | 26 | return sb.ToString(); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Helpers/SystemHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Noterium.Core.Helpers 5 | { 6 | public class SystemHelper 7 | { 8 | private const int SM_CXDRAG = 68; 9 | private const int SM_CYDRAG = 69; 10 | 11 | [DllImport("user32.dll")] 12 | private static extern int GetSystemMetrics(int index); 13 | 14 | public static Point GetDragThreshold() 15 | { 16 | return new Point(GetSystemMetrics(SM_CXDRAG), GetSystemMetrics(SM_CYDRAG)); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Hub.cs: -------------------------------------------------------------------------------- 1 | using Noterium.Core.DataCarriers; 2 | using Noterium.Core.Search; 3 | using Noterium.Core.Security; 4 | using Noterium.Core.Services; 5 | 6 | namespace Noterium.Core 7 | { 8 | public class Hub 9 | { 10 | // Explicit static constructor to tell C# compiler 11 | // not to mark type as beforefieldinit 12 | static Hub() 13 | { 14 | } 15 | 16 | private Hub() 17 | { 18 | Storage = new Storage(); 19 | AppSettings = new AppSettings(); 20 | } 21 | 22 | public static Hub Instance { get; } = new Hub(); 23 | 24 | public SearchManager SearchManager { get; private set; } 25 | 26 | public Storage Storage { get; } 27 | 28 | public Settings Settings { get; private set; } 29 | 30 | public TextClipper TextClipper { get; private set; } 31 | 32 | public EncryptionManager EncryptionManager { get; private set; } 33 | 34 | public TagManager TagManager { get; private set; } 35 | 36 | public AppSettings AppSettings { get; } 37 | 38 | public Library CurrentLibrary { get; set; } 39 | 40 | public void Init(Library l) 41 | { 42 | CurrentLibrary = l; 43 | Storage.Init(l); 44 | SearchManager = new SearchManager(Storage); 45 | Settings = Storage.GetSettings(); 46 | TextClipper = new TextClipper(); 47 | EncryptionManager = new EncryptionManager(Storage.DataStore); 48 | TagManager = new TagManager(); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/Noterium.Core/IDataStore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Noterium.Core.DataCarriers; 4 | 5 | namespace Noterium.Core 6 | { 7 | public interface IDataStore 8 | { 9 | void SaveNote(Note note); 10 | void SaveNoteBook(Notebook noteBook); 11 | List GetNotes(Notebook mg); 12 | int GetNoteCount(Notebook mg); 13 | int GetTotalNoteCount(); 14 | List GetNoteBooks(); 15 | List GetAllNotes(); 16 | void SaveSettings(Settings settings); 17 | Settings GetSettings(); 18 | Note GetNote(Guid id); 19 | void DeleteNote(Note note); 20 | void DeleteNoteBook(Notebook noteBook); 21 | void EnsureOneNotebook(); 22 | string GetStoragePath(); 23 | 24 | bool EnsureDropBox(); 25 | 26 | void MoveNote(Note note, Notebook noteBook); 27 | 28 | void BackupData(); 29 | DateTime GetLastBackupDate(); 30 | 31 | Notebook GetNoteBook(Guid guid); 32 | 33 | void CleanBackupData(int backupsToKeep); 34 | } 35 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Interfaces/ISortable.cs: -------------------------------------------------------------------------------- 1 | namespace Noterium.Core.Interfaces 2 | { 3 | public interface ISortable 4 | { 5 | int SortIndex { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | 8 | [assembly: AssemblyTitle("Noterium.Core")] 9 | [assembly: AssemblyDescription("Core component of Noterium")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Viktor Ekblom")] 12 | [assembly: AssemblyProduct("Noterium.Core")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | 25 | //[assembly: Guid("91422d3b-6769-407d-b34f-12418ccfeb68")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [assembly: AssemblyVersion("1.0.*")] 37 | 38 | -------------------------------------------------------------------------------- /src/Noterium.Core/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Noterium.Core.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Noterium.Core.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap image { 67 | get { 68 | object obj = ResourceManager.GetObject("image", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Noterium.Core/Resources/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/src/Noterium.Core/Resources/Thumbs.db -------------------------------------------------------------------------------- /src/Noterium.Core/Search/SearchManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Noterium.Core.DataCarriers; 5 | 6 | namespace Noterium.Core.Search 7 | { 8 | public class SearchManager 9 | { 10 | private readonly Storage _storage; 11 | 12 | public SearchManager(Storage storage) 13 | { 14 | _storage = storage; 15 | } 16 | 17 | public List Search(string searchTerm) 18 | { 19 | var notes = _storage.GetAllNotes(); 20 | return notes.Where(n => 21 | { 22 | if (n.InTrashCan) 23 | return false; 24 | 25 | var text = n.Name.IndexOf(searchTerm, StringComparison.InvariantCultureIgnoreCase) > -1 26 | || n.DecryptedText.IndexOf(searchTerm, StringComparison.InvariantCultureIgnoreCase) > -1; 27 | 28 | var tag = n.Tags.Any(t => t.IndexOf(searchTerm, StringComparison.InvariantCultureIgnoreCase) > -1); 29 | 30 | return text || tag; 31 | }).ToList(); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Services/ClipboardHtmlHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Text.RegularExpressions; 4 | 5 | namespace Noterium.Core.Services 6 | { 7 | internal class ClipboardHtmlHelper 8 | { 9 | public static ClipboardHtmlOutput ParseString(string s) 10 | { 11 | var html = new ClipboardHtmlOutput(); 12 | 13 | var pattern = @"Version:(?[0-9]+(?:\.[0-9]*)?).+StartHTML:(?\d*).+EndHTML:(?\d*).+StartFragment:(?\d+).+EndFragment:(?\d*).+SourceURL:(?f|ht{1}tps?://[-a-zA-Z0-9@:%_\+.~#?&//=]+)"; 14 | var match = Regex.Match(s, pattern, RegexOptions.Singleline); 15 | 16 | if (match.Success) 17 | { 18 | try 19 | { 20 | html.Input = s; 21 | html.Version = double.Parse(match.Groups["version"].Value, CultureInfo.InvariantCulture); 22 | html.Source = match.Groups["source"].Value; 23 | html.startHTML = int.Parse(match.Groups["startH"].Value); 24 | html.endHTML = int.Parse(match.Groups["endH"].Value); 25 | html.startFragment = int.Parse(match.Groups["startF"].Value); 26 | html.endFragment = int.Parse(match.Groups["endF"].Value); 27 | } 28 | catch (Exception) 29 | { 30 | return null; 31 | } 32 | 33 | return html; 34 | } 35 | 36 | return null; 37 | } 38 | } 39 | 40 | internal class ClipboardHtmlOutput 41 | { 42 | internal int endFragment; 43 | internal int endHTML; 44 | internal int startFragment; 45 | 46 | internal int startHTML; 47 | public double Version { get; internal set; } 48 | public string Source { get; internal set; } 49 | 50 | public string Input { get; internal set; } 51 | 52 | //public String Html { get { return Input.Substring(startHTML, (endHTML - startHTML)); } } 53 | public string Html => Input.Substring(startHTML, Math.Min(endHTML - startHTML, Input.Length - startHTML)); 54 | 55 | public string Fragment => Input.Substring(startFragment, endFragment - startFragment); 56 | } 57 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Services/TextClipper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | using System.Windows.Forms; 5 | using log4net; 6 | using Shortcut; 7 | 8 | namespace Noterium.Core.Services 9 | { 10 | public class TextClipper 11 | { 12 | public delegate void TextClippedEvent(string windowTitle, string text); 13 | 14 | private const int MOD_NOREPEAT = 0x4000; 15 | public const int C_KEY = 0x43; 16 | public static int MOD_ALT = 0x1; 17 | public static int MOD_CONTROL = 0x2; 18 | public static int MOD_SHIFT = 0x4; 19 | public static int MOD_WIN = 0x8; 20 | public static int WM_HOTKEY = 0x312; 21 | public static int HOTKEY_ID = MOD_CONTROL + MOD_SHIFT; 22 | private static int keyId = "Noterium hotkey".GetHashCode(); 23 | 24 | private readonly HotkeyBinder _hotkeyBinder = new HotkeyBinder(); 25 | private readonly object _lastHotkeyLocker = new object(); 26 | private readonly ILog _log = LogManager.GetLogger(typeof(TextClipper)); 27 | private Hotkey _hotkeyCombination; 28 | private DateTime _lastHotkey = DateTime.MinValue; 29 | 30 | private IntPtr _owner; 31 | public event TextClippedEvent OnTextClipped; 32 | 33 | [DllImport("User32.dll")] 34 | private static extern bool SetForegroundWindow(IntPtr hWnd); 35 | 36 | [DllImport("user32.dll", CharSet = CharSet.Auto)] 37 | public static extern IntPtr GetForegroundWindow(); 38 | 39 | [DllImport("user32.dll")] 40 | private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo); 41 | 42 | [DllImport("user32.dll")] 43 | private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); 44 | 45 | public void Init(IntPtr owner) 46 | { 47 | _owner = owner; 48 | 49 | _hotkeyCombination = new Hotkey(Modifiers.Control | Modifiers.Shift, Keys.C); 50 | 51 | if (_hotkeyBinder.IsHotkeyAlreadyBound(_hotkeyCombination)) 52 | return; 53 | 54 | _hotkeyBinder.Bind(_hotkeyCombination).To(HotkeyCallback); 55 | Application.ApplicationExit += Application_ApplicationExit; 56 | } 57 | 58 | private void HotkeyCallback() 59 | { 60 | _log.Debug("HotkeyCallback " + DateTime.Now); 61 | 62 | lock (_lastHotkeyLocker) 63 | { 64 | if (_lastHotkey != DateTime.MinValue) 65 | { 66 | var span = DateTime.Now - _lastHotkey; 67 | if (span.TotalMilliseconds < 1000) 68 | return; 69 | } 70 | } 71 | 72 | if (OnTextClipped != null) 73 | { 74 | lock (_lastHotkeyLocker) 75 | { 76 | _lastHotkey = DateTime.Now; 77 | } 78 | 79 | var text = GetActiveWindowsTextSelection(); 80 | var winTitle = GetActiveWindowTitle(); 81 | OnTextClipped(winTitle, text); 82 | } 83 | } 84 | 85 | private void Application_ApplicationExit(object sender, EventArgs e) 86 | { 87 | _hotkeyBinder.Unbind(_hotkeyCombination); 88 | } 89 | 90 | private void SendCtrlC(IntPtr hWnd) 91 | { 92 | uint KEYEVENTF_KEYUP = 2; 93 | byte VK_CONTROL = 0x11; 94 | SetForegroundWindow(hWnd); 95 | keybd_event(VK_CONTROL, 0, 0, 0); 96 | keybd_event(C_KEY, 0, 0, 0); //Send the C key (43 is "C") 97 | keybd_event(C_KEY, 0, KEYEVENTF_KEYUP, 0); 98 | keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); // 'Left Control Up 99 | } 100 | 101 | private string GetActiveWindowsTextSelection() 102 | { 103 | // Obtain the handle of the active window. 104 | //IntPtr handle = GetForegroundWindow(); 105 | //SendCtrlC(handle); 106 | 107 | if (Clipboard.ContainsData(DataFormats.Html)) 108 | { 109 | var html = (string) Clipboard.GetData(DataFormats.Html); 110 | 111 | var output = ClipboardHtmlHelper.ParseString(html); 112 | 113 | if (!string.IsNullOrWhiteSpace(output.Source)) return string.Format("{0}

{1}", output.Source, output.Html); 114 | return output.Html; 115 | } 116 | 117 | return Clipboard.GetText(); 118 | } 119 | 120 | private string GetActiveWindowTitle() 121 | { 122 | const int nChars = 256; 123 | var Buff = new StringBuilder(nChars); 124 | var handle = GetForegroundWindow(); 125 | 126 | if (GetWindowText(handle, Buff, nChars) > 0) return Buff.ToString(); 127 | return null; 128 | } 129 | } 130 | } -------------------------------------------------------------------------------- /src/Noterium.Core/StorageType.cs: -------------------------------------------------------------------------------- 1 | namespace Noterium.Core 2 | { 3 | public enum StorageType 4 | { 5 | Disc, 6 | DropBox, 7 | GoogleDrive, 8 | Undefined = 100 9 | } 10 | } -------------------------------------------------------------------------------- /src/Noterium.Core/TagManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using Noterium.Core.DataCarriers; 3 | 4 | namespace Noterium.Core 5 | { 6 | public class TagManager 7 | { 8 | public ObservableCollection Tags { get; set; } 9 | 10 | public void ReloadTags() 11 | { 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Noterium.Core/Utilities/FileSecurity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Security; 4 | using System.Security.Cryptography; 5 | using System.Text; 6 | using Noterium.Core.Security; 7 | 8 | namespace Noterium.Core.Utilities 9 | { 10 | public class FileSecurity 11 | { 12 | public static string Encrypt(string content, SecureString password) 13 | { 14 | return AESGCM.SimpleEncryptWithPassword(content, ConvertToUnSecureString(password)); 15 | } 16 | 17 | public static string Decrypt(string content, SecureString password) 18 | { 19 | return AESGCM.SimpleDecryptWithPassword(content, ConvertToUnSecureString(password)); 20 | } 21 | 22 | public static SecureString ConvertToSecureString(string s) 23 | { 24 | var secureStr = new SecureString(); 25 | if (s.Length > 0) 26 | foreach (var c in s.ToCharArray()) 27 | secureStr.AppendChar(c); 28 | return secureStr; 29 | } 30 | 31 | public static string ConvertToUnSecureString(SecureString ss) 32 | { 33 | var unmanagedString = IntPtr.Zero; 34 | try 35 | { 36 | unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(ss); 37 | return Marshal.PtrToStringUni(unmanagedString); 38 | } 39 | finally 40 | { 41 | Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); 42 | } 43 | } 44 | 45 | public static byte[] GetHash(string inputString) 46 | { 47 | HashAlgorithm algorithm = MD5.Create(); //or use SHA1.Create(); 48 | return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString)); 49 | } 50 | 51 | public static string GetHashString(string inputString) 52 | { 53 | var sb = new StringBuilder(); 54 | foreach (var b in GetHash(inputString)) 55 | sb.Append(b.ToString("X2")); 56 | 57 | return sb.ToString(); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/Noterium.Core/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Noterium.Core/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Noterium.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 15 3 | VisualStudioVersion = 15.0.26228.9 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noterium.Core", "Noterium.Core\Noterium.Core.csproj", "{8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}" 6 | EndProject 7 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{DAF49F5D-F5A8-46EA-B6B6-E26B490DF6AE}" 8 | ProjectSection(SolutionItems) = preProject 9 | .nuget\NuGet.Config = .nuget\NuGet.Config 10 | .nuget\NuGet.exe = .nuget\NuGet.exe 11 | .nuget\NuGet.targets = .nuget\NuGet.targets 12 | EndProjectSection 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noterium", "Noterium\Noterium.csproj", "{D35B4D1E-B885-47CB-B0CF-546FF3F3E391}" 15 | EndProject 16 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Setup", "Setup\Setup.wixproj", "{2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}" 17 | EndProject 18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documents", "Documents", "{B5D68528-8358-4112-9FED-DE05F08AFBA6}" 19 | ProjectSection(SolutionItems) = preProject 20 | CHANGELOG.md = CHANGELOG.md 21 | EndProjectSection 22 | EndProject 23 | Global 24 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 25 | Debug|Any CPU = Debug|Any CPU 26 | Debug|Mixed Platforms = Debug|Mixed Platforms 27 | Debug|x64 = Debug|x64 28 | Debug|x86 = Debug|x86 29 | Release|Any CPU = Release|Any CPU 30 | Release|Mixed Platforms = Release|Mixed Platforms 31 | Release|x64 = Release|x64 32 | Release|x86 = Release|x86 33 | EndGlobalSection 34 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 35 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 38 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 39 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Debug|x64.ActiveCfg = Debug|x64 40 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Debug|x64.Build.0 = Debug|x64 41 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Debug|x86.ActiveCfg = Debug|x86 42 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Debug|x86.Build.0 = Debug|x86 43 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Release|Any CPU.Build.0 = Release|Any CPU 45 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 46 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Release|Mixed Platforms.Build.0 = Release|Any CPU 47 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Release|x64.ActiveCfg = Release|x64 48 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Release|x64.Build.0 = Release|x64 49 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Release|x86.ActiveCfg = Release|x86 50 | {8DAEFFC0-4370-4F9F-A9E9-528D0E9FF2E4}.Release|x86.Build.0 = Release|x86 51 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 52 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Debug|Any CPU.Build.0 = Debug|Any CPU 53 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 54 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 55 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Debug|x64.ActiveCfg = Debug|Any CPU 56 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Debug|x86.ActiveCfg = Debug|x86 57 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Debug|x86.Build.0 = Debug|x86 58 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Release|Any CPU.ActiveCfg = Release|Any CPU 59 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Release|Any CPU.Build.0 = Release|Any CPU 60 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 61 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Release|Mixed Platforms.Build.0 = Release|Any CPU 62 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Release|x64.ActiveCfg = Release|Any CPU 63 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Release|x86.ActiveCfg = Release|x86 64 | {D35B4D1E-B885-47CB-B0CF-546FF3F3E391}.Release|x86.Build.0 = Release|x86 65 | {2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}.Debug|Any CPU.ActiveCfg = Debug|x86 66 | {2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 67 | {2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}.Debug|x64.ActiveCfg = Debug|x86 68 | {2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}.Debug|x86.ActiveCfg = Debug|x86 69 | {2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}.Release|Any CPU.ActiveCfg = Release|x86 70 | {2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}.Release|Any CPU.Build.0 = Release|x86 71 | {2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}.Release|Mixed Platforms.ActiveCfg = Release|x86 72 | {2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}.Release|Mixed Platforms.Build.0 = Release|x86 73 | {2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}.Release|x64.ActiveCfg = Release|x86 74 | {2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}.Release|x86.ActiveCfg = Release|x86 75 | {2338CB08-8C33-4E4E-8E63-DB6922EFF3AD}.Release|x86.Build.0 = Release|x86 76 | EndGlobalSection 77 | GlobalSection(SolutionProperties) = preSolution 78 | HideSolutionNode = FALSE 79 | EndGlobalSection 80 | GlobalSection(ExtensibilityGlobals) = postSolution 81 | RESX_AutoCreateNewLanguageFiles = True 82 | EndGlobalSection 83 | EndGlobal 84 | -------------------------------------------------------------------------------- /src/Noterium/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/Noterium/App.xaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 14 | 15 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Noterium/Code/AttachedProperties/HyperlinkExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Windows; 3 | using System.Windows.Documents; 4 | using System.Windows.Navigation; 5 | 6 | namespace Noterium.Code.AttachedProperties 7 | { 8 | public static class HyperlinkExtensions 9 | { 10 | public static readonly DependencyProperty IsExternalProperty = 11 | DependencyProperty.RegisterAttached("IsExternal", typeof(bool), typeof(HyperlinkExtensions), new UIPropertyMetadata(false, OnIsExternalChanged)); 12 | 13 | public static bool GetIsExternal(DependencyObject obj) 14 | { 15 | return (bool) obj.GetValue(IsExternalProperty); 16 | } 17 | 18 | public static void SetIsExternal(DependencyObject obj, bool value) 19 | { 20 | obj.SetValue(IsExternalProperty, value); 21 | } 22 | 23 | private static void OnIsExternalChanged(object sender, DependencyPropertyChangedEventArgs args) 24 | { 25 | var hyperlink = sender as Hyperlink; 26 | if (hyperlink == null) 27 | return; 28 | 29 | if ((bool) args.NewValue) 30 | hyperlink.RequestNavigate += HyperlinkRequestNavigate; 31 | else 32 | hyperlink.RequestNavigate -= HyperlinkRequestNavigate; 33 | } 34 | 35 | private static void HyperlinkRequestNavigate(object sender, RequestNavigateEventArgs e) 36 | { 37 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri)); 38 | e.Handled = true; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/Noterium/Code/AttachedProperties/RichTextboxAssistant.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Data; 4 | using System.Windows.Documents; 5 | 6 | namespace Noterium.Code.AttachedProperties 7 | { 8 | public static class RichTextboxAssistant 9 | { 10 | public static readonly DependencyProperty BoundDocument = 11 | DependencyProperty.RegisterAttached("BoundDocument", typeof(FlowDocument), typeof(RichTextboxAssistant), 12 | new FrameworkPropertyMetadata(null, 13 | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 14 | OnBoundDocumentChanged) 15 | ); 16 | 17 | private static void OnBoundDocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 18 | { 19 | var box = d as RichTextBox; 20 | 21 | if (box == null) 22 | return; 23 | 24 | RemoveEventHandler(box); 25 | 26 | var newXaml = GetBoundDocument(d); 27 | 28 | box.Document = newXaml; 29 | //box.Document.Blocks.Clear(); 30 | 31 | //if (!string.IsNullOrEmpty(newXAML)) 32 | //{ 33 | // using (MemoryStream xamlMemoryStream = new MemoryStream(Encoding.ASCII.GetBytes(newXAML))) 34 | // { 35 | // ParserContext parser = new ParserContext(); 36 | // parser.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation"); 37 | // parser.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml"); 38 | // FlowDocument doc = new FlowDocument(); 39 | // Section section = XamlReader.Load(xamlMemoryStream, parser) as Section; 40 | 41 | // box.Document.Blocks.Add(section); 42 | 43 | // } 44 | //} 45 | 46 | AttachEventHandler(box); 47 | } 48 | 49 | private static void RemoveEventHandler(RichTextBox box) 50 | { 51 | var binding = BindingOperations.GetBinding(box, BoundDocument); 52 | 53 | if (binding != null) 54 | { 55 | if (binding.UpdateSourceTrigger == UpdateSourceTrigger.Default || 56 | binding.UpdateSourceTrigger == UpdateSourceTrigger.LostFocus) 57 | box.LostFocus -= HandleLostFocus; 58 | else 59 | box.TextChanged -= HandleTextChanged; 60 | } 61 | } 62 | 63 | private static void AttachEventHandler(RichTextBox box) 64 | { 65 | var binding = BindingOperations.GetBinding(box, BoundDocument); 66 | 67 | if (binding != null) 68 | { 69 | if (binding.UpdateSourceTrigger == UpdateSourceTrigger.Default || 70 | binding.UpdateSourceTrigger == UpdateSourceTrigger.LostFocus) 71 | box.LostFocus += HandleLostFocus; 72 | else 73 | box.TextChanged += HandleTextChanged; 74 | } 75 | } 76 | 77 | private static void HandleLostFocus(object sender, RoutedEventArgs e) 78 | { 79 | var box = sender as RichTextBox; 80 | 81 | //TextRange tr = new TextRange(box.Document.ContentStart, box.Document.ContentEnd); 82 | 83 | //using (MemoryStream ms = new MemoryStream()) 84 | //{ 85 | // tr.Save(ms, DataFormats.Xaml); 86 | // string xamlText = ASCIIEncoding.Default.GetString(ms.ToArray()); 87 | // SetBoundDocument(box, xamlText); 88 | //} 89 | if (box != null) 90 | SetBoundDocument(box, box.Document); 91 | } 92 | 93 | private static void HandleTextChanged(object sender, RoutedEventArgs e) 94 | { 95 | // TODO: TextChanged is currently not working! 96 | var box = sender as RichTextBox; 97 | 98 | //TextRange tr = new TextRange(box.Document.ContentStart, box.Document.ContentEnd); 99 | 100 | //using (MemoryStream ms = new MemoryStream()) 101 | //{ 102 | // tr.Save(ms, DataFormats.Xaml); 103 | // string xamlText = ASCIIEncoding.Default.GetString(ms.ToArray()); 104 | // SetBoundDocument(box, box.Document); 105 | //} 106 | if (box != null) 107 | SetBoundDocument(box, box.Document); 108 | } 109 | 110 | public static FlowDocument GetBoundDocument(DependencyObject dp) 111 | { 112 | var fd = dp.GetValue(BoundDocument) as FlowDocument; 113 | return fd ?? new FlowDocument(); 114 | } 115 | 116 | public static void SetBoundDocument(DependencyObject dp, FlowDocument value) 117 | { 118 | //dp.SetValue(BoundDocument, value); 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /src/Noterium/Code/AttachedProperties/ScrollSpeed.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | using System.Windows.Input; 5 | using System.Windows.Media; 6 | 7 | namespace Noterium.Code.AttachedProperties 8 | { 9 | public class ScrollHelper 10 | { 11 | public static readonly DependencyProperty ScrollSpeedProperty = 12 | DependencyProperty.RegisterAttached( 13 | "ScrollSpeed", 14 | typeof(double), 15 | typeof(ScrollHelper), 16 | new FrameworkPropertyMetadata( 17 | 1.0, 18 | FrameworkPropertyMetadataOptions.Inherits & FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 19 | OnScrollSpeedChanged)); 20 | 21 | public static double GetScrollSpeed(DependencyObject obj) 22 | { 23 | return (double) obj.GetValue(ScrollSpeedProperty); 24 | } 25 | 26 | public static void SetScrollSpeed(DependencyObject obj, double value) 27 | { 28 | obj.SetValue(ScrollSpeedProperty, value); 29 | } 30 | 31 | public static DependencyObject GetScrollViewer(DependencyObject o) 32 | { 33 | // Return the DependencyObject if it is a ScrollViewer 34 | if (o is ScrollViewer) return o; 35 | 36 | for (var i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++) 37 | { 38 | var child = VisualTreeHelper.GetChild(o, i); 39 | 40 | var result = GetScrollViewer(child); 41 | if (result == null) 42 | continue; 43 | return result; 44 | } 45 | 46 | return null; 47 | } 48 | 49 | private static void OnScrollSpeedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 50 | { 51 | var host = o as UIElement; 52 | host.PreviewMouseWheel += OnPreviewMouseWheelScrolled; 53 | } 54 | 55 | private static void OnPreviewMouseWheelScrolled(object sender, MouseWheelEventArgs e) 56 | { 57 | var scrollHost = sender as DependencyObject; 58 | 59 | var scrollSpeed = (double) scrollHost.GetValue(ScrollSpeedProperty); 60 | 61 | var scrollViewer = GetScrollViewer(scrollHost) as ScrollViewer; 62 | 63 | if (scrollViewer != null) 64 | { 65 | var offset = scrollViewer.VerticalOffset - e.Delta * scrollSpeed / 6; 66 | if (offset < 0) 67 | scrollViewer.ScrollToVerticalOffset(0); 68 | else if (offset > scrollViewer.ExtentHeight) 69 | scrollViewer.ScrollToVerticalOffset(scrollViewer.ExtentHeight); 70 | else 71 | scrollViewer.ScrollToVerticalOffset(offset); 72 | 73 | e.Handled = true; 74 | } 75 | else 76 | { 77 | throw new NotSupportedException("ScrollSpeed Attached Property is not attached to an element containing a ScrollViewer."); 78 | } 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Behaviors/DataGridBehavior.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using System.Windows.Controls.Primitives; 6 | using System.Windows.Media; 7 | 8 | namespace Noterium.Code.Behaviors 9 | { 10 | public class DataGridBehavior 11 | { 12 | #region DisplayRowNumber 13 | 14 | public static DependencyProperty DisplayRowNumberProperty = DependencyProperty.RegisterAttached("DisplayRowNumber", typeof(bool), typeof(DataGridBehavior), new FrameworkPropertyMetadata(false, OnDisplayRowNumberChanged)); 15 | 16 | public static bool GetDisplayRowNumber(DependencyObject target) 17 | { 18 | return (bool) target.GetValue(DisplayRowNumberProperty); 19 | } 20 | 21 | public static void SetDisplayRowNumber(DependencyObject target, bool value) 22 | { 23 | target.SetValue(DisplayRowNumberProperty, value); 24 | } 25 | 26 | private static void OnDisplayRowNumberChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 27 | { 28 | var dataGrid = target as DataGrid; 29 | if ((bool) e.NewValue) 30 | { 31 | EventHandler loadedRowHandler = null; 32 | loadedRowHandler = (sender, ea) => 33 | { 34 | if (GetDisplayRowNumber(dataGrid) == false) 35 | { 36 | dataGrid.LoadingRow -= loadedRowHandler; 37 | return; 38 | } 39 | 40 | ea.Row.Header = ea.Row.GetIndex(); 41 | }; 42 | dataGrid.LoadingRow += loadedRowHandler; 43 | 44 | ItemsChangedEventHandler itemsChangedHandler = null; 45 | itemsChangedHandler = (sender, ea) => 46 | { 47 | if (GetDisplayRowNumber(dataGrid) == false) 48 | { 49 | dataGrid.ItemContainerGenerator.ItemsChanged -= itemsChangedHandler; 50 | return; 51 | } 52 | 53 | GetVisualChildCollection(dataGrid).ForEach(d => d.Header = d.GetIndex()); 54 | }; 55 | dataGrid.ItemContainerGenerator.ItemsChanged += itemsChangedHandler; 56 | } 57 | } 58 | 59 | #endregion // DisplayRowNumber 60 | 61 | #region Get Visuals 62 | 63 | private static List GetVisualChildCollection(object parent) where T : Visual 64 | { 65 | var visualCollection = new List(); 66 | GetVisualChildCollection(parent as DependencyObject, visualCollection); 67 | return visualCollection; 68 | } 69 | 70 | private static void GetVisualChildCollection(DependencyObject parent, List visualCollection) where T : Visual 71 | { 72 | var count = VisualTreeHelper.GetChildrenCount(parent); 73 | for (var i = 0; i < count; i++) 74 | { 75 | var child = VisualTreeHelper.GetChild(parent, i); 76 | if (child is T) visualCollection.Add(child as T); 77 | if (child != null) GetVisualChildCollection(child, visualCollection); 78 | } 79 | } 80 | 81 | #endregion // Get Visuals 82 | } 83 | } -------------------------------------------------------------------------------- /src/Noterium/Code/BoundObservableCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Collections.Specialized; 5 | using System.Linq; 6 | 7 | namespace Noterium.Code 8 | { 9 | public class BoundObservableCollection : ObservableCollection 10 | { 11 | private readonly Func _converter; 12 | private readonly Func _isSameSource; 13 | private readonly ObservableCollection _source; 14 | 15 | public BoundObservableCollection( 16 | ObservableCollection source, 17 | Func converter, 18 | Func isSameSource) 19 | { 20 | _source = source; 21 | _converter = converter; 22 | _isSameSource = isSameSource; 23 | 24 | // Copy items 25 | AddItems(_source); 26 | 27 | // Subscribe to the source's CollectionChanged event 28 | _source.CollectionChanged += SourceCollectionChanged; 29 | } 30 | 31 | private void AddItems(IEnumerable items) 32 | { 33 | foreach (var sourceItem in items) Add(_converter(sourceItem)); 34 | } 35 | 36 | private void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 37 | { 38 | switch (e.Action) 39 | { 40 | case NotifyCollectionChangedAction.Add: 41 | AddItems(e.NewItems.Cast()); 42 | break; 43 | case NotifyCollectionChangedAction.Move: 44 | // Not sure what to do here... 45 | 46 | break; 47 | case NotifyCollectionChangedAction.Remove: 48 | foreach (var sourceItem in e.OldItems.Cast()) 49 | { 50 | var toRemove = this.First(item => _isSameSource(item, sourceItem)); 51 | Remove(toRemove); 52 | } 53 | 54 | break; 55 | case NotifyCollectionChangedAction.Replace: 56 | for (var i = e.NewStartingIndex; i < e.NewItems.Count; i++) this[i] = _converter((TSource) e.NewItems[i]); 57 | break; 58 | case NotifyCollectionChangedAction.Reset: 59 | Clear(); 60 | AddItems(_source); 61 | break; 62 | } 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Commands/CustomCommandInvoker.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Input; 3 | using System.Windows.Interactivity; 4 | 5 | namespace Noterium.Code.Commands 6 | { 7 | public sealed class CustomCommandInvoker : TriggerAction 8 | { 9 | public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CustomCommandInvoker), null); 10 | 11 | public ICommand Command 12 | { 13 | get => (ICommand) GetValue(CommandProperty); 14 | set => SetValue(CommandProperty, value); 15 | } 16 | 17 | protected override void Invoke(object parameter) 18 | { 19 | if (AssociatedObject != null) 20 | { 21 | var command = Command; 22 | if (command != null && command.CanExecute(parameter)) command.Execute(parameter); 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Commands/NoteFileCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | using Noterium.Core.DataCarriers; 4 | 5 | namespace Noterium.Code.Commands 6 | { 7 | public class NoteFileCommand : ICommand 8 | { 9 | public NoteFileCommand(Func function) 10 | { 11 | Function = function; 12 | } 13 | 14 | public Func Function { get; internal set; } 15 | 16 | public bool CanExecute(object parameter) 17 | { 18 | return Function != null; 19 | } 20 | 21 | public void Execute(object parameter) 22 | { 23 | Function((NoteFile) parameter); 24 | } 25 | 26 | public event EventHandler CanExecuteChanged 27 | { 28 | add => CommandManager.RequerySuggested += value; 29 | remove => CommandManager.RequerySuggested -= value; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Commands/SimpleCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | 4 | namespace Noterium.Code.Commands 5 | { 6 | public class SimpleCommand : ICommand 7 | { 8 | public SimpleCommand(Action action) 9 | { 10 | ExecuteDelegate = action; 11 | } 12 | 13 | public Predicate CanExecuteDelegate { get; set; } 14 | public Action ExecuteDelegate { get; } 15 | 16 | public bool CanExecute(object parameter) 17 | { 18 | if (CanExecuteDelegate != null) 19 | return CanExecuteDelegate(parameter); 20 | return true; // if there is no can execute default to true 21 | } 22 | 23 | public event EventHandler CanExecuteChanged 24 | { 25 | add => CommandManager.RequerySuggested += value; 26 | remove => CommandManager.RequerySuggested -= value; 27 | } 28 | 29 | public void Execute(object parameter) 30 | { 31 | ExecuteDelegate?.Invoke(parameter); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Controls/BindingProxy.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace Noterium.Code.Controls 4 | { 5 | public class BindingProxy : Freezable 6 | { 7 | // Using a DependencyProperty as the backing store for Data. 8 | // This enables animation, styling, binding, etc... 9 | public static readonly DependencyProperty DataProperty = 10 | DependencyProperty.Register("Data", typeof(object), 11 | typeof(BindingProxy), new UIPropertyMetadata(null)); 12 | 13 | public object Data 14 | { 15 | get => GetValue(DataProperty); 16 | set => SetValue(DataProperty, value); 17 | } 18 | 19 | protected override Freezable CreateInstanceCore() 20 | { 21 | return new BindingProxy(); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Converters/BindingNullConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | 6 | namespace Noterium.Code.Converters 7 | { 8 | public class BindingNullConverter : IValueConverter 9 | { 10 | public BindingNullConverter(T trueValue, T falseValue) 11 | { 12 | True = trueValue; 13 | False = falseValue; 14 | } 15 | 16 | public T True { get; set; } 17 | public T False { get; set; } 18 | 19 | public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | return value == null ? True : False; 22 | } 23 | 24 | public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 25 | { 26 | return value is T && EqualityComparer.Default.Equals((T) value, True); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Converters/BindingNullToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace Noterium.Code.Converters 4 | { 5 | public sealed class BindingNullToVisibilityConverter : BindingNullConverter 6 | { 7 | public BindingNullToVisibilityConverter() : 8 | base(Visibility.Visible, Visibility.Collapsed) 9 | { 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Converters/BooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | 6 | namespace Noterium.Code.Converters 7 | { 8 | public class BooleanConverter : IValueConverter 9 | { 10 | public BooleanConverter(T trueValue, T falseValue) 11 | { 12 | True = trueValue; 13 | False = falseValue; 14 | } 15 | 16 | public T True { get; set; } 17 | public T False { get; set; } 18 | 19 | public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | return value is bool && (bool) value ? True : False; 22 | } 23 | 24 | public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 25 | { 26 | return value is T && EqualityComparer.Default.Equals((T) value, True); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Converters/BooleanToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace Noterium.Code.Converters 4 | { 5 | public sealed class BooleanToVisibilityConverter : BooleanConverter 6 | { 7 | public BooleanToVisibilityConverter() : 8 | base(Visibility.Visible, Visibility.Collapsed) 9 | { 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Converters/MultiValueBindingConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace Noterium.Code.Converters 6 | { 7 | public class MultiValueBindingConverter : IMultiValueConverter 8 | { 9 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | return values.Clone(); 12 | } 13 | 14 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 15 | { 16 | throw new NotImplementedException(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Converters/StaticResourceConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace Noterium.Code.Converters 7 | { 8 | public class StaticResourceConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | var resourceKey = (string) value; 13 | 14 | return Application.Current.Resources[resourceKey]; 15 | } 16 | 17 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 18 | { 19 | throw new Exception("The method or operation is not implemented."); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Converters/XamlTextToFlowDocumentConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.IO; 4 | using System.Windows; 5 | using System.Windows.Data; 6 | using System.Windows.Documents; 7 | using System.Windows.Markup; 8 | using System.Xml; 9 | 10 | namespace Noterium.Code.Converters 11 | { 12 | public class XamlTextToFlowDocumentConverter : DependencyObject, IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | if (value == null) 17 | return null; 18 | 19 | if (!(value is string)) 20 | return null; 21 | 22 | var text = (string) value; 23 | 24 | if (string.IsNullOrWhiteSpace(text)) 25 | return new FlowDocument(); 26 | 27 | return GetNewDocument(text); 28 | } 29 | 30 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 31 | { 32 | throw new NotImplementedException(); 33 | } 34 | 35 | public FlowDocument GetNewDocument(string xamlString) 36 | { 37 | var stringReader = new StringReader(xamlString); 38 | var xmlReader = XmlReader.Create(stringReader); 39 | return XamlReader.Load(xmlReader) as FlowDocument; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Data/DocumentEntitiy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ICSharpCode.AvalonEdit.Document; 3 | 4 | namespace Noterium.Code.Data 5 | { 6 | public class DocumentEntitiy 7 | { 8 | public delegate void DocumentEntitiyDeleted(DocumentEntitiy ent); 9 | 10 | public DocumentEntitiy(TextAnchor start, TextAnchor end) 11 | { 12 | StartIndex = start; 13 | EndIndex = end; 14 | 15 | StartIndex.Deleted += AnchorDeleted; 16 | EndIndex.Deleted += AnchorDeleted; 17 | } 18 | 19 | public EntityType Type { get; set; } 20 | public TextAnchor StartIndex { get; } 21 | public TextAnchor EndIndex { get; } 22 | 23 | public ISegment Segment { get; set; } 24 | 25 | public event DocumentEntitiyDeleted Deleted; 26 | 27 | private void AnchorDeleted(object sender, EventArgs eventArgs) 28 | { 29 | Deleted?.Invoke(this); 30 | } 31 | 32 | public bool InRange(int carretIndex) 33 | { 34 | if (StartIndex.IsDeleted) 35 | return false; 36 | 37 | return StartIndex.Offset <= carretIndex && EndIndex.Offset >= carretIndex; 38 | } 39 | } 40 | 41 | public enum EntityType 42 | { 43 | Image, 44 | List, 45 | Anchor, 46 | SimpleAnchor, 47 | Table 48 | } 49 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Extensions/SecureStringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Security; 4 | 5 | namespace Noterium.Code.Extensions 6 | { 7 | public static class SecureStringExtensions 8 | { 9 | public static bool IsEqualTo(this SecureString ss1, SecureString ss2) 10 | { 11 | var bstr1 = IntPtr.Zero; 12 | var bstr2 = IntPtr.Zero; 13 | try 14 | { 15 | bstr1 = Marshal.SecureStringToBSTR(ss1); 16 | bstr2 = Marshal.SecureStringToBSTR(ss2); 17 | var length1 = Marshal.ReadInt32(bstr1, -4); 18 | var length2 = Marshal.ReadInt32(bstr2, -4); 19 | if (length1 == length2) 20 | for (var x = 0; x < length1; ++x) 21 | { 22 | var b1 = Marshal.ReadByte(bstr1, x); 23 | var b2 = Marshal.ReadByte(bstr2, x); 24 | if (b1 != b2) return false; 25 | } 26 | else return false; 27 | 28 | return true; 29 | } 30 | finally 31 | { 32 | if (bstr2 != IntPtr.Zero) Marshal.ZeroFreeBSTR(bstr2); 33 | if (bstr1 != IntPtr.Zero) Marshal.ZeroFreeBSTR(bstr1); 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Helpers/DialogHelpers.cs: -------------------------------------------------------------------------------- 1 | using MahApps.Metro.Controls.Dialogs; 2 | 3 | namespace Noterium.Code.Helpers 4 | { 5 | public static class DialogHelpers 6 | { 7 | public static MetroDialogSettings GetDefaultDialogSettings() 8 | { 9 | var settings = new MetroDialogSettings(); 10 | settings.AnimateShow = false; 11 | settings.AnimateHide = false; 12 | settings.DefaultButtonFocus = MessageDialogResult.Negative; 13 | settings.ColorScheme = MetroDialogColorScheme.Theme; 14 | return settings; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Helpers/NoteMathHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Text.RegularExpressions; 5 | using org.mariuszgromada.math.mxparser; 6 | 7 | namespace Noterium.Code.Helpers 8 | { 9 | public static class NoteMathHelper 10 | { 11 | public static Regex Math = new Regex(@"(\$\$) (?=\S) (.+?[$]*) (?<=\S) \1", 12 | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled); 13 | 14 | public static Regex ConstantVariables = new Regex(@"\$\$var[\s]*?(?[a-zA-Z]*?)[\s]*?=[\s]*?(?[1-9\.\,]*?)\$\$", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.ExplicitCapture); 15 | 16 | public static string ReplaceMathTokens(string text) 17 | { 18 | var vars = InitMathConstants(text); 19 | RemoveMathConstants(ref text); 20 | text = ReplaceMathTokensPrivate(text, vars); 21 | return text; 22 | } 23 | 24 | private static void RemoveMathConstants(ref string text) 25 | { 26 | var lines = text.Split('\n'); 27 | var result = new List(); 28 | foreach (var l in lines) 29 | if (!l.StartsWith("$$var")) 30 | result.Add(l); 31 | 32 | text = string.Join("\n", result); 33 | } 34 | 35 | private static string ReplaceMathTokensPrivate(string text, Constant[] constants) 36 | { 37 | var match = Math.Match(text); 38 | while (match.Success) 39 | { 40 | text = text.Remove(match.Index, match.Length); 41 | var result = "**Invalid math expression**"; 42 | 43 | try 44 | { 45 | var e = new Expression(match.Value.Trim('$'), constants); 46 | var expressionResult = e.calculate(); 47 | 48 | if (!double.IsNaN(expressionResult)) 49 | result = expressionResult.ToString("N", CultureInfo.InvariantCulture); 50 | } 51 | catch (Exception) 52 | { 53 | } 54 | 55 | text = text.Insert(match.Index, result); 56 | 57 | match = Math.Match(text); 58 | } 59 | 60 | return text; 61 | } 62 | 63 | private static Constant[] InitMathConstants(string text) 64 | { 65 | if (text == null) throw new ArgumentNullException(nameof(text)); 66 | 67 | var mathParams = new List(); 68 | 69 | var matches = ConstantVariables.Matches(text); 70 | foreach (Match m in matches) 71 | { 72 | var name = m.Groups[1].Value; 73 | var value = m.Groups[2].Value; 74 | 75 | double doubleValue; 76 | if (double.TryParse(value, out doubleValue)) 77 | mathParams.Add(new Constant(name, doubleValue)); 78 | } 79 | 80 | return mathParams.ToArray(); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Interfaces/IMainMenuItem.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using Noterium.Code.Messages; 3 | using Noterium.ViewModels; 4 | 5 | namespace Noterium.Code.Interfaces 6 | { 7 | public interface IMainMenuItem 8 | { 9 | string Name { get; } 10 | 11 | MenuItemType MenuItemType { get; } 12 | 13 | ObservableCollection Notes { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Interfaces/INoteMenuItem.cs: -------------------------------------------------------------------------------- 1 | using Noterium.Core.DataCarriers; 2 | 3 | namespace Noterium.Code.Interfaces 4 | { 5 | public interface INoteMenuItem 6 | { 7 | Note Note { get; } 8 | string ShortDescription { get; } 9 | bool Secure { get; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Noterium/Code/ListViewDragDrop/MouseUtilities.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 4 | using System.Windows.Media; 5 | 6 | namespace Noterium.Code.ListViewDragDrop 7 | { 8 | /// 9 | /// Provides access to the mouse location by calling unmanaged code. 10 | /// 11 | /// 12 | /// This class was written by Dan Crevier (Microsoft). 13 | /// http://blogs.msdn.com/llobo/archive/2006/09/06/Scrolling-Scrollviewer-on-Mouse-Drag-at-the-boundaries.aspx 14 | /// 15 | public class MouseUtilities 16 | { 17 | [DllImport("user32.dll")] 18 | private static extern bool GetCursorPos(ref Win32Point pt); 19 | 20 | [DllImport("user32.dll")] 21 | public static extern bool ScreenToClient(IntPtr hwnd, ref Win32Point pt); 22 | 23 | /// 24 | /// Returns the mouse cursor location. This method is necessary during 25 | /// a drag-drop operation because the WPF mechanisms for retrieving the 26 | /// cursor coordinates are unreliable. 27 | /// 28 | /// The Visual to which the mouse coordinates will be relative. 29 | public static Point GetMousePosition(Visual relativeTo) 30 | { 31 | var mouse = new Win32Point(); 32 | GetCursorPos(ref mouse); 33 | 34 | // Using PointFromScreen instead of Dan Crevier's code (commented out below) 35 | // is a bug fix created by William J. Roberts. Read his comments about the fix 36 | // here: http://www.codeproject.com/useritems/ListViewDragDropManager.asp?msg=1911611#xx1911611xx 37 | return relativeTo.PointFromScreen(new Point(mouse.X, mouse.Y)); 38 | 39 | #region Commented Out 40 | 41 | //System.Windows.Interop.HwndSource presentationSource = 42 | // (System.Windows.Interop.HwndSource)PresentationSource.FromVisual( relativeTo ); 43 | //ScreenToClient( presentationSource.Handle, ref mouse ); 44 | //GeneralTransform transform = relativeTo.TransformToAncestor( presentationSource.RootVisual ); 45 | //Point offset = transform.Transform( new Point( 0, 0 ) ); 46 | //return new Point( mouse.X - offset.X, mouse.Y - offset.Y ); 47 | 48 | #endregion // Commented Out 49 | } 50 | 51 | [StructLayout(LayoutKind.Sequential)] 52 | public struct Win32Point 53 | { 54 | public int X { get; set; } 55 | 56 | public int Y { get; set; } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Markdown/LinkInlineRenderer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2017 Nicolas Musset. All rights reserved. 2 | // This file is licensed under the MIT license. 3 | // See the LICENSE.md file in the project root for more information. 4 | 5 | using System; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Documents; 9 | using System.Windows.Media.Imaging; 10 | using Markdig.Syntax.Inlines; 11 | using Markdig.Wpf; 12 | using Noterium.Properties; 13 | 14 | namespace Noterium.Code.Markdown 15 | { 16 | /// 17 | /// A WPF renderer for a . 18 | /// 19 | /// 20 | public class LinkInlineRenderer : Markdig.Renderers.Wpf.Inlines.LinkInlineRenderer 21 | { 22 | /// 23 | protected override void Write([NotNull] Markdig.Renderers.WpfRenderer renderer, [NotNull] LinkInline link) 24 | { 25 | var url = link.GetDynamicUrl != null ? link.GetDynamicUrl() ?? link.Url : link.Url; 26 | 27 | if (!Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute)) 28 | { 29 | url = "#"; 30 | } 31 | 32 | if (link.IsImage) 33 | { 34 | var image = new Image 35 | { 36 | Source = new BitmapImage(new Uri(url, UriKind.RelativeOrAbsolute)) 37 | }; 38 | 39 | image.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.ImageStyleKey); 40 | 41 | renderer.WriteInline(new InlineUIContainer(image)); 42 | } 43 | else 44 | { 45 | var hyperlink = new Hyperlink 46 | { 47 | Command = Markdig.Wpf.Commands.Hyperlink, 48 | CommandParameter = url, 49 | NavigateUri = new Uri(url, UriKind.RelativeOrAbsolute), 50 | ToolTip = link.Title != string.Empty ? link.Title : null, 51 | }; 52 | 53 | hyperlink.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.HyperlinkStyleKey); 54 | 55 | renderer.Push(hyperlink); 56 | renderer.WriteChildren(link); 57 | renderer.Pop(); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Noterium/Code/Markdown/TaskListRenderer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2017 Nicolas Musset. All rights reserved. 2 | // This file is licensed under the MIT license. 3 | // See the LICENSE.md file in the project root for more information. 4 | 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Documents; 8 | using System.Windows.Input; 9 | using Markdig.Extensions.TaskLists; 10 | using Markdig.Renderers.Wpf; 11 | using Markdig.Wpf; 12 | using Noterium.Properties; 13 | 14 | namespace Noterium.Code.Markdown 15 | { 16 | public class TaskListRenderer : Markdig.Renderers.Wpf.Extensions.TaskListRenderer 17 | { 18 | public static RoutedCommand TaskListItemChanged { get; } = new RoutedCommand(nameof(Hyperlink), typeof(TaskListRenderer)); 19 | 20 | private int _checkCount = 0; 21 | protected override void Write([NotNull] Markdig.Renderers.WpfRenderer renderer, [NotNull] TaskList taskList) 22 | { 23 | var checkBox = new CheckBox 24 | { 25 | IsChecked = taskList.Checked, 26 | Tag = _checkCount, 27 | Command = TaskListItemChanged 28 | }; 29 | 30 | checkBox.CommandParameter = checkBox; 31 | 32 | _checkCount++; 33 | 34 | checkBox.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.TaskListStyleKey); 35 | renderer.WriteInline(new InlineUIContainer(checkBox)); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Noterium/Code/Markdown/TextToFlowDocumentConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Text; 6 | using System.Windows; 7 | using System.Windows.Data; 8 | using System.Windows.Documents; 9 | using System.Windows.Input; 10 | using System.Windows.Markup; 11 | using Markdig; 12 | using Markdig.Wpf; 13 | using Noterium.Code.Helpers; 14 | using Noterium.Core.Annotations; 15 | using Noterium.Core.DataCarriers; 16 | 17 | namespace Noterium.Code.Markdown 18 | { 19 | public class TextToFlowDocumentConverter : DependencyObject, IMultiValueConverter 20 | { 21 | private string _text; 22 | 23 | public bool Pause { get; set; } 24 | public Note CurrentNote { get; set; } 25 | 26 | public FlowDocument CurrentDocument { get; set; } 27 | 28 | /// 29 | /// Converts a value. 30 | /// 31 | /// 32 | /// A converted value. If the method returns null, the valid null value is used. 33 | /// 34 | /// The value produced by the binding source. 35 | /// The type of the binding target property. 36 | /// The converter parameter to use. 37 | /// The culture to use in the converter. 38 | public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture) 39 | { 40 | if (Pause) 41 | return CurrentDocument; 42 | 43 | if (value == null || value.Length != 2) 44 | return null; 45 | 46 | if (!(value[0] is string)) 47 | return null; 48 | 49 | _text = (string) value[0]; 50 | var searchText = (string) value[1]; 51 | 52 | if (string.IsNullOrWhiteSpace(_text)) 53 | CurrentDocument = new FlowDocument(); 54 | else 55 | CurrentDocument = GetNewDocument(); 56 | 57 | CurrentDocument.FocusVisualStyle = null; 58 | CurrentDocument.PagePadding = new Thickness(20); 59 | CurrentDocument.PreviewKeyDown += CurrentDocument_PreviewKeyDown; 60 | 61 | return CurrentDocument; 62 | } 63 | 64 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 65 | { 66 | throw new NotImplementedException(); 67 | } 68 | 69 | private static MarkdownPipeline BuildPipeline() 70 | { 71 | return new MarkdownPipelineBuilder() 72 | .UseSupportedExtensions() 73 | .Build(); 74 | } 75 | 76 | public FlowDocument GetNewDocument() 77 | { 78 | var sw = new Stopwatch(); 79 | sw.Start(); 80 | var text = NoteMathHelper.ReplaceMathTokens(_text); 81 | 82 | return ToFlowDocument(text, BuildPipeline()); 83 | } 84 | 85 | public static FlowDocument ToFlowDocument([NotNull] string markdown, MarkdownPipeline pipeline = null) 86 | { 87 | if (markdown == null) throw new ArgumentNullException(nameof(markdown)); 88 | pipeline = pipeline ?? new MarkdownPipelineBuilder().Build(); 89 | 90 | // We override the renderer with our own writer 91 | var result = new FlowDocument(); 92 | var renderer = new WpfRenderer(result); 93 | 94 | pipeline.Setup(renderer); 95 | 96 | var document = Markdig.Markdown.Parse(markdown, pipeline); 97 | renderer.Render(document); 98 | 99 | return result; 100 | } 101 | 102 | 103 | private void CurrentDocument_PreviewKeyDown(object sender, KeyEventArgs e) 104 | { 105 | if (e.SystemKey == Key.LeftCtrl && e.Key == Key.F) e.Handled = true; 106 | } 107 | 108 | /// 109 | /// Converts a value. 110 | /// 111 | /// 112 | /// A converted value. If the method returns null, the valid null value is used. 113 | /// 114 | /// The value that is produced by the binding target. 115 | /// The type to convert to. 116 | /// The converter parameter to use. 117 | /// The culture to use in the converter. 118 | public object[] ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 119 | { 120 | throw new NotImplementedException(); 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Markdown/WpfRenderer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2017 Nicolas Musset. All rights reserved. 2 | // This file is licensed under the MIT license. 3 | // See the LICENSE.md file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Runtime.CompilerServices; 8 | using System.Windows; 9 | using System.Windows.Documents; 10 | using System.Windows.Markup; 11 | using Markdig.Annotations; 12 | using Markdig.Helpers; 13 | using Markdig.Renderers; 14 | using Markdig.Renderers.Wpf; 15 | using Markdig.Renderers.Wpf.Extensions; 16 | using Markdig.Renderers.Wpf.Inlines; 17 | using Markdig.Syntax; 18 | using Markdig.Wpf; 19 | using Noterium.Properties; 20 | using Block = System.Windows.Documents.Block; 21 | 22 | namespace Noterium.Code.Markdown 23 | { 24 | /// 25 | /// WPF renderer for a Markdown object. 26 | /// 27 | /// 28 | public class WpfRenderer : Markdig.Renderers.WpfRenderer 29 | { 30 | 31 | public WpfRenderer([NotNull] FlowDocument document) : base(document) 32 | { 33 | ObjectRenderers.RemoveAt(ObjectRenderers.FindIndex(x => x is Markdig.Renderers.Wpf.Extensions.TaskListRenderer)); 34 | ObjectRenderers.Add(new TaskListRenderer()); 35 | 36 | ObjectRenderers.RemoveAt(ObjectRenderers.FindIndex(x => x is Markdig.Renderers.Wpf.Inlines.LinkInlineRenderer)); 37 | ObjectRenderers.Add(new LinkInlineRenderer()); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/ApplicationPartLoaded.cs: -------------------------------------------------------------------------------- 1 | namespace Noterium.Code.Messages 2 | { 3 | internal struct ApplicationPartLoaded 4 | { 5 | public enum ApplicationParts 6 | { 7 | NoteView, 8 | NoteMenu, 9 | NotebookMenu 10 | } 11 | 12 | public ApplicationParts Part { get; } 13 | 14 | public ApplicationPartLoaded(ApplicationParts part) 15 | { 16 | Part = part; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/ApplicationUnlocked.cs: -------------------------------------------------------------------------------- 1 | namespace Noterium.Code.Messages 2 | { 3 | internal struct ApplicationUnlocked 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/ChangeLibrary.cs: -------------------------------------------------------------------------------- 1 | using Noterium.Core.DataCarriers; 2 | 3 | namespace Noterium.Code.Messages 4 | { 5 | internal struct ChangeLibrary 6 | { 7 | public Library Library { get; } 8 | 9 | public ChangeLibrary(Library l) 10 | { 11 | Library = l; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/ChangeViewMode.cs: -------------------------------------------------------------------------------- 1 | using Noterium.Core.Constants; 2 | 3 | namespace Noterium.Code.Messages 4 | { 5 | internal struct ChangeViewMode 6 | { 7 | public NoteViewModes Mode { get; } 8 | 9 | public ChangeViewMode(NoteViewModes mode) 10 | { 11 | Mode = mode; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/ConfigureControlsForParnetType.cs: -------------------------------------------------------------------------------- 1 | namespace Noterium.Code.Messages 2 | { 3 | internal struct ConfigureControlsForParnetType 4 | { 5 | public ParentType Type { get; } 6 | 7 | public ConfigureControlsForParnetType(ParentType type) 8 | { 9 | Type = type; 10 | } 11 | 12 | public enum ParentType 13 | { 14 | Notebook, 15 | Tag, 16 | Library 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/DeleteNote.cs: -------------------------------------------------------------------------------- 1 | using Noterium.ViewModels; 2 | 3 | namespace Noterium.Code.Messages 4 | { 5 | internal struct DeleteNote 6 | { 7 | public NoteViewModel Note { get; set; } 8 | 9 | public DeleteNote(NoteViewModel note) 10 | { 11 | Note = note; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/MenuItemType.cs: -------------------------------------------------------------------------------- 1 | namespace Noterium.Code.Messages 2 | { 3 | public enum MenuItemType 4 | { 5 | Undefined, 6 | Trashcan, 7 | Favorites, 8 | All, 9 | Recent, 10 | Notebook, 11 | Tag 12 | } 13 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/QuickMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Noterium.Code.Messages 2 | { 3 | internal struct QuickMessage 4 | { 5 | public string Message { get; } 6 | 7 | public QuickMessage(string message) 8 | { 9 | Message = message; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/ReloadNoteMenuList.cs: -------------------------------------------------------------------------------- 1 | using Noterium.Core.DataCarriers; 2 | 3 | namespace Noterium.Code.Messages 4 | { 5 | internal struct ReloadNoteMenuList 6 | { 7 | public Tag Tag { get; } 8 | 9 | public Notebook Notebook { get; } 10 | 11 | public MenuItemType LibraryType { get; } 12 | 13 | public Note SelectedNote { get; } 14 | 15 | public ReloadNoteMenuList(Tag tag) 16 | { 17 | LibraryType = MenuItemType.Undefined; 18 | Notebook = null; 19 | SelectedNote = null; 20 | Tag = tag; 21 | } 22 | 23 | public ReloadNoteMenuList(Notebook notebook, Note selectedNote = null) 24 | { 25 | LibraryType = MenuItemType.Undefined; 26 | Notebook = notebook; 27 | SelectedNote = selectedNote; 28 | Tag = null; 29 | } 30 | 31 | public ReloadNoteMenuList(MenuItemType type) 32 | { 33 | LibraryType = type; 34 | Notebook = null; 35 | SelectedNote = null; 36 | Tag = null; 37 | } 38 | 39 | public bool IsEmpty() 40 | { 41 | return Tag == null && Notebook == null && SelectedNote == null && LibraryType == MenuItemType.Undefined; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/SelectNote.cs: -------------------------------------------------------------------------------- 1 | using Noterium.Core.DataCarriers; 2 | 3 | namespace Noterium.Code.Messages 4 | { 5 | internal struct SelectNote 6 | { 7 | public Note Note { get; } 8 | 9 | public SelectNote(Note note) 10 | { 11 | Note = note; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/SelectedNoteChanged.cs: -------------------------------------------------------------------------------- 1 | using Noterium.ViewModels; 2 | 3 | namespace Noterium.Code.Messages 4 | { 5 | internal struct SelectedNoteChanged 6 | { 7 | public NoteViewModel SelectedNote { get; } 8 | 9 | public SelectedNoteChanged(NoteViewModel note) 10 | { 11 | SelectedNote = note; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Noterium/Code/Messages/UpdateNoteList.cs: -------------------------------------------------------------------------------- 1 | using Noterium.Code.Interfaces; 2 | 3 | namespace Noterium.Code.Messages 4 | { 5 | internal struct UpdateNoteList 6 | { 7 | public IMainMenuItem MenuItem { get; } 8 | 9 | public UpdateNoteList(IMainMenuItem menuItem) 10 | { 11 | MenuItem = menuItem; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Noterium/Components/AuthenticationForm.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 32 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/Noterium/Components/AuthenticationForm.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | using System.Threading; 5 | using System.Windows; 6 | using System.Windows.Input; 7 | using System.Windows.Threading; 8 | using Noterium.Core; 9 | using Noterium.Properties; 10 | 11 | namespace Noterium.Components 12 | { 13 | /// 14 | /// Interaction logic for AuthenticationForm.xaml 15 | /// 16 | public partial class AuthenticationForm : INotifyPropertyChanged 17 | { 18 | public delegate void AuthenticatedEventHandler(); 19 | 20 | public delegate void CancelAuthenticationEventHandler(); 21 | 22 | private bool _onlyVerifyPassword; 23 | private int _passwordTries; 24 | 25 | public AuthenticationForm() 26 | { 27 | InitializeComponent(); 28 | IsVisibleChanged += AuthenticationFormControlIsVisibleChanged; 29 | } 30 | 31 | public bool OnlyVerifyPassword 32 | { 33 | get => _onlyVerifyPassword; 34 | set 35 | { 36 | _onlyVerifyPassword = value; 37 | OnPropertyChanged(); 38 | } 39 | } 40 | 41 | public event PropertyChangedEventHandler PropertyChanged; 42 | public event AuthenticatedEventHandler OnAuthenticated; 43 | public event CancelAuthenticationEventHandler OnAuthentionCanceled; 44 | 45 | private void AuthenticationFormControlIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) 46 | { 47 | if ((bool) e.NewValue) 48 | Dispatcher.BeginInvoke( 49 | DispatcherPriority.ContextIdle, 50 | new Action(delegate { Password.Focus(); }) 51 | ); 52 | } 53 | 54 | private void PasswordBox_OnPreviewKeyDown(object sender, KeyEventArgs e) 55 | { 56 | if (e.Key == Key.Enter && Password.SecurePassword.Length > 0) 57 | { 58 | bool sucess; 59 | 60 | try 61 | { 62 | if (_passwordTries >= 3) 63 | Thread.Sleep(3000); 64 | 65 | if (OnlyVerifyPassword) 66 | sucess = Hub.Instance.EncryptionManager.ValidatePassword(Password.SecurePassword); 67 | else 68 | sucess = Hub.Instance.EncryptionManager.Authenticate(true, Password.SecurePassword); 69 | } 70 | catch (Exception) 71 | { 72 | sucess = false; 73 | } 74 | 75 | if (sucess) 76 | { 77 | //GlowBrush = (SolidColorBrush)FindResource("AccentColorBrush"); 78 | _passwordTries = 0; 79 | e.Handled = true; 80 | OnAuthenticated?.Invoke(); 81 | //DialogResult = true; 82 | //Close(); 83 | } 84 | else 85 | { 86 | //GlowBrush = (SolidColorBrush)FindResource("ValidationBrush5"); 87 | _passwordTries++; 88 | Password.SelectAll(); 89 | } 90 | } 91 | else if (e.Key == Key.Escape) 92 | { 93 | e.Handled = true; 94 | OnAuthentionCanceled?.Invoke(); 95 | //DialogResult = null; 96 | //Close(); 97 | } 98 | } 99 | 100 | public void Reset() 101 | { 102 | Password.Clear(); 103 | Password.Focus(); 104 | } 105 | 106 | [NotifyPropertyChangedInvocator] 107 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 108 | { 109 | var handler = PropertyChanged; 110 | if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /src/Noterium/Components/NoteMenu/NoteMenu.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using Noterium.ViewModels; 3 | 4 | namespace Noterium.Components.NoteMenu 5 | { 6 | /// 7 | /// Interaction logic for NoteMenu.xaml 8 | /// 9 | public partial class NoteMenu 10 | { 11 | public NoteMenu() 12 | { 13 | InitializeComponent(); 14 | } 15 | 16 | public NoteMenuViewModel Model => DataContext as NoteMenuViewModel; 17 | 18 | private void NoteMenu_OnLoaded(object sender, RoutedEventArgs e) 19 | { 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Noterium/Components/NotebookMenu/NotebookMenu.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using System.Windows.Documents; 6 | using Noterium.ViewModels; 7 | 8 | namespace Noterium.Components.NotebookMenu 9 | { 10 | // https://github.com/punker76/gong-wpf-dragdrop 11 | 12 | 13 | /// 14 | /// Interaction logic for NotebookMenu.xaml 15 | /// 16 | public partial class NotebookMenu 17 | { 18 | public static readonly DependencyProperty AdornerLayerProperty = DependencyProperty.Register("AdornerLayer", typeof(AdornerLayer), typeof(NotebookMenu), new PropertyMetadata(null)); 19 | 20 | public static readonly DependencyProperty AdornedElementProperty = DependencyProperty.Register("AdornedElement", typeof(UIElement), typeof(NotebookMenu), new PropertyMetadata(null)); 21 | 22 | private readonly List _lists = new List(); 23 | private NotebookMenuViewModel _model; 24 | 25 | public NotebookMenu() 26 | { 27 | InitializeComponent(); 28 | 29 | _lists.Add(Tree); 30 | _lists.Add(FnissTree); 31 | _lists.Add(TagsTree); 32 | 33 | Tree.SelectionChanged += ListSelectionChanged; 34 | FnissTree.SelectionChanged += ListSelectionChanged; 35 | TagsTree.SelectionChanged += ListSelectionChanged; 36 | } 37 | 38 | public AdornerLayer AdornerLayer 39 | { 40 | get => (AdornerLayer) GetValue(AdornerLayerProperty); 41 | set => SetValue(AdornerLayerProperty, value); 42 | } 43 | 44 | 45 | public UIElement AdornedElement 46 | { 47 | get => (UIElement) GetValue(AdornedElementProperty); 48 | set => SetValue(AdornedElementProperty, value); 49 | } 50 | 51 | public NotebookMenuViewModel Model => DataContext as NotebookMenuViewModel; 52 | 53 | private void ListSelectionChanged(object sender, SelectionChangedEventArgs e) 54 | { 55 | if (e.AddedItems.Count == 0) 56 | return; 57 | 58 | var temp = _lists.Where(l => !Equals(l, sender)).ToList(); 59 | temp.ForEach(l => l.SelectedItem = null); 60 | } 61 | 62 | //private void ProcessDrop(object sender, ProcessDropEventArgs e) 63 | //{ 64 | // Log.Debug(e.DataItem.ToJson()); 65 | 66 | // /* 67 | // if (e.OldIndex > -1) 68 | // { 69 | // ContextNote.ToDos.Move(e.OldIndex, e.NewIndex); 70 | // e.ItemsSource.Move(e.OldIndex, e.NewIndex); 71 | // } 72 | // else 73 | // { 74 | // ContextNote.ToDos.Insert(e.NewIndex, e.DataItem.ToDoItem); 75 | // e.ItemsSource.Insert(e.NewIndex, e.DataItem); 76 | // } 77 | 78 | // ContextNote.Save(); 79 | // */ 80 | //} 81 | 82 | private void NotebookMenu_OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 83 | { 84 | _model = DataContext as NotebookMenuViewModel; 85 | if (_model == null || _model.Notebooks == null) 86 | return; 87 | 88 | var first = _model?.Notebooks.FirstOrDefault(); 89 | if (first != null) _model.SelectedItemChangedCommand?.Execute(first); 90 | } 91 | 92 | private void NotebookMenu_OnLoaded(object sender, RoutedEventArgs e) 93 | { 94 | //CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(Tree.ItemsSource); 95 | //PropertyGroupDescription groupDescription = new PropertyGroupDescription("Parent"); 96 | //view.GroupDescriptions.Add(groupDescription); 97 | 98 | //var listViewDragDropManager = new ListViewDragDropManager(Tree, true); 99 | //listViewDragDropManager.ProcessDrop += ProcessDrop; 100 | //listViewDragDropManager.AdornerLayer = AdornerLayer; 101 | //listViewDragDropManager.AdornedElement = AdornedElement; 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /src/Noterium/Controls/AdornedControl/AdornerPlacement.cs: -------------------------------------------------------------------------------- 1 | namespace Noterium.Controls.AdornedControl 2 | { 3 | /// 4 | /// Specifies the placement of the adorner in related to the adorned control. 5 | /// 6 | public enum AdornerPlacement 7 | { 8 | Inside, 9 | Outside 10 | } 11 | } -------------------------------------------------------------------------------- /src/Noterium/Controls/BaseUserControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | 5 | namespace Noterium.Controls 6 | { 7 | public class BaseUserControl : UserControl 8 | { 9 | public void InvokeOnCurrentDispatcher(Action a) 10 | { 11 | Application.Current.Dispatcher.Invoke(a); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/Noterium/Controls/Behaviors/AvalonEditBehavior.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Interactivity; 4 | using ICSharpCode.AvalonEdit; 5 | using Noterium.Core.DataCarriers; 6 | 7 | namespace Noterium.Controls.Behaviors 8 | { 9 | public sealed class AvalonEditBehaviour : Behavior 10 | { 11 | public static readonly DependencyProperty GiveMeTheTextProperty = 12 | DependencyProperty.Register("GiveMeTheText", typeof(string), typeof(AvalonEditBehaviour), 13 | new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, PropertyChangedCallback)); 14 | 15 | public static readonly DependencyProperty EditedNoteProperty = 16 | DependencyProperty.Register("EditedNote", typeof(Note), typeof(AvalonEditBehaviour), 17 | new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, PropertyChangedCallback)); 18 | 19 | public string GiveMeTheText 20 | { 21 | get => (string) GetValue(GiveMeTheTextProperty); 22 | set => SetValue(GiveMeTheTextProperty, value); 23 | } 24 | 25 | public Note EditedNote 26 | { 27 | get => (Note) GetValue(EditedNoteProperty); 28 | set => SetValue(EditedNoteProperty, value); 29 | } 30 | 31 | protected override void OnAttached() 32 | { 33 | base.OnAttached(); 34 | if (AssociatedObject != null) 35 | AssociatedObject.TextChanged += AssociatedObjectOnTextChanged; 36 | } 37 | 38 | protected override void OnDetaching() 39 | { 40 | base.OnDetaching(); 41 | if (AssociatedObject != null) 42 | AssociatedObject.TextChanged -= AssociatedObjectOnTextChanged; 43 | } 44 | 45 | private void AssociatedObjectOnTextChanged(object sender, EventArgs eventArgs) 46 | { 47 | var textEditor = sender as TextEditor; 48 | if (textEditor?.Document != null) GiveMeTheText = textEditor.Document.Text; 49 | } 50 | 51 | private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 52 | { 53 | var behavior = dependencyObject as AvalonEditBehaviour; 54 | if (behavior?.AssociatedObject != null && dependencyPropertyChangedEventArgs.Property == GiveMeTheTextProperty) 55 | { 56 | var editor = behavior.AssociatedObject; 57 | if (editor.Document != null) 58 | { 59 | var text = dependencyPropertyChangedEventArgs.NewValue?.ToString() ?? string.Empty; 60 | 61 | var caretOffset = editor.CaretOffset; 62 | editor.Document.Text = text; 63 | if (editor.Document.Text.Length < caretOffset) 64 | caretOffset = 0; 65 | 66 | editor.CaretOffset = caretOffset; 67 | } 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /src/Noterium/Controls/Behaviors/BindableSelectedItemBehavior.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Interactivity; 4 | 5 | namespace Noterium.Controls.Behaviors 6 | { 7 | public class BindableSelectedItemBehavior : Behavior 8 | { 9 | protected override void OnAttached() 10 | { 11 | base.OnAttached(); 12 | 13 | AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged; 14 | } 15 | 16 | protected override void OnDetaching() 17 | { 18 | base.OnDetaching(); 19 | 20 | if (AssociatedObject != null) AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged; 21 | } 22 | 23 | private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) 24 | { 25 | SelectedItem = e.NewValue; 26 | } 27 | 28 | #region SelectedItem Property 29 | 30 | public object SelectedItem 31 | { 32 | get => GetValue(SelectedItemProperty); 33 | set => SetValue(SelectedItemProperty, value); 34 | } 35 | 36 | public static readonly DependencyProperty SelectedItemProperty = 37 | DependencyProperty.Register("SelectedItem", typeof(object), typeof(BindableSelectedItemBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged)); 38 | 39 | private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 40 | { 41 | var item = e.NewValue as TreeViewItem; 42 | item?.SetValue(TreeViewItem.IsSelectedProperty, true); 43 | } 44 | 45 | #endregion 46 | } 47 | } -------------------------------------------------------------------------------- /src/Noterium/Controls/Behaviors/PasteBehavior.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.IO; 4 | using System.Windows; 5 | using System.Windows.Input; 6 | using System.Windows.Interactivity; 7 | using Noterium.Core.Helpers; 8 | 9 | namespace Noterium.Controls.Behaviors 10 | { 11 | public class PasteBehavior : Behavior 12 | { 13 | public delegate void FilePasted(FileInfo file); 14 | 15 | public delegate void HyperLinkPasted(Uri uri); 16 | 17 | public delegate void ImagePasted(Image image, string fileName); 18 | 19 | public event FilePasted OnFilePasted; 20 | public event ImagePasted OnImagePasted; 21 | public event HyperLinkPasted OnHyperLinkPasted; 22 | 23 | protected override void OnAttached() 24 | { 25 | base.OnAttached(); 26 | 27 | CommandManager.AddPreviewCanExecuteHandler(AssociatedObject, onPreviewCanExecute); 28 | CommandManager.AddPreviewExecutedHandler(AssociatedObject, OnPreviewExecuted); 29 | } 30 | 31 | private void onPreviewCanExecute(object sender, CanExecuteRoutedEventArgs e) 32 | { 33 | // In this case, we just say it always can be executed (only for a Paste command), but you can 34 | // write some checks here 35 | if (e.Command == ApplicationCommands.Paste) 36 | { 37 | e.CanExecute = true; 38 | e.Handled = true; 39 | } 40 | } 41 | 42 | private void OnPreviewExecuted(object sender, ExecutedRoutedEventArgs e) 43 | { 44 | // If it is a paste command.. 45 | if (e.Command == ApplicationCommands.Paste) 46 | if (Clipboard.ContainsImage() || Clipboard.ContainsFileDropList() || Clipboard.ContainsData(DataFormats.FileDrop)) 47 | { 48 | if (OnImagePasted != null) 49 | { 50 | var img = ClipboardHelper.GetImageFromClipboard(); 51 | if (img != null) 52 | { 53 | string fileName = null; 54 | if (Clipboard.ContainsFileDropList()) 55 | { 56 | var fileNames = Clipboard.GetFileDropList(); 57 | if (fileNames.Count > 0) fileName = fileNames[0]; 58 | } 59 | 60 | OnImagePasted(img, fileName); 61 | return; 62 | } 63 | } 64 | 65 | if (OnFilePasted != null) 66 | if (Clipboard.ContainsData(DataFormats.FileDrop)) 67 | { 68 | var files = Clipboard.GetFileDropList(); 69 | if (files.Count == 1) 70 | { 71 | var fileName = files[0]; 72 | if (File.Exists(fileName)) 73 | { 74 | var fi = new FileInfo(fileName); 75 | OnFilePasted(fi); 76 | } 77 | } 78 | } 79 | 80 | if (OnHyperLinkPasted != null) 81 | { 82 | var text = Clipboard.GetText(); 83 | if (Uri.IsWellFormedUriString(text, UriKind.Absolute)) OnHyperLinkPasted(new Uri(text)); 84 | } 85 | 86 | e.Handled = true; 87 | } 88 | } 89 | 90 | protected override void OnDetaching() 91 | { 92 | base.OnDetaching(); 93 | 94 | CommandManager.RemovePreviewExecutedHandler(AssociatedObject, OnPreviewExecuted); 95 | CommandManager.RemovePreviewCanExecuteHandler(AssociatedObject, onPreviewCanExecute); 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /src/Noterium/Controls/ColumnDefinitionExtended.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace Noterium.Controls 5 | { 6 | public class ColumnDefinitionExtended : ColumnDefinition 7 | { 8 | // Variables 9 | public static DependencyProperty VisibleProperty; 10 | 11 | // Constructors 12 | static ColumnDefinitionExtended() 13 | { 14 | VisibleProperty = DependencyProperty.Register("Visible", 15 | typeof(bool), 16 | typeof(ColumnDefinitionExtended), 17 | new PropertyMetadata(true, OnVisibleChanged)); 18 | 19 | WidthProperty.OverrideMetadata(typeof(ColumnDefinitionExtended), 20 | new FrameworkPropertyMetadata(new GridLength(1, GridUnitType.Star), null, 21 | CoerceWidth)); 22 | 23 | MinWidthProperty.OverrideMetadata(typeof(ColumnDefinitionExtended), 24 | new FrameworkPropertyMetadata((double) 0, null, 25 | CoerceMinWidth)); 26 | } 27 | 28 | // Properties 29 | public bool Visible 30 | { 31 | get => (bool) GetValue(VisibleProperty); 32 | set => SetValue(VisibleProperty, value); 33 | } 34 | 35 | // Get/Set 36 | public static void SetVisible(DependencyObject obj, bool nVisible) 37 | { 38 | obj.SetValue(VisibleProperty, nVisible); 39 | } 40 | 41 | public static bool GetVisible(DependencyObject obj) 42 | { 43 | return (bool) obj.GetValue(VisibleProperty); 44 | } 45 | 46 | private static void OnVisibleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 47 | { 48 | obj.CoerceValue(WidthProperty); 49 | obj.CoerceValue(MinWidthProperty); 50 | } 51 | 52 | private static object CoerceWidth(DependencyObject obj, object nValue) 53 | { 54 | return ((ColumnDefinitionExtended) obj).Visible ? nValue : new GridLength(0); 55 | } 56 | 57 | private static object CoerceMinWidth(DependencyObject obj, object nValue) 58 | { 59 | return ((ColumnDefinitionExtended) obj).Visible ? nValue : (double) 0; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/Noterium/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Noterium")] 9 | [assembly: AssemblyDescription("Main executable for Noterium")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Viktor Ekblom")] 12 | [assembly: AssemblyProduct("Noterium")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | //In order to begin building localizable applications, set 23 | //CultureYouAreCodingWith in your .csproj file 24 | //inside a . For example, if you are using US english 25 | //in your source files, set the to en-US. Then uncomment 26 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 27 | //the line below to match the UICulture setting in the project file. 28 | 29 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 30 | 31 | 32 | [assembly: ThemeInfo( 33 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 34 | //(used if a resource is not found in the page, 35 | // or application resource dictionaries) 36 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 37 | //(used if a resource is not found in the page, 38 | // app, or any theme specific resource dictionaries) 39 | )] -------------------------------------------------------------------------------- /src/Noterium/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Noterium.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Noterium/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/Noterium/Properties/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 55 | 56 | 70 | -------------------------------------------------------------------------------- /src/Noterium/Resources/Entypo-license.txt: -------------------------------------------------------------------------------- 1 | Entypo (http://www.entypo.com/) is created by Daniel Bruce and released under the Creative Commons, Share Alike/Attribution license. 2 | 3 | http://creativecommons.org/licenses/by-sa/3.0/ -------------------------------------------------------------------------------- /src/Noterium/Resources/Entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/src/Noterium/Resources/Entypo.ttf -------------------------------------------------------------------------------- /src/Noterium/Resources/WindowsIcons-license.txt: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Please carefully understand the license and download the latest icons at ModernUIIcons.com. 4 | 5 | ## Understand Your Rights 6 | No Attribution and No Derived Works 7 | http://creativecommons.org/licenses/by-nd/3.0/ * 8 | 9 | - If your project is open source include this license file in the source. 10 | - Nothing is needed in the front facing project (UNLESS you 11 | are using any of the icons listed below in the attribution section). 12 | - Commercial use is not only allowed but encouraged. If it is an icon 13 | in the attribution list below, you still need to attribute those! 14 | - Do not distribute the entire package (I've allowed this dozens of 15 | times for open source projects, but email me first). 16 | 17 | ## Creator 18 | - Austin Andrews (@templarian) 19 | 20 | ## Contributor** 21 | - Jay Zawrotny (@JayZawrotny) 22 | - A Bunch 23 | - Oren Nachman 24 | - appbar.chevron.down 25 | - appbar.chevron.up 26 | - appbar.chevron.left 27 | - appbar.chevron.right 28 | 29 | ## Derived Works 30 | - Alex Peattie 31 | - Social: http://www.alexpeattie.com/projects/justvector_icons/ 32 | 33 | ## Attribution*** 34 | - Kris Vandermotten (@kvandermotten) 35 | - appbar.medical.pulse 36 | - Constantin Kichinsky (@kichinsky) 37 | - appbar.currency.rubles 38 | - appbar.currency.grivna 39 | - Massimo Savazzi (@msavazzi) 40 | - List of missing exported icons 41 | - Proletkult Graphik, from The Noun Project 42 | - appbar.draw.pen (inspired) 43 | - Olivier Guin, from The Noun Project 44 | - appbar.draw.marker 45 | - Gibran Bisio, from The Noun Project 46 | - appbar.draw.bucket 47 | Andrew Forrester, from The Noun Project 48 | - appbar.fingerprint 49 | 50 | * The license is for attribution, but this is not required. 51 | ** Developers and designers that emailed Templarian the source .design icons to be added into the package. PNGs also accepted, but may take longer to be added. 52 | *** Icons I've copied so closely you want to attribute them and are also under the CC license. 53 | 54 | Contact 55 | - http://templarian.com/ 56 | - admin[@]templarian[.]com 57 | 58 | * Does not apply to copyrighted logos 59 | - Skype 60 | - Facebook 61 | - Twitter 62 | - etc... 63 | -------------------------------------------------------------------------------- /src/Noterium/Resources/icon.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /src/Noterium/Settings.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Configuration; 3 | 4 | namespace Noterium.Properties 5 | { 6 | // This class allows you to handle specific events on the settings class: 7 | // The SettingChanging event is raised before a setting's value is changed. 8 | // The PropertyChanged event is raised after a setting's value is changed. 9 | // The SettingsLoaded event is raised after the setting values are loaded. 10 | // The SettingsSaving event is raised before the setting values are saved. 11 | internal sealed partial class Settings 12 | { 13 | private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e) 14 | { 15 | // Add code to handle the SettingChangingEvent event here. 16 | } 17 | 18 | private void SettingsSavingEventHandler(object sender, CancelEventArgs e) 19 | { 20 | // Add code to handle the SettingsSaving event here. 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModel/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | using GalaSoft.MvvmLight; 2 | 3 | namespace Noterium.ViewModel 4 | { 5 | /// 6 | /// This class contains properties that the main View can data bind to. 7 | /// 8 | /// Use the mvvminpc snippet to add bindable properties to this ViewModel. 9 | /// 10 | /// 11 | /// You can also use Blend to data bind with the tool's support. 12 | /// 13 | /// 14 | /// See http://www.galasoft.ch/mvvm 15 | /// 16 | /// 17 | public class MainViewModel : ViewModelBase 18 | { 19 | /// 20 | /// Initializes a new instance of the MainViewModel class. 21 | /// 22 | public MainViewModel() 23 | { 24 | ////if (IsInDesignMode) 25 | ////{ 26 | //// // Code runs in Blend --> create design time data. 27 | ////} 28 | ////else 29 | ////{ 30 | //// // Code runs "for real" 31 | ////} 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModel/ViewModelLocator.cs: -------------------------------------------------------------------------------- 1 | /* 2 | In App.xaml: 3 | 4 | 6 | 7 | 8 | In the View: 9 | DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}" 10 | 11 | You can also use Blend to do all this with the tool's support. 12 | See http://www.galasoft.ch/mvvm 13 | */ 14 | 15 | using GalaSoft.MvvmLight; 16 | using GalaSoft.MvvmLight.Ioc; 17 | using CommonServiceLocator; 18 | 19 | namespace Noterium.ViewModel 20 | { 21 | /// 22 | /// This class contains static references to all the view models in the 23 | /// application and provides an entry point for the bindings. 24 | /// 25 | public class ViewModelLocator 26 | { 27 | /// 28 | /// Initializes a new instance of the ViewModelLocator class. 29 | /// 30 | public ViewModelLocator() 31 | { 32 | ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 33 | 34 | ////if (ViewModelBase.IsInDesignModeStatic) 35 | ////{ 36 | //// // Create design time view services and models 37 | //// SimpleIoc.Default.Register(); 38 | ////} 39 | ////else 40 | ////{ 41 | //// // Create run time view services and models 42 | //// SimpleIoc.Default.Register(); 43 | ////} 44 | 45 | SimpleIoc.Default.Register(); 46 | } 47 | 48 | public MainViewModel Main 49 | { 50 | get 51 | { 52 | return ServiceLocator.Current.GetInstance(); 53 | } 54 | } 55 | 56 | public static void Cleanup() 57 | { 58 | // TODO Clear the ViewModels 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModels/AutoFilterViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using System.Linq; 4 | using Noterium.Code.Interfaces; 5 | using Noterium.Code.Messages; 6 | using Noterium.Core; 7 | using Noterium.Core.DataCarriers; 8 | 9 | namespace Noterium.ViewModels 10 | { 11 | public class AutoFilterViewModel : NoteriumViewModelBase, IMainMenuItem 12 | { 13 | private string _name; 14 | 15 | public AutoFilterViewModel(string name, MenuItemType type) 16 | { 17 | Name = name; 18 | MenuItemType = type; 19 | 20 | MessengerInstance.Register(this, ReloadNoteList); 21 | } 22 | 23 | public string Name 24 | { 25 | get => _name; 26 | private set 27 | { 28 | _name = value; 29 | RaisePropertyChanged(); 30 | } 31 | } 32 | 33 | public MenuItemType MenuItemType { get; } 34 | 35 | public ObservableCollection Notes { get; } = new ObservableCollection(); 36 | 37 | private void ReloadNoteList(UpdateNoteList obj) 38 | { 39 | if (obj.MenuItem.MenuItemType == MenuItemType.Notebook) 40 | return; 41 | 42 | List notes; 43 | if (MenuItemType == MenuItemType.Trashcan) 44 | { 45 | var tempNotes = Hub.Instance.Storage.GetAllNotes(); 46 | notes = tempNotes.Where(n => n.InTrashCan).ToList(); 47 | } 48 | else if (MenuItemType == MenuItemType.Favorites) 49 | { 50 | var tempNotes = Hub.Instance.Storage.GetAllNotes(); 51 | notes = tempNotes.Where(n => n.Favourite).Where(n => !n.InTrashCan).ToList(); 52 | } 53 | else if (MenuItemType == MenuItemType.All) 54 | { 55 | notes = Hub.Instance.Storage.GetAllNotes().Where(n => !n.InTrashCan).OrderBy(n => n.Name).ToList(); 56 | } 57 | else if (MenuItemType == MenuItemType.Recent) 58 | { 59 | notes = Hub.Instance.Storage.GetAllNotes().Where(n => !n.InTrashCan).OrderBy(n => n.Changed).Take(15).ToList(); 60 | } 61 | else 62 | { 63 | notes = new List(); 64 | } 65 | 66 | var noteModels = ViewModelLocator.Instance.GetNoteViewModels(notes); 67 | Notes.Clear(); 68 | noteModels.ForEach(Notes.Add); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModels/LibraryViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Windows.Input; 4 | using GalaSoft.MvvmLight.CommandWpf; 5 | using GalaSoft.MvvmLight.Messaging; 6 | using MahApps.Metro.Controls.Dialogs; 7 | using Noterium.Code.Helpers; 8 | using Noterium.Code.Messages; 9 | using Noterium.Core; 10 | using Noterium.Core.DataCarriers; 11 | 12 | namespace Noterium.ViewModels 13 | { 14 | public class LibraryViewModel : NoteriumViewModelBase 15 | { 16 | public LibraryViewModel(Library library) 17 | { 18 | Library = library; 19 | 20 | ChangeLibraryCommand = new RelayCommand(SendChangeLibraryMessage); 21 | DeleteLibraryCommand = new RelayCommand(DeleteLibrary); 22 | SetDefaultLibraryCommand = new RelayCommand(SetDefaultLibrary); 23 | } 24 | 25 | public ICommand ChangeLibraryCommand { get; set; } 26 | public ICommand SetDefaultLibraryCommand { get; set; } 27 | public ICommand DeleteLibraryCommand { get; set; } 28 | 29 | public Library Library { get; } 30 | 31 | public bool IsCurrent => Hub.Instance.CurrentLibrary.Equals(Library); 32 | 33 | private void SendChangeLibraryMessage() 34 | { 35 | Messenger.Default.Send(new ChangeLibrary(Library)); 36 | } 37 | 38 | private void SetDefaultLibrary() 39 | { 40 | Hub.Instance.AppSettings.Librarys.ToList().ForEach(l => 41 | { 42 | l.Default = Library == l; 43 | l.Save(); 44 | }); 45 | Hub.Instance.AppSettings.DefaultLibrary = Library.Name; 46 | Hub.Instance.AppSettings.Save(); 47 | } 48 | 49 | private void DeleteLibrary() 50 | { 51 | var settings = DialogHelpers.GetDefaultDialogSettings(); 52 | 53 | var message = $"Do you want to delete the library '{Library.Name}'?\nAll files will be left untouched, it's just the connection that is removed."; 54 | MainWindowInstance.ShowMessageAsync("Delete library", message, MessageDialogStyle.AffirmativeAndNegative, settings).ContinueWith(delegate(Task task) 55 | { 56 | if (task.Result == MessageDialogResult.Affirmative) 57 | InvokeOnCurrentDispatcher(() => 58 | { 59 | Hub.Instance.AppSettings.Librarys.Remove(Library); 60 | Library.Delete(); 61 | }); 62 | }); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModels/LibrarysViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using System.Collections.Specialized; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Windows.Input; 6 | using GalaSoft.MvvmLight.CommandWpf; 7 | using GalaSoft.MvvmLight.Messaging; 8 | using Microsoft.WindowsAPICodePack.Dialogs; 9 | using Noterium.Code.Messages; 10 | using Noterium.Core; 11 | using Noterium.Core.DataCarriers; 12 | 13 | namespace Noterium.ViewModels 14 | { 15 | internal class LibrarysViewModel : NoteriumViewModelBase 16 | { 17 | private Library _currentLibrary; 18 | 19 | public LibrarysViewModel() 20 | { 21 | CurrentLibrary = Hub.Instance.CurrentLibrary; 22 | 23 | AddLibraryCommand = new RelayCommand(AddLibrary); 24 | Hub.Instance.AppSettings.Librarys.CollectionChanged += LibrarysOnCollectionChanged; 25 | 26 | Librarys = new ObservableCollection(); 27 | ReloadLibrary(); 28 | } 29 | 30 | public ICommand AddLibraryCommand { get; set; } 31 | 32 | public Library CurrentLibrary 33 | { 34 | get => _currentLibrary; 35 | set 36 | { 37 | _currentLibrary = value; 38 | RaisePropertyChanged(); 39 | } 40 | } 41 | 42 | public ObservableCollection Librarys { get; } 43 | public bool Loaded { get; internal set; } 44 | 45 | private void LibrarysOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) 46 | { 47 | ReloadLibrary(); 48 | } 49 | 50 | private void ReloadLibrary() 51 | { 52 | Librarys.Clear(); 53 | Hub.Instance.AppSettings.Librarys.ToList().ConvertAll(li => new LibraryViewModel(li)).ForEach(Librarys.Add); 54 | } 55 | 56 | private void AddLibrary() 57 | { 58 | var dialog = new CommonOpenFileDialog 59 | { 60 | IsFolderPicker = true, 61 | AllowNonFileSystemItems = false, 62 | EnsurePathExists = true, 63 | Multiselect = false 64 | }; 65 | 66 | var result = dialog.ShowDialog(); 67 | if (result == CommonFileDialogResult.Ok) 68 | { 69 | var di = new DirectoryInfo(dialog.FileName); 70 | if (di.Exists) 71 | { 72 | var path = dialog.FileName; 73 | var name = Path.GetFileName(path); 74 | var library = new Library 75 | { 76 | Name = name, 77 | Path = path, 78 | StorageType = StorageType.Disc 79 | }; 80 | library.Save(); 81 | 82 | Hub.Instance.AppSettings.Librarys.Add(library); 83 | Hub.Instance.AppSettings.LibraryFiles.Add(library.FilePath); 84 | Hub.Instance.AppSettings.Save(); 85 | 86 | Messenger.Default.Send(new ChangeLibrary(library)); 87 | } 88 | } 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModels/NoteEditorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | using System.Windows; 5 | using System.Windows.Input; 6 | using Noterium.Code; 7 | using Noterium.Code.Commands; 8 | using Noterium.Core.DataCarriers; 9 | using Noterium.Properties; 10 | 11 | namespace Noterium.ViewModels 12 | { 13 | public class NoteEditorViewModel : INotifyPropertyChanged 14 | { 15 | private Note _note; 16 | private string _text; 17 | 18 | public NoteEditorViewModel(Note note) 19 | { 20 | Note = note; 21 | 22 | Text = Note.DecryptedText; 23 | 24 | NoteFiles = new BoundObservableCollection(Note.Files, nf => new NoteFileViewModel(nf), (vm, m) => vm.NoteFile == m); 25 | 26 | AddNoteFileCommand = new NoteFileCommand(AddNoteFile); 27 | DeleteNoteFileCommand = new NoteFileCommand(DeleteNoteFile); 28 | //WeakEventManager.AddHandler(this, "NoteFileDeleted", null); 29 | } 30 | 31 | public ICommand AddNoteFileCommand { get; } 32 | public ICommand DeleteNoteFileCommand { get; } 33 | 34 | public Note Note 35 | { 36 | get => _note; 37 | internal set 38 | { 39 | _note = value; 40 | OnPropertyChanged(); 41 | } 42 | } 43 | 44 | public BoundObservableCollection NoteFiles { get; internal set; } 45 | 46 | public string Text 47 | { 48 | get => _text; 49 | private set 50 | { 51 | _text = value; 52 | OnPropertyChanged(); 53 | } 54 | } 55 | 56 | public event PropertyChangedEventHandler PropertyChanged; 57 | 58 | [NotifyPropertyChangedInvocator] 59 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 60 | { 61 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 62 | } 63 | 64 | private bool DeleteNoteFile(NoteFile nf) 65 | { 66 | var result = MessageBox.Show($"Do you want to delete the file {nf.Name}?", "Delete", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No); 67 | if (result == MessageBoxResult.Yes) 68 | { 69 | nf.Delete(); 70 | Note.Files.Remove(nf); 71 | } 72 | 73 | return true; 74 | } 75 | 76 | private bool AddNoteFile(NoteFile nf) 77 | { 78 | return true; 79 | } 80 | 81 | public class NoteFileEventArgs : EventArgs 82 | { 83 | public NoteFileEventArgs(NoteFile noteFile) 84 | { 85 | NoteFile = noteFile; 86 | } 87 | 88 | public NoteFile NoteFile { get; } 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModels/NoteFileViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Windows.Media; 3 | using Microsoft.WindowsAPICodePack.Shell; 4 | using Noterium.Core.DataCarriers; 5 | 6 | namespace Noterium.ViewModels 7 | { 8 | public class NoteFileViewModel 9 | { 10 | public NoteFileViewModel(NoteFile noteFile) 11 | { 12 | NoteFile = noteFile; 13 | } 14 | 15 | public NoteFile NoteFile { get; set; } 16 | 17 | public ImageSource Thumbnail 18 | { 19 | get 20 | { 21 | var filePath = NoteFile.FullName; 22 | if (File.Exists(filePath)) 23 | { 24 | var shellFile = ShellFile.FromFilePath(filePath); 25 | return shellFile.Thumbnail?.MediumBitmapSource; 26 | } 27 | 28 | return null; 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModels/NoteViewerViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Text.RegularExpressions; 3 | using System.Windows.Controls; 4 | using System.Windows.Input; 5 | using Noterium.Code.Commands; 6 | using Noterium.Code.Markdown; 7 | using Noterium.Code.Messages; 8 | using Noterium.Core; 9 | using Noterium.Core.DataCarriers; 10 | 11 | namespace Noterium.ViewModels 12 | { 13 | public class NoteViewerViewModel : NoteriumViewModelBase 14 | { 15 | private NoteViewModel _noteViewModel; 16 | 17 | private bool _secureNotesEnabled; 18 | 19 | public NoteViewerViewModel() 20 | { 21 | PropertyChanged += NoteViewModelPropertyChanged; 22 | 23 | Hub.Instance.EncryptionManager.PropertyChanged += NoteViewModelPropertyChanged; 24 | IsSecureNotesEnabled = Hub.Instance.EncryptionManager.SecureNotesEnabled; 25 | 26 | DocumentCheckBoxCheckedCommand = new SimpleCommand(DocumentCheckBoxChecked); 27 | MessengerInstance.Register(this, UpdateSelectedNote); 28 | 29 | // Force selection of first note sincen NoteMenuViewModel is instantiated before this. 30 | CurrentNote = ViewModelLocator.Instance.NoteMenu.SelectedNote; 31 | } 32 | 33 | public ICommand EditNoteCommand { get; set; } 34 | public ICommand SaveNoteCommand { get; set; } 35 | public ICommand DocumentCheckBoxCheckedCommand { get; set; } 36 | public ICommand CheckBoxCheckUpdatedTextCommand { get; set; } 37 | public ICommand CopyNoteCommand { get; set; } 38 | public ICommand RenameNoteCommand { get; set; } 39 | 40 | public NoteViewModel CurrentNote 41 | { 42 | get => _noteViewModel; 43 | set 44 | { 45 | _noteViewModel = value; 46 | RaisePropertyChanged(); 47 | } 48 | } 49 | 50 | public Settings Settings => Hub.Instance.Settings; 51 | 52 | public bool IsSecureNotesEnabled 53 | { 54 | get => _secureNotesEnabled; 55 | set 56 | { 57 | _secureNotesEnabled = value; 58 | RaisePropertyChanged(); 59 | } 60 | } 61 | 62 | public TextToFlowDocumentConverter MarkdownConverter { get; set; } 63 | 64 | public bool Loaded { get; internal set; } 65 | 66 | private void UpdateSelectedNote(SelectedNoteChanged obj) 67 | { 68 | if (MarkdownConverter != null) 69 | { 70 | if (obj.SelectedNote != null) 71 | MarkdownConverter.CurrentNote = obj.SelectedNote.Note; 72 | else 73 | MarkdownConverter.CurrentNote = null; 74 | } 75 | 76 | CurrentNote = obj.SelectedNote; 77 | } 78 | 79 | private void DocumentCheckBoxChecked(object arg) 80 | { 81 | const string markerToDo = @"\s*[*\-\s]\s\[(?:\s|x)\]"; 82 | 83 | var cb = arg as CheckBox; 84 | if (cb != null) 85 | { 86 | var number = (int)cb.Tag; 87 | 88 | var regString = "^" + markerToDo; 89 | var reg = new Regex(regString, RegexOptions.Compiled | RegexOptions.Singleline); 90 | var replaceRegex = @"\[(?:\s|x)\]"; 91 | var cbNumber = 0; 92 | var lines = CurrentNote.Note.DecryptedText.Split('\n'); 93 | for (var index = 0; index < lines.Length; index++) 94 | { 95 | var line = lines[index]; 96 | if (reg.IsMatch(line)) 97 | { 98 | if (cbNumber == number) 99 | { 100 | var isChecked = cb.IsChecked ?? false; 101 | 102 | var isCheckedString = isChecked ? "[x]" : "[ ]"; 103 | //string text = line.Substring(line.LastIndexOf("]", StringComparison.Ordinal) + 2); 104 | lines[index] = Regex.Replace(line, replaceRegex, isCheckedString); 105 | break; 106 | } 107 | 108 | cbNumber++; 109 | } 110 | } 111 | 112 | CurrentNote.Note.DecryptedText = string.Join("\n", lines); 113 | CheckBoxCheckUpdatedTextCommand?.Execute(CurrentNote.Note.DecryptedText); 114 | } 115 | } 116 | 117 | private void NoteViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) 118 | { 119 | if (e.PropertyName == "Note") 120 | { 121 | } 122 | else if (e.PropertyName == "SecureNotesEnabled") 123 | { 124 | IsSecureNotesEnabled = Hub.Instance.EncryptionManager.SecureNotesEnabled; 125 | } 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModels/NotebookViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using Noterium.Code.Interfaces; 3 | using Noterium.Code.Messages; 4 | using Noterium.Core; 5 | using Noterium.Core.DataCarriers; 6 | 7 | namespace Noterium.ViewModels 8 | { 9 | public class NotebookViewModel : NoteriumViewModelBase, IMainMenuItem 10 | { 11 | private bool _isSelected; 12 | public Notebook Notebook { get; private set; } 13 | 14 | public bool IsSelected 15 | { 16 | get => _isSelected; 17 | set 18 | { 19 | _isSelected = value; 20 | RaisePropertyChanged(); 21 | } 22 | } 23 | 24 | public string Name => Notebook.Name; 25 | 26 | public ObservableCollection Notes { get; } = new ObservableCollection(); 27 | 28 | public MenuItemType MenuItemType => MenuItemType.Notebook; 29 | 30 | internal void Init(Notebook notebook) 31 | { 32 | Notebook = notebook; 33 | 34 | MessengerInstance.Register(this, ReloadNoteList); 35 | } 36 | 37 | private void ReloadNoteList(UpdateNoteList obj) 38 | { 39 | var model = obj.MenuItem as NotebookViewModel; 40 | if (model == null) 41 | return; 42 | 43 | if (model.Notebook != Notebook) 44 | return; 45 | 46 | var notes = Hub.Instance.Storage.GetNotes(Notebook); 47 | var noteModels = ViewModelLocator.Instance.GetNoteViewModels(notes); 48 | Notes.Clear(); 49 | noteModels.ForEach(Notes.Add); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModels/NoteriumViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using GalaSoft.MvvmLight; 4 | 5 | namespace Noterium.ViewModels 6 | { 7 | public class NoteriumViewModelBase : ViewModelBase 8 | { 9 | private MainWindow _mainWindow; 10 | 11 | public MainWindow MainWindowInstance => _mainWindow ?? (_mainWindow = Application.Current.MainWindow as MainWindow); 12 | 13 | public void InvokeOnCurrentDispatcher(Action a) 14 | { 15 | Application.Current.Dispatcher.Invoke(a); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModels/TagViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using Noterium.Code.Interfaces; 4 | using Noterium.Code.Messages; 5 | using Noterium.Core.DataCarriers; 6 | 7 | namespace Noterium.ViewModels 8 | { 9 | public class TagViewModel : NoteriumViewModelBase, IMainMenuItem 10 | { 11 | private bool _isSelected; 12 | 13 | public TagViewModel(Tag tag) 14 | { 15 | Tag = tag; 16 | } 17 | 18 | public Tag Tag { get; set; } 19 | 20 | public bool IsSelected 21 | { 22 | get => _isSelected; 23 | set 24 | { 25 | _isSelected = value; 26 | RaisePropertyChanged(); 27 | } 28 | } 29 | 30 | public string Name => Tag.Name; 31 | 32 | public MenuItemType MenuItemType => MenuItemType.Tag; 33 | 34 | public ObservableCollection Notes => throw new NotImplementedException(); 35 | } 36 | } -------------------------------------------------------------------------------- /src/Noterium/ViewModels/TopMainMenuItemViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using System.Windows.Media; 3 | 4 | namespace Noterium.ViewModels 5 | { 6 | public class TopMainMenuItemViewModel 7 | { 8 | public TopMainMenuItemViewModel() 9 | { 10 | IconColor = Brushes.Black; 11 | } 12 | 13 | public string Name { get; set; } 14 | public string ToolTip { get; set; } 15 | public Canvas Icon { get; set; } 16 | public SolidColorBrush IconColor { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Noterium/Views/Dialogs/AuthenticationWindow.xaml: -------------------------------------------------------------------------------- 1 |  14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Noterium/Views/Dialogs/AuthenticationWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using System.Windows; 4 | using Noterium.Components; 5 | using Noterium.Properties; 6 | 7 | namespace Noterium.Views.Dialogs 8 | { 9 | /// 10 | /// Interaction logic for AuthenticationWindow.xaml 11 | /// 12 | public partial class AuthenticationWindow : INotifyPropertyChanged 13 | { 14 | public AuthenticationWindow() 15 | { 16 | InitializeComponent(); 17 | } 18 | 19 | public AuthenticationForm AuthForm => AuthenticationForm1; 20 | 21 | public event PropertyChangedEventHandler PropertyChanged; 22 | 23 | private void AuthenticationWindow_OnLoaded(object sender, RoutedEventArgs e) 24 | { 25 | AuthenticationForm1.Password.Focus(); 26 | } 27 | 28 | [NotifyPropertyChangedInvocator] 29 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 30 | { 31 | var handler = PropertyChanged; 32 | handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/Noterium/Views/Dialogs/LoadingWindow.xaml: -------------------------------------------------------------------------------- 1 |  14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 34 | 35 | -------------------------------------------------------------------------------- /src/Noterium/Views/Dialogs/LoadingWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using Noterium.Properties; 4 | 5 | namespace Noterium.Views.Dialogs 6 | { 7 | /// 8 | /// Interaction logic for AuthenticationWindow.xaml 9 | /// 10 | public partial class LoadingWindow : INotifyPropertyChanged 11 | { 12 | public LoadingWindow() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | public event PropertyChangedEventHandler PropertyChanged; 18 | 19 | [NotifyPropertyChangedInvocator] 20 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 21 | { 22 | var handler = PropertyChanged; 23 | handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 24 | } 25 | 26 | public void SetMessage(string message) 27 | { 28 | if (!Dispatcher.CheckAccess()) 29 | { 30 | Dispatcher.Invoke(() => SetMessage(message)); 31 | return; 32 | } 33 | 34 | LoadingText.Text = message; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/Noterium/Views/Dialogs/StorageSelector.xaml: -------------------------------------------------------------------------------- 1 |  14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Welcome! 26 | 27 | 28 | Before you start you need to decide where to store your notes. I have two options for you, Dropbox or a folder of your choosing. The simplest is to select Dropbox (if you have it installed, otherwise you can get it 29 | here 30 | ) and the application does the rest, else you can select a folder on your computer and all files will be stored there. 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 42 | Dropbox 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 53 | Filesystem 54 | 55 | 56 | 57 | 61 | 62 | -------------------------------------------------------------------------------- /src/Noterium/Views/Dialogs/StorageSelector.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.IO; 3 | using System.Runtime.CompilerServices; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | using Microsoft.WindowsAPICodePack.Dialogs; 7 | using Noterium.Core; 8 | using Noterium.Core.DataCarriers; 9 | using Noterium.Core.DropBox; 10 | using Noterium.Properties; 11 | 12 | namespace Noterium.Views.Dialogs 13 | { 14 | /// 15 | /// Interaction logic for AuthenticationWindow.xaml 16 | /// 17 | public partial class StorageSelector : INotifyPropertyChanged 18 | { 19 | private bool _onlyVerifyPassword; 20 | 21 | public StorageSelector() 22 | { 23 | InitializeComponent(); 24 | } 25 | 26 | public bool OnlyVerifyPassword 27 | { 28 | get => _onlyVerifyPassword; 29 | set 30 | { 31 | _onlyVerifyPassword = value; 32 | OnPropertyChanged(); 33 | } 34 | } 35 | 36 | public event PropertyChangedEventHandler PropertyChanged; 37 | 38 | private void AuthenticationWindow_OnLoaded(object sender, RoutedEventArgs e) 39 | { 40 | } 41 | 42 | [NotifyPropertyChangedInvocator] 43 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 44 | { 45 | var handler = PropertyChanged; 46 | handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 47 | } 48 | 49 | private void NextButtonClick(object sender, RoutedEventArgs e) 50 | { 51 | if (StorageTypeListBox.SelectedItem != null) 52 | { 53 | var item = (ListBoxItem) StorageTypeListBox.SelectedItem; 54 | if ((string) item.Tag == "DropBox") 55 | { 56 | var dbPath = DataStore.GetDropBoxPath(); 57 | if (!string.IsNullOrWhiteSpace(dbPath)) 58 | { 59 | var lib = new Library 60 | { 61 | Name = "DropBox", 62 | StorageType = StorageType.DropBox 63 | }; 64 | lib.Save(); 65 | 66 | Hub.Instance.AppSettings.Librarys.Add(lib); 67 | Hub.Instance.AppSettings.LibraryFiles.Add(lib.FilePath); 68 | Hub.Instance.AppSettings.Save(); 69 | 70 | DialogResult = true; 71 | } 72 | else 73 | { 74 | MessageBox.Show(this, "It seems that you dont have Dropbox installed.\n\nIf you have, please contact me via the support form on http://www.homepage.se.\n\nIf you don't, and don't want to install it, please select \"Filesystem\" as storage type where you can select a folder to store the notes.", "Cant find Dropbox...", MessageBoxButton.OK, MessageBoxImage.Information); 75 | } 76 | } 77 | else 78 | { 79 | var dialog = new CommonOpenFileDialog 80 | { 81 | IsFolderPicker = true, 82 | AllowNonFileSystemItems = false, 83 | EnsurePathExists = true, 84 | Multiselect = false 85 | }; 86 | 87 | var result = dialog.ShowDialog(); 88 | if (result == CommonFileDialogResult.Ok) 89 | { 90 | var di = new DirectoryInfo(dialog.FileName); 91 | if (di.Exists) 92 | { 93 | var path = dialog.FileName; 94 | var name = Path.GetFileName(path); 95 | var lib = new Library 96 | { 97 | Name = name, 98 | Path = path, 99 | StorageType = StorageType.Disc 100 | }; 101 | lib.Save(); 102 | Hub.Instance.AppSettings.Librarys.Add(lib); 103 | Hub.Instance.AppSettings.LibraryFiles.Add(lib.FilePath); 104 | Hub.Instance.AppSettings.Save(); 105 | DialogResult = true; 106 | } 107 | } 108 | } 109 | 110 | if (DialogResult == true) Close(); 111 | } 112 | } 113 | 114 | private void StorageTypeListBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) 115 | { 116 | NextButton.IsEnabled = true; 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /src/Noterium/Views/Flyouts/Librarys.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace Noterium.Views.Flyouts 4 | { 5 | /// 6 | /// Interaction logic for Librarys.xaml 7 | /// 8 | public partial class Librarys : UserControl 9 | { 10 | public Librarys() 11 | { 12 | InitializeComponent(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Noterium/Views/Flyouts/Settings.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace Noterium.Views.Flyouts 4 | { 5 | /// 6 | /// Interaction logic for Settings.xaml 7 | /// 8 | public partial class Settings : UserControl 9 | { 10 | public Settings() 11 | { 12 | InitializeComponent(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Noterium/Windows/AboutWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Windows.Navigation; 3 | using Noterium.ViewModels; 4 | 5 | namespace Noterium.Windows 6 | { 7 | /// 8 | /// Interaction logic for AboutWindow.xaml 9 | /// 10 | public partial class AboutWindow 11 | { 12 | public AboutWindow() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | public AboutWindowViewModel CurrentModel => (AboutWindowViewModel) DataContext; 18 | 19 | private void LinkRequestNavigate(object sender, RequestNavigateEventArgs e) 20 | { 21 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri)); 22 | e.Handled = true; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/Noterium/Windows/BackupManager.xaml: -------------------------------------------------------------------------------- 1 |  16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 42 | 43 | 45 | 46 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 82 | 83 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/Noterium/Windows/BackupManager.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using Noterium.ViewModels; 3 | 4 | namespace Noterium.Windows 5 | { 6 | /// 7 | /// Interaction logic for BackupManager.xaml 8 | /// 9 | public partial class BackupManager 10 | { 11 | public BackupManager() 12 | { 13 | InitializeComponent(); 14 | } 15 | 16 | public BackupManagerViewModel Model => (BackupManagerViewModel) DataContext; 17 | 18 | private void BackupTree_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) 19 | { 20 | Model.SelectedFileNode = e.NewValue as FileTreeNode; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Noterium/Windows/TableEditor.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 23 | 26 | 27 | 28 | 31 | 34 | 37 | 38 | 41 | 44 | 47 | 48 | 61 | 62 | 68 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/Noterium/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/src/Noterium/icon.ico -------------------------------------------------------------------------------- /src/Noterium/icon_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/src/Noterium/icon_24.png -------------------------------------------------------------------------------- /src/Noterium/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Setup/Setup.wixproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 3.9 7 | 2338cb08-8c33-4e4e-8e63-db6922eff3ad 8 | 2.0 9 | Setup 10 | Package 11 | $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets 12 | $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets 13 | 14 | 15 | bin\$(Configuration)\ 16 | obj\$(Configuration)\ 17 | Debug 18 | 19 | 20 | bin\$(Configuration)\ 21 | obj\$(Configuration)\ 22 | 23 | 24 | 25 | 26 | 27 | 28 | $(WixExtDir)\WixUtilExtension.dll 29 | WixUtilExtension 30 | 31 | 32 | $(WixExtDir)\WixUIExtension.dll 33 | WixUIExtension 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Noterium.Core 43 | {8daeffc0-4370-4f9f-a9e9-528d0e9ff2e4} 44 | True 45 | True 46 | Binaries;Content;Satellites 47 | INSTALLFOLDER 48 | 49 | 50 | Noterium 51 | {d35b4d1e-b885-47cb-b0cf-546ff3f3e391} 52 | True 53 | True 54 | Binaries;Content;Satellites 55 | INSTALLFOLDER 56 | 57 | 58 | 59 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/Setup/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/src/Setup/icon.ico -------------------------------------------------------------------------------- /src/lib/CommonMark.NET/CommonMark.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/src/lib/CommonMark.NET/CommonMark.dll -------------------------------------------------------------------------------- /src/lib/Markdig.Wpf/Markdig.Wpf.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/src/lib/Markdig.Wpf/Markdig.Wpf.dll -------------------------------------------------------------------------------- /src/lib/Markdig.Wpf/Markdig.Wpf.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekblom/noterium/7349ae01c581c2bee9fb245c241c1d7821e70b44/src/lib/Markdig.Wpf/Markdig.Wpf.pdb --------------------------------------------------------------------------------