private void OnReadNow(object sender, RoutedEventArgs e) { var nav = Navigator.Get(); var parentControlId = Navigator.NavigateControlId.BookSearchDisplay; nav.DisplayBook(parentControlId, DataContext as BookData); }
private void UserDidNavigationRequest(EpubChapterData chapter) { if (chapter == null) { return; } var nav = Navigator.Get(); BookLocation location = null; if (chapter == Chapters[0]) { // First one is special: we always go to the very start of the book, including stuff that's not in // the classic table of contents. For example, Gutenberg Campfire Girls Station Island has a cover that's // not in the TOC but which is in the inner.SpecialResources.HtmlInReadingOrder and which is placed first. // Additionally, that book also has the weird thing that the ID for the first section (in the TOC) is // near the end of the section, so when you click on it, it scrolls to there, but then the next TOC entry // (chapter 1) is visible near the top, and so the selection jumps to there. location = new BookLocation(0, 0); // first HTML page, at the very top. } else { location = EpubChapterData.FromChapter(chapter); } nav.UserNavigatedTo(ControlId, location); }
private async Task DoSwipeDownload(BookData bookData) { var bookcard = GetBookCardFromBookData(bookData); var bookdb = BookDataContext.Get(); var nd = CommonQueries.BookNavigationDataEnsure(bookdb, bookData); nd.NSwipeRight++; nd.NSpecificSelection++; CommonQueries.BookSaveChanges(bookdb); // Before I can download, make sure that the download file list is set up. SetupDownloadsIfNeeded(bookData); // But wait! If the book is already downloaded, then just display it var fileStatus = bookData.DownloadData == null ? DownloadData.FileStatus.Unknown : bookData.DownloadData.CurrFileStatus; switch (fileStatus) { case DownloadData.FileStatus.Downloaded: var nav = Navigator.Get(); nav.DisplayBook(ControlId, bookData); break; default: await bookcard.DoDownloadAsync(); break; } }
private void OnSetFromColors(object sender, RoutedEventArgs e) { var b = (sender as Button); var bg = (b.Background as SolidColorBrush).Color; var fg = (b.Foreground as SolidColorBrush).Color; var nav = Navigator.Get(); nav.SetAppColors(bg, fg); }
private async void OnReviewClicked(object sender, RoutedEventArgs e) { // The review page might have to set navigation data (review includes UserStatus). Let's make 100% sure // that the database has correct navigation data set up. Hint: it really should already because if we are // here, then the book has been set to "reading", and that should in turn force navigation data. var bookdb = BookDataContext.Get(); EnsureBookNavigationData(bookdb); var sh = new ContentDialog() { Title = "Review Book", PrimaryButtonText = "OK", }; // Old style: var review = new BookReview(); // This is the edit control, not the UserReview data var review = new ReviewNoteStatusControl(); // This is the edit control, not the UserReview data // Set up the potential note, if that's what the user is going to do. var location = GetCurrBookLocation().ToJson(); string currSelection = ""; if (CurrHtml != null && CurrHtml.Contains("DoGetSelection")) { currSelection = await uiHtml.InvokeScriptAsync("DoGetSelection", null); } var note = new UserNote() { BookId = BookData.BookId, CreateDate = DateTimeOffset.Now, Location = location, Text = currSelection, }; review.SetupNote(note); sh.Content = review; string defaultReviewText = ""; if (CurrHtml != null && CurrHtml.Contains("DoGetSelection")) { defaultReviewText = await uiHtml.InvokeScriptAsync("DoGetSelection", null); } review.SetBookData(BookData, defaultReviewText); var result = await sh.ShowAsync(); switch (result) { case ContentDialogResult.Primary: review.SaveData(); var nav = Navigator.Get(); nav.UpdateProjectRome(ControlId, GetCurrBookLocation()); break; } SetReviewSymbol(); }
private void DoUserNavigateToAsNeeded() { var location = UserNavigatedToArgument; UserNavigatedToArgument = null; if (location != null) { var nav = Navigator.Get(); nav.UserNavigatedTo(ControlId, location); } }
private void OnImageHolding(object sender, HoldingRoutedEventArgs e) { var data = (sender as FrameworkElement).DataContext as ImageData; if (data == null) { return; } var location = ToBookLocation(data); Navigator.Get().UserNavigatedTo(ControlId, location); }
private void OnGoto(object sender, RoutedEventArgs e) { var data = uiImageFullSize.DataContext as ImageData; if (data == null) { return; } var location = ToBookLocation(data); Navigator.Get().UserNavigatedTo(ControlId, location); }
public void SaveNoteIfNeeded(NavigateControlId controlId, BookDataContext bookdb) { var note = DataContext as UserNote; if (note == null) { return; } bool changed = SaveToContext(); if (changed) { CommonQueries.BookNoteSave(bookdb, note); Navigator.Get().UpdatedNotes(controlId); } }
private void OnCardTapped(object sender, TappedRoutedEventArgs e) { var bookdb = BookDataContext.Get(); var book = (sender as BookCard)?.DataContext as BookData; if (book == null) { return; } var dd = CommonQueries.DownloadedBookFind(bookdb, book.BookId); if (dd == null) { return; // Can't display a book that isn't there! } var nav = Navigator.Get(); nav.DisplayBook(ControlId, book); }
private void SyncPosition_Click(object sender, RoutedEventArgs e) { var bookdb = BookDataContext.Get(); // The button is only clickable when there's exactly one item selected // (baring race conditions, of course) foreach (var item in uiList.SelectedItems) { var noteWithTitle = item as UserNoteWithTitle; if (noteWithTitle == null) { return; // should never happen. } var note = noteWithTitle.BaseNote; if (note == null) { continue; // should never happen } var location = note.LocationToBookLocatation(); if (location == null) { continue; // should never happen } // Are we in the same book, or a different one? var nav = Navigator.Get(); if (noteWithTitle.BookId != CurrBookData.BookId) { var book = CommonQueries.BookGet(bookdb, noteWithTitle.BookId); CurrBookData = book; // make sure to reset this! nav.DisplayBook(ControlId, book, location); } else { nav.UserNavigatedTo(ControlId, location); } } }
private void OnPositionTapped(object sender, TappedRoutedEventArgs e) { if (uiPosition.ActualWidth < 1) { return; } var position = e.GetPosition(uiPosition); var xvalue = position.X / uiPosition.ActualWidth; // should be 0..1.0 if (!Calculations.SectionSizesOk) { return; } // Which section is it in? var(htmlIndex, percentPosition) = Calculations.GetPercentPosition(xvalue); if (htmlIndex >= 0 && percentPosition >= 0.0) { var nav = Navigator.Get(); nav.UserNavigatedTo(ControlId, new BookLocation(htmlIndex, percentPosition)); return; } }
/// <summary> /// Called when the user has navigated to somewhere in the book. The chapter display /// tries to sync itself to the value. The chapter display depends on the caller being /// fully initialized first! /// </summary> /// <param name="sourceId"></param> /// <param name="location"></param> public async void NavigateTo(NavigateControlId sourceId, BookLocation location) { string chapterid = ""; var nav = Navigator.Get(); if (!double.IsNaN(location.ScrollPercent)) { chapterid = await nav.MainBookHandler.GetChapterBeforePercentAsync(location); } else { chapterid = nav.MainBookHandler.GetChapterContainingId(location.Location, location.HtmlIndex); } EpubChapterData foundChapter = null; if (foundChapter == null && location.HtmlIndex >= 0) { var html = Book.ResourcesHtmlOrdered[location.HtmlIndex]; foreach (var chapter in Chapters) { // FAIL: Intro to Planetary Nebulae the location is html 8, id tit1 which is shared by multiple chapters. if (html.Href.EndsWith(chapter.FileName) && chapter.Anchor == chapterid) { foundChapter = chapter; break; } } } // Most common: there's an id, and it matches a single chapter. if (foundChapter == null) { foreach (var chapter in Chapters) { if (chapter.Anchor == chapterid || chapter.FileName == chapterid) { foundChapter = chapter; break; } } } if (foundChapter == null && location.HtmlIndex >= 0) { var html = Book.ResourcesHtmlOrdered[location.HtmlIndex]; foreach (var chapter in Chapters) { // FAIL: Intro to Planetary Nebulae the location is html 8, id tit1 which is shared by multiple chapters. if (html.Href.EndsWith(chapter.FileName)) { foundChapter = chapter; break; } } } // Worse case scenario, but it's better to display something if (foundChapter == null) { foreach (var chapter in Chapters) { if (string.IsNullOrEmpty(chapterid)) { App.Error($"ChapterDisplay:Navigate({location}) was asked to find an empty chapter"); foundChapter = chapter; break; } } } if (foundChapter == null) { // Truly desperate. if (Chapters.Count > 0) { App.Error($"ChapterDisplay:Navigate({location}) completely failed"); foundChapter = Chapters[0]; } else { App.Error($"ChapterDisplay:Navigate({location}) last ditch completely failed -- no chapters at all!"); } } if (foundChapter != null) { // Select this one uiChapterList.SelectedItem = foundChapter; uiChapterList.ScrollIntoView(foundChapter); return; // all done! } }
/// <summary> /// Handles the entire problem of reviewing each of the selected books. Will pop up a little pop-up /// and let the user do a review of each one. /// </summary> /// <returns></returns> public async Task RunSavedReviewEachBook() { if (SavedSelectedBooks == null) { return; } var selectedBooks = SavedSelectedBooks; var deleteBook = SavedDeleteBook; // Setup to delete all selected books from the Nook EbookReaderProgressControl progress = null; if (deleteBook) { await SetupProgressFolderAsync(); progress = new EbookReaderProgressControl(); uiAlternateContent.Visibility = Visibility.Visible; uiAlternateContent.Children.Clear(); uiAlternateContent.Children.Add(progress); progress.SetNBooks(selectedBooks.Count); } var bookdb = BookDataContext.Get(); var sh = new ContentDialog() { Title = "Review Book", PrimaryButtonText = "OK", SecondaryButtonText = "Cancel", }; var reviewlist = new ReviewNoteStatusListControl(); reviewlist.SetBookList(selectedBooks); sh.Content = reviewlist; var result = await sh.ShowAsync(); ; #if NEVER_EVER_DEFINED // The old code that did a pop-up per book. The new way does one pop-up with a swipable list. foreach (var bookData in selectedBooks) { var srcfullname = bookData.DownloadData.FullFilePath; var fname = bookData.DownloadData.FileName; var nd = CommonQueries.BookNavigationDataEnsure(bookdb, bookData); var sh = new ContentDialog() { Title = "Review Book", PrimaryButtonText = "OK", SecondaryButtonText = "Cancel", }; var review = new ReviewNoteStatusControl(); string defaultReviewText = null; var BookData = bookData; review.SetBookData(BookData, defaultReviewText); sh.Content = review; var result = await sh.ShowAsync(); switch (result) { case ContentDialogResult.Primary: review.SaveData(); bool deleteOk = true; if (progress != null) { deleteOk = await DeleteDownloadedBookAsync(progress, bookData); } var nav = Navigator.Get(); //TODO: setup Rome?? nav.UpdateProjectRome(ControlId, GetCurrBookLocation()); break; } if (deleteBook) { // TODO: How to delete it? ; } } #endif }
private void OnSetDark(object sender, RoutedEventArgs e) { var nav = Navigator.Get(); nav.SetAppColors(Colors.DarkRed, Colors.WhiteSmoke); }
// Not doing any color stuff until it can be made to work better private void OnSetLight(object sender, RoutedEventArgs e) { var nav = Navigator.Get(); nav.SetAppColors(Colors.AntiqueWhite, Colors.DarkGreen); }
private void OnScriptNotify(object sender, NotifyEventArgs e) { var parsed = e.Value.Split(new char[] { ':' }, 2); var cmd = parsed[0]; var param = parsed[1]; var nav = Navigator.Get(); switch (cmd) { default: App.Error($"WebView:ERROR:Log:{cmd} and {param} are not valid"); break; case "dbg": if (Logger.LogExtraTiming || !param.Contains("doWindowReportScroll:")) { Logger.Log($"WebView:Log:{param}"); } break; case "monopage": // Reported when this particular section doesn't even fit onto a screen. // A next page should always trigger the next section. CurrPageIsMonoPage = true; break; case "scroll": { var status = double.TryParse(param, out double value); if (Logger.LogExtraTiming) { Logger.Log($"Report:Scroll: percent={param} status={status} and update position htmlIndex={CurrHtmlIndex} scroll={CurrScrollPosition} to {value}"); } if (status) { CurrScrollPosition = value; SavePositionEZ(); uiAllUpPosition.UpdatePosition(CurrHtmlIndex, CurrScrollPosition); // If we're at the bottom of the html section, and there's a next section, enable the button. uiNextPage.IsEnabled = HaveNextPage(); uiPrevPage.IsEnabled = HavePreviousPage(); } //Logger.Log($"Report:Scroll: finished update"); } break; case "select": //Logger.Log("Selection!" + param); MostRecentSelection = param; nav.UserSelected(ControlId, param); break; case "selectpos": { //Logger.Log("SelectPos!" + param); var status = double.TryParse(param, out double value); if (status) { CurrSelectPosition = value; } } break; case "topid": if (Logger.LogExtraTiming) { Logger.Log($"Report:TopId: closest id is {param} htmlIndex={CurrHtmlIndex}"); } // FAIL: Into to Planetary Nebula has chapters (like the dedication) with no 'id' tags at all. On navigation, // these report back that they've navigated to the autogenerated 'uiLog' item which then isn't found in any of // the chapters, resulting in the navigation switching back to the title page. if (param == "uiLog") { nav.UserNavigatedTo(ControlId, new BookLocation(CurrHtmlIndex, 0)); } else { nav.UserNavigatedTo(ControlId, new BookLocation(CurrHtmlIndex, param)); } //Logger.Log($"Report:TopId: finished navigation"); break; case "topnoid": // The page scrolled, but the page has no id at all. We have to pick a chapter based just on // the current HTML and hope it's good enough. if (Logger.LogExtraTiming) { Logger.Log($"Report:TopINod: no id, but the htmlIndex={CurrHtmlIndex}"); } // Hang on -- why isn't this reporting as the uiLog?? nav.UserNavigatedTo(ControlId, new BookLocation(CurrHtmlIndex, 0)); break; } }