Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow cover to be full-bleed image (BL-13271) #6602

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
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">
<source xml:lang="en">Check</source>
Expand Down Expand Up @@ -600,6 +604,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
46 changes: 45 additions & 1 deletion src/BloomBrowserUI/bookEdit/bookSettings/BookSettingsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ import { default as TrashIcon } from "@mui/icons-material/Delete";
import { PWithLink } from "../../react_components/pWithLink";
import { FieldVisibilityGroup } from "./FieldVisibilityGroup";
import { StyleAndFontTable } from "./StyleAndFontTable";
import {
BloomEnterpriseIndicatorIconAndText,
useEnterpriseAvailable
} from "../../react_components/requiresBloomEnterprise";

let isOpenAlready = false;

Expand Down Expand Up @@ -208,6 +212,16 @@ export const BookSettingsDialog: React.FunctionComponent<{
"BookSettings.TopLevelTextPadding.1emLabel"
);

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 @@ -306,6 +320,8 @@ export const BookSettingsDialog: React.FunctionComponent<{
setMigratedTheme("");
};

const enterpriseAvailable = useEnterpriseAvailable();

function saveSettingsAndCloseDialog() {
if (settingsToReturnLater) {
// If nothing changed, we don't get any...and don't need to make this call.
Expand Down Expand Up @@ -353,7 +369,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 @@ -398,6 +414,34 @@ export const BookSettingsDialog: React.FunctionComponent<{
label={whatToShowOnCoverLabel}
path={`appearance`}
>
<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
136 changes: 117 additions & 19 deletions src/BloomExe/Book/AppearanceSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,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 @@ -43,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 @@ -108,7 +108,20 @@ 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"),
// BooleanPropertyDef, not CssXDef because this is not a css variable.
new BooleanPropertyDef(
"coverIsImage",
"coverIsImage",
defaultValue: false,
requiresXmatterUpdate: true,
valueRequiredIfLegacyTheme: false
), // If true, cover page is just a full bleed image.
// 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.
//new BooleanPropertyDef("fullBleed", "fullBleed", false), // If true, book is full bleed.

new CssStringVariableDef("cover-background-color", "colors"),
// 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 +169,69 @@ public string FirstPossiblyOffendingCssFile
public string CssThemeName
{
get { return _properties.cssThemeName; }
set { _properties.cssThemeName = value; }
set
{
_properties.cssThemeName = value;
SetRequiredValuesIfLegacyTheme();
}
}

// Some setting's values are not allowed in legacy mode.
// REVIEW:
// This concept of forcing a value based on the legacy theme was introduced at the time coverIsImage was added.
// And currently (Dec 2024), it is the only property that has a valueRequiredIfLegacyTheme.
// But I think the properties which existed before that and which get disabled by setting the theme
// to legacy should also be set. 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.
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;

foreach (var propertyDefinition in propertyDefinitions)
{
if (propertyDefinition.ValueRequiredIfLegacyTheme != null)
{
SetProperty(
new KeyValuePair<string, object>(
propertyDefinition.Name,
propertyDefinition.ValueRequiredIfLegacyTheme
)
);
}
}
}

private void SetProperty(KeyValuePair<string, object> property)
{
if (
!Properties.ContainsKey(property.Key)
|| !Properties[property.Key].Equals(property.Value)
)
{
var propDef = propertyDefinitions.FirstOrDefault(pd => pd.Name == property.Key);
if (propDef?.RequiresXmatterUpdate == true)
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; }
//}

// When this is set to true, we ensure that the xmatter is updated before saving the book.
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 @@ -682,9 +755,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 @@ -801,13 +874,12 @@ 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.
foreach (var property in (IDictionary<string, object>)x)
{
Properties[property.Key] = property.Value;
}
SetProperty(property);

SetRequiredValuesIfLegacyTheme();
}

/// <summary>
Expand Down Expand Up @@ -971,6 +1043,8 @@ public abstract class PropertyDef
{
public string Name;
public dynamic DefaultValue;
public bool RequiresXmatterUpdate;
public object ValueRequiredIfLegacyTheme;

public void SetDefault(dynamic prop)
{
Expand All @@ -981,27 +1055,51 @@ 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)
public StringPropertyDef(
string name,
string overrideGroup,
string defaultValue,
bool requiresXmatterUpdate = false,
object valueRequiredIfLegacyTheme = null
)
{
Name = name;
DefaultValue = defaultValue;
OverrideGroup = overrideGroup;
RequiresXmatterUpdate = requiresXmatterUpdate;
ValueRequiredIfLegacyTheme = valueRequiredIfLegacyTheme;
}
}

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

// 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
Loading