Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions src/BloomExe/Book/Book.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ public Book(
/// </summary>
public string PendingCreationSource { get; set; }

/// <summary>
/// Snapshot of the source book's title (in L1, usually empty) captured when the new book is created.
/// This lets us distinguish true user title edits from automatic recalculation.
/// </summary>
public string PendingCreationSourceTitle { get; set; }

/// <summary>
/// If there is a pending "Created" history event (set during book creation), record it now
/// using the book's current title.
Expand All @@ -244,14 +250,27 @@ public void RecordPendingCreatedHistoryEvent(bool onlyIfTitleChanged = false)
{
if (PendingCreationSource == null)
return;
if (onlyIfTitleChanged && Storage.Dom.Title == PendingCreationSource)
return;
if (onlyIfTitleChanged)
{
// Compare L1 titles to detect if the user has actually changed the title.
// Extract the current book's L1 title using its BookData language.
var sourceTitle = PendingCreationSourceTitle ?? string.Empty;
var currentL1Title = string.Empty;
if (BookInfo != null && BookData != null)
{
currentL1Title =
BookInfo.GetTitleForLanguage(BookData.Language1Tag) ?? string.Empty;
}
if (sourceTitle == currentL1Title)
return;
}
BookHistory.AddEvent(
this,
BookHistoryEventType.Created,
$"Created a new book \"{Storage.Dom.Title}\" from a source book \"{PendingCreationSource}\""
);
PendingCreationSource = null;
PendingCreationSourceTitle = null;
}

public void UpdateBookInfoFromDisk()
Expand Down
27 changes: 27 additions & 0 deletions src/BloomExe/Book/BookInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,33 @@ public virtual string AllTitles
set { MetaData.AllTitles = value; }
}

/// <summary>
/// Extract the title for a specific language from AllTitles JSON.
/// Returns the title if found, otherwise returns an empty string.
/// </summary>
public string GetTitleForLanguage(string languageTag)
{
if (string.IsNullOrWhiteSpace(AllTitles) || string.IsNullOrWhiteSpace(languageTag))
return string.Empty;

try
{
var jsonString = AllTitles.Replace("\r", "\\r").Replace("\n", "\\n");
dynamic titles = DynamicJson.Parse(jsonString);
var langs = (IEnumerable<string>)titles.GetDynamicMemberNames();
if (langs.Contains(languageTag))
{
return ((string)titles[languageTag]).Trim();
}
}
catch
{
// If parsing fails, return empty
}

return string.Empty;
}

public string Isbn
{
get { return MetaData.Isbn; }
Expand Down
21 changes: 9 additions & 12 deletions src/BloomExe/CollectionTab/CollectionModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1032,19 +1032,16 @@ private void CreateFromSourceBook(Book.Book sourceBook)
if (newBook == null)
return; //This can happen if there is a configuration dialog and the user clicks Cancel

// We want it to have the name it's eventually going to BEFORE we add it to the collection.
// Otherwise, there are race conditions between the code that is selecting it (and as a side
// effect, bringing it up to date, which may rename it and its folder, if it already has a
// title in the relevant language) and the code that wants to display a thumbnail of the new
// item in the list.
// (We can't fix this by reordering things, because there will also be problems if we attempt
// to select an item before it is present in the collection to select.)
// We know this is a new book object, so there's no point in using EnsureUpToDate.
// When we later select it, that code uses EnsureUpToDate and will not do it again.
// Set before BringBookUpToDate so that title-change events fired during that call
// are suppressed (no spurious Renamed entries). The Created event will be recorded
// when the user enters a title (or various events if no title is entered earlier).
// We want to eventually make a book-created entry in history for this book,
// which includes information about the book we made it from. We want to wait
// to make that record until the new author gives it a name in L1. Possible
// sources for the original name may be lost in the course of bringing it up to
// date, so we capture the original title now. Also, we capture the initial
// L1 title, so we can reliably tell whether the user has actually provided one.
newBook.PendingCreationSource = Path.GetFileName(sourceBook.FolderPath);
var l1Lang = newBook?.BookData?.Language1Tag;
var sourceL1Title = sourceBook.BookInfo.GetTitleForLanguage(l1Lang);
newBook.PendingCreationSourceTitle = sourceL1Title;
newBook.BringBookUpToDate(new NullProgress(), false);

TheOneEditableCollection.AddBookInfo(newBook.BookInfo);
Expand Down