Skip to content

Commit

Permalink
Allow cover to be full-bleed image (BL-13271)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrew-polk committed Aug 22, 2024
1 parent b00ebef commit 5899216
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 37 deletions.
12 changes: 12 additions & 0 deletions DistFiles/localization/en/BloomMediumPriority.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
<note>We are in the process of moving strings from Bloom.xlf to BloomMediumPriority.xlf and BloomLowPriority.xlf while trying very hard to preserve translations and approval status.</note>
</header>
<body>
<trans-unit id="AvailableWithEnterprise" translate="no">
<source xml:lang="en">Available with your Enterprise Subscription</source>
<note>ID: AvailableWithEnterprise</note>
</trans-unit>
<!-- Drag Activity Tool -->
<trans-unit id="EditTab.Toolbox.DragActivity.Check" translate="no">
<source xml:lang="en">Check</source>
Expand Down Expand Up @@ -584,6 +588,14 @@
<source xml:lang="en">Cover</source>
<note>BookSettings.CoverGroupLabel</note>
</trans-unit>
<trans-unit id="BookSettings.CoverIsImage" sil:dynamic="true" translate="no">
<source xml:lang="en">Fill the front cover with a single image</source>
<note>BookSettings.CoverIsImage</note>
</trans-unit>
<trans-unit id="BookSettings.CoverIsImage.Description" sil:dynamic="true" translate="no">
<source xml:lang="en">Using this option turns on the [Print Bleed](https://docs.bloomlibrary.org) indicators on paper layouts. See [Full Page Cover Images](https://docs.bloomlibrary.org) for information on sizing your image to fit.</source>
<note>BookSettings.CoverIsImage.Description</note>
</trans-unit>
<trans-unit id="BookSettings.ContentPagesGroupLabel" sil:dynamic="true">
<source xml:lang="en">Content Pages</source>
<note>BookSettings.ContentPagesGroupLabel</note>
Expand Down
47 changes: 46 additions & 1 deletion src/BloomBrowserUI/bookEdit/bookSettings/BookSettingsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ import { NoteBox, WarningBox } from "../../react_components/boxes";
import { default as TrashIcon } from "@mui/icons-material/Delete";
import { PWithLink } from "../../react_components/pWithLink";
import { FieldVisibilityGroup } from "./FieldVisibilityGroup";
import {
BloomEnterpriseIndicatorIconAndText,
useEnterpriseAvailable
} from "../../react_components/requiresBloomEnterprise";

let isOpenAlready = false;

Expand Down Expand Up @@ -190,6 +194,16 @@ export const BookSettingsDialog: React.FunctionComponent<{
const resolutionLabel = useL10n("Resolution", "BookSettings.Resolution");
const bloomPubLabel = useL10n("eBooks", "PublishTab.bloomPUBButton"); // reuse the same string localized for the Publish tab

const coverIsImageLabel = useL10n(
"Fill the front cover with a single image",
"BookSettings.CoverIsImage"
);
//TODO real links (and change .xlf)
const coverIsImageDescription = useL10n(
"Using this option turns on the [Print Bleed](https://docs.bloomlibrary.org) indicators on paper layouts. See [Full Page Cover Images](https://docs.bloomlibrary.org) for information on sizing your image to fit.",
"BookSettings.CoverIsImage.Description"
);

// This is a helper function to make it easier to pass the override information
function getAdditionalProps<T>(
subPath: string
Expand Down Expand Up @@ -288,6 +302,8 @@ export const BookSettingsDialog: React.FunctionComponent<{
setMigratedTheme("");
};

const enterpriseAvailable = useEnterpriseAvailable();

return (
<BloomDialog
css={css`
Expand Down Expand Up @@ -323,7 +339,7 @@ export const BookSettingsDialog: React.FunctionComponent<{
height: 600px;
// This odd width was chosen to make the customBookStyles alert box format nicely.
// See BL-12956. It's not that important, but I don't think anything else is affected
// much by the exact witdh.
// much by the exact width.
width: 638px;
#groups {
margin-right: 10px; // make room for the scrollbar
Expand Down Expand Up @@ -375,6 +391,35 @@ export const BookSettingsDialog: React.FunctionComponent<{
</Div>
</NoteBox>
)}

<div>
<ConfigrBoolean
label={coverIsImageLabel}
description={coverIsImageDescription}
{...getAdditionalProps<boolean>(
`coverIsImage`
)}
disabled={
appearanceDisabled ||
!enterpriseAvailable
}
/>
<div
css={css`
display: flex;
padding-bottom: 5px;
font-size: 12px;
font-weight: bold;
`}
>
<BloomEnterpriseIndicatorIconAndText
css={css`
margin-left: auto;
`}
disabled={appearanceDisabled}
/>
</div>
</div>
<FieldVisibilityGroup
field="cover-title"
labelFrame="Show Title in {0}"
Expand Down
44 changes: 43 additions & 1 deletion src/BloomBrowserUI/react_components/requiresBloomEnterprise.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { get, post } from "../utils/bloomApi";
import Button from "@mui/material/Button";
import { kBloomBlue50Transparent, lightTheme } from "../bloomMaterialUITheme";
import { ThemeProvider, StyledEngineProvider } from "@mui/material/styles";
import { Div } from "./l10nComponents";
import { Div, Span } from "./l10nComponents";
import { useL10n } from "./l10nHooks";
import { WireUpForWinforms } from "../utils/WireUpWinform";
import { Dialog, DialogActions, DialogContent } from "@mui/material";
Expand Down Expand Up @@ -490,6 +490,48 @@ export const RequiresBloomEnterpriseDialog: React.FunctionComponent<{
);
};

export const BloomEnterpriseIndicatorIconAndText: React.FunctionComponent<{
disabled?: boolean;
className?: string;
}> = props => {
const enterpriseAvailable = useEnterpriseAvailable();

return (
<div
onClick={() => {
enterpriseAvailable ||
props.disabled ||
openBloomEnterpriseSettings();
}}
css={css`
display: flex;
align-items: center;
${enterpriseAvailable || props.disabled || "cursor:pointer"};
opacity: ${props.disabled ? kBloomDisabledOpacity : 1.0};
`}
className={props.className}
>
<img
src={badgeUrl}
css={css`
height: 1.5em;
padding-right: 0.5em;
`}
/>
{enterpriseAvailable ? (
<Span l10nKey={"AvailableWithEnterprise"}>
Available with your Enterprise Subscription
</Span>
) : (
<Span l10nKey={"Common.EnterpriseRequired"}>
Enterprise Required
</Span>
)}
</div>
);
};

function openBloomEnterpriseSettings() {
post("common/showSettingsDialog?tab=enterprise");
}
Expand Down
109 changes: 89 additions & 20 deletions src/BloomExe/Book/AppearanceSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Navigation;
using Amazon.Auth.AccessControlPolicy;
using Bloom;
using Bloom.Book;
using Bloom.web.controllers;
Expand All @@ -27,9 +25,9 @@ public class AppearanceSettings
public AppearanceSettings()
{
_properties = new ExpandoObject();
if (_substitutinator == null)
if (_appearanceMigrator == null)
{
_substitutinator = new AppearanceMigrator();
_appearanceMigrator = new AppearanceMigrator();
}

// copy in the default values from each definition
Expand All @@ -45,7 +43,7 @@ public AppearanceSettings()
public static string kDoShowValueForDisplay = "doShow-css-will-ignore-this-and-use-default"; // by using an illegal value, we just get a no-op rule, which is what we want
public static string kHideValueForDisplay = "none";
public static string kOverrideGroupsArrayKey = "groupsToOverrideFromParent"; // e.g. "coverFields, xmatter"
private static AppearanceMigrator _substitutinator;
private static AppearanceMigrator _appearanceMigrator;

// A representation of the content of Appearance.json
internal dynamic _properties;
Expand Down Expand Up @@ -110,9 +108,17 @@ public string FirstPossiblyOffendingCssFile
// The default here is rarely if ever relevant. Usually a newly created instance will be initialized from a folder, and the default will be overwritten,
// either to whatever we find in appearance.json, or to "legacy-5-6" if there is no appearance.json.
new StringPropertyDef("cssThemeName", "cssThemeName", "default"),
// Cover page is just a full bleed image.
new BooleanPropertyDef("coverIsImage", "coverIsImage", false),
// Not implemented yet. When it is, it needs to be tied together with the coverIsImage setting
// such that coverIsImage cannot be true unless fullBleed is also true.
// Book is full bleed.
//new BooleanPropertyDef("fullBleed", "fullBleed", false),
// Todo: when we implement this setting, we want to migrate the old record of color color.
// See code commented out in BringBookUpToDateUnprotected.
//new CssStringVariableDef("coverColor","colors","yellow"),

// User can turn the visibility of these fields on and off in the dialog.
new CssDisplayVariableDef("cover-title-L1-show", "coverFields", true),
new CssDisplayVariableDef("cover-title-L2-show", "coverFields", true),
new CssDisplayVariableDef("cover-title-L3-show", "coverFields", false),
Expand Down Expand Up @@ -156,9 +162,63 @@ public string FirstPossiblyOffendingCssFile
public string CssThemeName
{
get { return _properties.cssThemeName; }
set { _properties.cssThemeName = value; }
set
{
_properties.cssThemeName = value;
SetRequiredValuesIfLegacyTheme();
}
}

// Some setting values are not allowed in legacy mode.
private void SetRequiredValuesIfLegacyTheme()
{
if (CssThemeName != "legacy-5-6") // Can't use UsingLegacy here because it includes logic about the syncing of files which we don't want.
return;

var propertyValuesRequiredByLegacyTheme = new Dictionary<string, object>()
{
//REVIEW: I think that some of the other properties should also be here.
// This concept of forcing a value based on the legacy theme was introduced at the time coverIsImage was added.
// But I think the properties which existed before that and which get disabled by setting the theme
// to legacy should also be here.
// e.g. cover-topic-show
// Without this, the user can set the theme to non-legacy, change the property to whatever he wants,
// then change the theme back to legacy.
{ "coverIsImage", false }
};
foreach (var property in propertyValuesRequiredByLegacyTheme)
SetProperty(property);
}

private void SetProperty(KeyValuePair<string, object> property)
{
var propertiesWhichRequireXmatterUpdate = new string[] { "coverIsImage" };
if (
(
!Properties.ContainsKey(property.Key)
|| !Properties[property.Key].Equals(property.Value)
) && propertiesWhichRequireXmatterUpdate.Contains(property.Key)
)
{
PendingChangeRequiresXmatterUpdate = true;
}

Properties[property.Key] = property.Value;
}

public bool CoverIsImage
{
get { return _properties.coverIsImage; }
}

//public bool FullBleed
//{
// get { return _properties.fullBleed; }
// set { _properties.fullBleed = value; }
//}

public bool PendingChangeRequiresXmatterUpdate;

/// <summary>
/// Usually, this is simply the theme name, but if the book doesn't have one (that is, it was made by
/// an earlier Bloom and has not been migrated), it answers "none". Currently this is used only
Expand Down Expand Up @@ -667,9 +727,9 @@ public string GetCssOwnPropsDeclaration(dynamic properties, AppearanceSettings p
}
}

if (definition is CssPropertyDef)
if (definition is CssPropertyDef cssPropertydefinition)
{
var setting = ((PropertyDef)definition).GetCssVariableDeclaration(keyValuePair);
var setting = cssPropertydefinition.GetCssVariableDeclaration(keyValuePair);
if (!string.IsNullOrEmpty(setting))
cssBuilder.AppendLine("\t" + setting);
}
Expand Down Expand Up @@ -786,13 +846,14 @@ internal void UpdateFromJson(string json)
{
// parse the json into an object
var x = JsonConvert.DeserializeObject<ExpandoObject>(json);
//and then for each property, copy into the _properties object
// For backwards capabilty, if the json we are reading has a null for a value,
// do not override the default value that we already have loaded.

// and then for each property, copy into the Properties object.
// The original comment here also said: For backwards capability, if the json we are reading has a null for a value, do not override the default value that we already have loaded.
// But the code didn't seem to implement that when I got here. (AP, Aug 2024)
foreach (var property in (IDictionary<string, object>)x)
{
Properties[property.Key] = property.Value;
}
SetProperty(property);

SetRequiredValuesIfLegacyTheme();
}

/// <summary>
Expand Down Expand Up @@ -952,12 +1013,9 @@ public void SetDefault(dynamic prop)
/// The name of the group of properties that can a book can override from a collection, or a page can override from a book.
/// </summary>
public string OverrideGroup;

public abstract string GetCssVariableDeclaration(dynamic property);
}

public abstract class CssPropertyDef : PropertyDef { }

// StringPropertyDefs and BooleanPropertyDefs get written to appearance.json but not appearance.css
public class StringPropertyDef : PropertyDef
{
public StringPropertyDef(string name, string overrideGroup, string defaultValue)
Expand All @@ -966,13 +1024,24 @@ public StringPropertyDef(string name, string overrideGroup, string defaultValue)
DefaultValue = defaultValue;
OverrideGroup = overrideGroup;
}
}

public override string GetCssVariableDeclaration(dynamic property)
public class BooleanPropertyDef : PropertyDef
{
public BooleanPropertyDef(string name, string overrideGroup, bool defaultValue)
{
return $"--{Name}: {property.Value};";
Name = name;
OverrideGroup = overrideGroup;
DefaultValue = defaultValue;
}
}

// CssPropertyDefs get written to appearance.json and appearance.css
public abstract class CssPropertyDef : PropertyDef
{
public abstract string GetCssVariableDeclaration(dynamic property);
}

public class CssStringVariableDef : CssPropertyDef
{
public CssStringVariableDef(string name, string overrideGroup, string defaultValue = null)
Expand Down
17 changes: 14 additions & 3 deletions src/BloomExe/Book/Book.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2349,7 +2349,9 @@ public void BringXmatterHtmlUpToDate(HtmlDom bookDOM)
layout,
BookInfo.UseDeviceXMatter,
_bookData.MetadataLanguage1Tag,
oldIds
oldIds,
BookInfo.AppearanceSettings.CoverIsImage
&& CollectionSettings.HaveEnterpriseFeatures
);

var dataBookLangs = bookDOM.GatherDataBookLanguages();
Expand Down Expand Up @@ -3853,8 +3855,13 @@ public void InsertFullBleedMarkup(SafeXmlElement body)
}

public bool FullBleed =>
BookData.GetVariableOrNull("fullBleed", "*").Xml == "true"
&& CollectionSettings.HaveEnterpriseFeatures;
(
// Wants to be
// BookInfo.AppearanceSettings.FullBleed
// but we haven't put that in the book settings yet.
BookData.GetVariableOrNull("fullBleed", "*").Xml == "true"
|| BookInfo.AppearanceSettings.CoverIsImage
) && CollectionSettings.HaveEnterpriseFeatures;

/// <summary>
/// Save the page content to the DOM.
Expand Down Expand Up @@ -4541,6 +4548,10 @@ public void Save()
PageTemplateSource = Path.GetFileName(FolderPath);
}

if (BookInfo.AppearanceSettings.PendingChangeRequiresXmatterUpdate)
EnsureUpToDateMemory(new NullProgress());
BookInfo.AppearanceSettings.PendingChangeRequiresXmatterUpdate = false;

try
{
Storage.Save();
Expand Down
Loading

0 comments on commit 5899216

Please sign in to comment.