├── Booklet_Blue.ico ├── Resources ├── Filter_64x64.png ├── Info_16x16.png ├── Read_48x48.png ├── Search_64x64.png ├── Stack_64x64.png ├── Unread_48x48.png ├── Update_64x64.png ├── BarChart_64x64.png ├── Comment_64x64.png ├── DarkMode_64x64.png ├── Notepad_64x64.png ├── Settings_64x64.png ├── LightMode_64x64.png ├── folder-open_64x64.png ├── Heart-Filled_48x48.png └── Heart-Outline_48x48.png ├── UI ├── App.xaml.cs ├── StoryFilterContent.xaml.cs ├── SettingsWindow.xaml.cs ├── StoryDetails.xaml.cs ├── DownloadWindow.xaml.cs ├── GithubAd.xaml.cs ├── UpdateAvailable.xaml ├── UpdateAvailable.xaml.cs ├── FavoritesToggle.xaml.cs ├── GithubAd.xaml ├── FavoritesToggle.xaml ├── RatingControl.xaml ├── RatingControl.xaml.cs ├── StoriesList.xaml.cs ├── StoryViewer.xaml.cs ├── CircularProgressBar.xaml ├── MainWindow.xaml.cs ├── SearchContent.xaml.cs ├── StoryDetails.xaml ├── App.xaml ├── CircularProgressBar.xaml.cs ├── DownloadWindow.xaml ├── StoryFilterContent.xaml └── StoryViewer.xaml ├── VM ├── Helpers │ ├── ViewModelBase.cs │ ├── UrlExtensions.cs │ ├── LimitedStack.cs │ ├── JsonConverters.cs │ ├── CollectionViewHelpers.cs │ ├── GeneralUtils.cs │ ├── Converters.cs │ └── XMLSerializer.cs ├── Literotica │ ├── NavigationButton.cs │ ├── SearchResult.cs │ ├── AuthorGroup.cs │ ├── Serialization.cs │ ├── Model.cs │ └── LiteroticaUtils.cs ├── Bookmark.cs ├── DisplaySettings.cs └── FilterSettings.cs ├── Properties ├── PublishProfiles │ └── SingleFileFrameworkDependent.pubxml ├── Resources.Designer.cs └── Resources.resx ├── LICENSE ├── StoryManager.sln ├── ideas.txt ├── .gitattributes ├── README.md ├── StoryManager.csproj └── .gitignore /Booklet_Blue.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Booklet_Blue.ico -------------------------------------------------------------------------------- /Resources/Filter_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Filter_64x64.png -------------------------------------------------------------------------------- /Resources/Info_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Info_16x16.png -------------------------------------------------------------------------------- /Resources/Read_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Read_48x48.png -------------------------------------------------------------------------------- /Resources/Search_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Search_64x64.png -------------------------------------------------------------------------------- /Resources/Stack_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Stack_64x64.png -------------------------------------------------------------------------------- /Resources/Unread_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Unread_48x48.png -------------------------------------------------------------------------------- /Resources/Update_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Update_64x64.png -------------------------------------------------------------------------------- /Resources/BarChart_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/BarChart_64x64.png -------------------------------------------------------------------------------- /Resources/Comment_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Comment_64x64.png -------------------------------------------------------------------------------- /Resources/DarkMode_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/DarkMode_64x64.png -------------------------------------------------------------------------------- /Resources/Notepad_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Notepad_64x64.png -------------------------------------------------------------------------------- /Resources/Settings_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Settings_64x64.png -------------------------------------------------------------------------------- /Resources/LightMode_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/LightMode_64x64.png -------------------------------------------------------------------------------- /Resources/folder-open_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/folder-open_64x64.png -------------------------------------------------------------------------------- /Resources/Heart-Filled_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Heart-Filled_48x48.png -------------------------------------------------------------------------------- /Resources/Heart-Outline_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Videogamers0/StoryManager/HEAD/Resources/Heart-Outline_48x48.png -------------------------------------------------------------------------------- /UI/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | 8 | namespace StoryManager 9 | { 10 | public partial class App : Application 11 | { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /VM/Helpers/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace StoryManager.VM.Helpers 9 | { 10 | public class ViewModelBase : INotifyPropertyChanged 11 | { 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | public virtual void NotifyPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 14 | public void NPC(string propertyName) => NotifyPropertyChanged(propertyName); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Properties/PublishProfiles/SingleFileFrameworkDependent.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | Release 8 | Any CPU 9 | bin\publish\ 10 | FileSystem 11 | <_TargetId>Folder 12 | net7.0-windows 13 | false 14 | win-x64 15 | true 16 | false 17 | True 18 | 19 | -------------------------------------------------------------------------------- /UI/StoryFilterContent.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace StoryManager.UI 17 | { 18 | /// 19 | /// Interaction logic for StoryFilterContent.xaml 20 | /// 21 | public partial class StoryFilterContent : UserControl 22 | { 23 | public StoryFilterContent() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /UI/SettingsWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.WindowsAPICodePack.Dialogs; 2 | using Prism.Commands; 3 | using StoryManager.VM; 4 | using StoryManager.VM.Helpers; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.ComponentModel; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows; 12 | using System.Windows.Controls; 13 | using System.Windows.Data; 14 | using System.Windows.Documents; 15 | using System.Windows.Input; 16 | using System.Windows.Media; 17 | using System.Windows.Media.Imaging; 18 | using System.Windows.Shapes; 19 | 20 | namespace StoryManager.UI 21 | { 22 | /// 23 | /// Interaction logic for SettingsWindow.xaml 24 | /// 25 | public partial class SettingsWindow : Window 26 | { 27 | public SettingsWindow(Settings DataContext) 28 | { 29 | InitializeComponent(); 30 | this.DataContext = DataContext; 31 | } 32 | 33 | private void Close_Click(object sender, RoutedEventArgs e) => Close(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /UI/StoryDetails.xaml.cs: -------------------------------------------------------------------------------- 1 | using StoryManager.VM.Helpers; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace StoryManager.UI 18 | { 19 | /// 20 | /// Interaction logic for StoryDetails.xaml 21 | /// 22 | public partial class StoryDetails : UserControl 23 | { 24 | public StoryDetails() 25 | { 26 | InitializeComponent(); 27 | } 28 | 29 | private void OpenCategoryInBrowser(object sender, RequestNavigateEventArgs e) 30 | { 31 | string FullUrl = $"https://www.literotica.com/c/{e.Uri.ToString()}"; 32 | GeneralUtils.OpenUrl(FullUrl, true); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /VM/Helpers/UrlExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Web; 7 | 8 | namespace StoryManager.VM.Helpers 9 | { 10 | #region https://stackoverflow.com/a/12410826 11 | public static class UrlExtensions 12 | { 13 | public static string SetUrlParameter(this string url, string paramName, string value) 14 | { 15 | return new Uri(url).SetParameter(paramName, value).ToString(); 16 | } 17 | 18 | public static Uri SetParameter(this Uri url, string paramName, string value) 19 | { 20 | var queryParts = HttpUtility.ParseQueryString(url.Query); 21 | queryParts[paramName] = value; 22 | return new Uri(url.AbsoluteUriExcludingQuery() + '?' + queryParts.ToString()); 23 | } 24 | 25 | public static string AbsoluteUriExcludingQuery(this Uri url) 26 | { 27 | return url.AbsoluteUri.Split('?').FirstOrDefault() ?? String.Empty; 28 | } 29 | } 30 | #endregion 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 SlayerDharok 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 | -------------------------------------------------------------------------------- /StoryManager.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33414.496 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StoryManager", "StoryManager.csproj", "{BF581157-C9F2-4F39-8E22-939DFAEEF038}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {BF581157-C9F2-4F39-8E22-939DFAEEF038}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {BF581157-C9F2-4F39-8E22-939DFAEEF038}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {BF581157-C9F2-4F39-8E22-939DFAEEF038}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {BF581157-C9F2-4F39-8E22-939DFAEEF038}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {C2B9151D-21A2-4E11-B00E-69F4B3B0D907} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /ideas.txt: -------------------------------------------------------------------------------- 1 | Some ideas for future improvements: 2 | 3 | - Setting to auto-mark stories as 'Read' when user reaches the bottom scroll offset 4 | - Additional settings to change sorting? 5 | Sort groupbox: List of options, can drag/drop to re-order 6 | A-Z, Download Date, Authored Date, Last Viewed, Your Rating etc 7 | - Custom bookmarks 8 | Click a button 'Save bookmark' (use the same icon that Literotica uses for bookmarks) to store the current scroll offset as a numbered bookmark for the selected story 9 | Bookmarks are auto-deleted / un-loadable if they were created with a different WebView2 width, 10 | since the width of the viewer dictates what content is visible at a particular vertical scroll offset 11 | - UI for finding stories that are related to the selected story 12 | - Story importer? Must manually fill in the story metadata, and some features would need to be refactored 13 | such as clicking the Title to open story in browser since the base address would be different 14 | Could also have 2-tabbed UI. Tab #1: Literotica. Tab #2: Other 15 | Other tab would be a simplified copy of the code used for the Literotica tab. 16 | - Story filter settings could have a checkbox list of categories to show/hide -------------------------------------------------------------------------------- /UI/DownloadWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using StoryManager.VM.Helpers; 2 | using StoryManager.VM.Literotica; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | using System.Windows.Controls; 10 | using System.Windows.Data; 11 | using System.Windows.Documents; 12 | using System.Windows.Input; 13 | using System.Windows.Media; 14 | using System.Windows.Media.Imaging; 15 | using System.Windows.Navigation; 16 | using System.Windows.Shapes; 17 | 18 | namespace StoryManager.UI 19 | { 20 | /// 21 | /// Interaction logic for DownloadWindow.xaml 22 | /// 23 | public partial class DownloadWindow : Window 24 | { 25 | public DownloadWindow(Downloader DataContext) 26 | { 27 | InitializeComponent(); 28 | this.DataContext = DataContext; 29 | 30 | #if NEVER //DEBUG 31 | this.TopStoriesButton.Visibility = Visibility.Visible; 32 | #endif 33 | } 34 | 35 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) 36 | { 37 | if (sender is Hyperlink hl) 38 | GeneralUtils.OpenUrl(hl.NavigateUri.ToString(), true); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /UI/GithubAd.xaml.cs: -------------------------------------------------------------------------------- 1 | using StoryManager.VM.Helpers; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace StoryManager.UI 18 | { 19 | /// 20 | /// Interaction logic for GithubAd.xaml 21 | /// 22 | public partial class GithubAd : Window 23 | { 24 | public int OpenedCount { get; } 25 | 26 | public GithubAd(int Count) 27 | { 28 | InitializeComponent(); 29 | 30 | OpenedCount = Count; 31 | 32 | DataContext = this; 33 | } 34 | 35 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) 36 | { 37 | if (sender is Hyperlink hl) 38 | GeneralUtils.OpenUrl(hl.NavigateUri.ToString(), false); 39 | } 40 | 41 | private void Close_Click(object sender, RoutedEventArgs e) 42 | { 43 | Close(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /UI/UpdateAvailable.xaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |