├── .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 | [](https://github.com/ekblom/noterium/issues)
5 |
6 | [](https://github.com/ekblom/noterium/releases)
7 |
8 | 
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 | 
39 |
40 | 
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 $"";
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