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
16 changes: 16 additions & 0 deletions src/valdi_modules/src/valdi/valdi_core/src/Asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ export type PlatformAssetOverrides = {
android?: string | Asset;
};

export type ThemableAssetMap = {
[colorPaletteName: string]: string | Asset;
};

/**
* Make a platform specific Asset from a default asset `defaultAsset` and
* iOS and/or Android assets in `platformAssetOverrides`. The iOS asset will be
Expand All @@ -97,6 +101,18 @@ export function makePlatformSpecificAsset(
return runtime.makePlatformSpecificAsset(defaultAsset, platformAssetOverrides);
}

/**
* Make a themable Asset from an object keyed by color palette name.
* The asset matching the resolved color palette of the element will be
* rendered. If no asset matches the resolved color palette, nothing is rendered.
* @param assetsByColorPalette an object containing asset overrides keyed by color palette name
* @returns an Asset that can be used as a src attribute, and will use the
* asset matching the resolved color palette.
*/
export function makeThemableAsset(assetsByColorPalette: ThemableAssetMap): Asset {
return runtime.makeThemableAsset(assetsByColorPalette);
}

/**
* Callback called whenever an asset has finished loading.
*/
Expand Down
6 changes: 4 additions & 2 deletions src/valdi_modules/src/valdi/valdi_core/src/ValdiRuntime.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { RuntimeBase } from 'coreutils/src/RuntimeBase';
import { ElementFrame } from 'valdi_tsx/src/Geometry';
import { NativeNode } from 'valdi_tsx/src/NativeNode';
import { NativeView } from 'valdi_tsx/src/NativeView';
import { Asset, PlatformAssetOverrides } from './Asset';
import { Asset, PlatformAssetOverrides, ThemableAssetMap } from './Asset';
import { ElementId } from './IRenderedElement';
import { IRootComponentsManager } from './IRootComponentsManager';
import { RenderRequest } from './RenderRequest';
Expand Down Expand Up @@ -163,6 +163,7 @@ export interface ValdiRuntime extends RuntimeBase {
makeAssetFromBytes(bytes: ArrayBuffer | Uint8Array): Asset;
makeDirectionalAsset(ltrAsset: string | Asset, rtlAsset: string | Asset): Asset;
makePlatformSpecificAsset(defaultAsset: string | Asset, platformAssetOverrides: PlatformAssetOverrides): Asset;
makeThemableAsset(assetsByColorPalette: ThemableAssetMap): Asset;
getAssets(catalogPath: string): AssetEntry[];
addAssetLoadObserver(
asset: string | Asset,
Expand All @@ -173,7 +174,8 @@ export interface ValdiRuntime extends RuntimeBase {
): () => void;
getLoadedAssetMetadata(loadedAsset: LoadedAsset): LoadedAssetMetadata | undefined;

setColorPalette(colorPalette: ColorPalette): void;
configureColorPalette(name: string, colorPalette: ColorPalette): void;
setActiveColorPalette(name: string): void;

outputLog(type: number, content: string): void;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ interface LayoutAttributes {
*/
lazyLayout?: boolean;

/**
* Overrides the configured color palette for this element and descendants.
*/
colorPaletteName?: string;

/**
* @experimental This feature is experimental and may change in future releases.
*
Expand Down
7 changes: 4 additions & 3 deletions valdi/src/valdi/android/NativeBridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1865,9 +1865,10 @@ jlong ValdiAndroid::NativeBridge::createViewFactory( // NOLINT
auto attributes = viewManagerContext->getAttributesManager().getAttributesForClass(cppViewClassName);

if (hasBindAttributes == JNI_TRUE) {
Valdi::AttributesBindingContextImpl bindingContext(viewManagerContext->getAttributesManager().getAttributeIds(),
viewManagerContext->getAttributesManager().getColorPalette(),
runtimeManagerWrapper->getRuntimeManager().getLogger());
Valdi::AttributesBindingContextImpl bindingContext(
viewManagerContext->getAttributesManager().getAttributeIds(),
viewManagerContext->getAttributesManager().getColorPaletteManager(),
runtimeManagerWrapper->getRuntimeManager().getLogger());

auto wrapper = Valdi::makeShared<AttributesBindingContextWrapper>(androidViewManager, bindingContext);
auto ptr = reinterpret_cast<int64_t>(Valdi::unsafeBridgeCast(wrapper.get()));
Expand Down
2 changes: 1 addition & 1 deletion valdi/src/valdi/ios/SCValdiRuntime.mm
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ - (void)setPerformHapticFeedbackFunctionBlock:(void (^)(NSString *))block
auto attributes = attributesManager.getAttributesForClass(viewClassName);

if (attributesBinder) {
Valdi::AttributesBindingContextImpl bindingContext(attributesManager.getAttributeIds(), attributesManager.getColorPalette(), _runtime->getLogger());
Valdi::AttributesBindingContextImpl bindingContext(attributesManager.getAttributeIds(), attributesManager.getColorPaletteManager(), _runtime->getLogger());

SCValdiAttributesBinder *wrapper =
[[SCValdiAttributesBinder alloc] initWithNativeAttributesBindingContext:(SCValdiAttributesBinderNative *)&bindingContext fontManager:_fontManager];
Expand Down
13 changes: 10 additions & 3 deletions valdi/src/valdi/runtime/Attributes/AssetAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ class AssetMeasureDelegate : public DefaultMeasureDelegate {
return Size();
}

asset = asset->withDirection(isRightToLeft);
asset = asset->withConfiguration(AssetConfiguration(nullptr, std::nullopt, isRightToLeft));
if (asset == nullptr) {
return Size();
}

double maxWidth = widthMode == MeasureMode::MeasureModeUnspecified ? -1 : static_cast<double>(width);
double maxHeight = heightMode == MeasureMode::MeasureModeUnspecified ? -1 : static_cast<double>(height);
Expand Down Expand Up @@ -89,8 +92,8 @@ class AssetSrcAttributeHandlerDelegate : public AttributeHandlerDelegate {
if (!result) {
return result.moveError();
}
asset = result.value()->withPlatform(viewNode.getPlatformType());
asset = asset->withDirection(viewNode.isRightToLeft());
asset = result.value()->withConfiguration(AssetConfiguration(
viewNode.getResolvedColorPalette(), viewNode.getPlatformType(), viewNode.isRightToLeft()));
}

setAsset(viewTransactionScope, viewNode, view, asset, callback, associatedData, flipOnRtl);
Expand Down Expand Up @@ -233,8 +236,12 @@ void AssetAttributes::bind(AttributeHandlerById& attributes, Ref<MeasureDelegate
makeShared<AssetSrcAttributeHandlerDelegate>(_assetOutputType),
true);

auto& srcOnLoadHandler = attributes[_attributeIds.getIdForName(srcOnLoad)];
srcOnLoadHandler.setShouldReevaluateOnColorPaletteChange(true);

auto& srcHandler = attributes[srcAttributeId];
srcHandler.appendPostprocessor(postprocessAsset);
srcHandler.setShouldReevaluateOnColorPaletteChange(true);

if (_assetOutputType != snap::valdi_core::AssetOutputType::Lottie) {
auto& filterHandler = attributes[filterAttributeId];
Expand Down
1 change: 1 addition & 0 deletions valdi/src/valdi/runtime/Attributes/AttributeHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ AttributeHandler AttributeHandler::withDelegate(const Ref<AttributeHandlerDelega
}

handler._preprocessors = _preprocessors;
handler._postprocessors = _postprocessors;
if (!_preprocessingTrivial) {
handler._preprocessingTrivial = false;
}
Expand Down
1 change: 1 addition & 0 deletions valdi/src/valdi/runtime/Attributes/AttributeIds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ AttributeIds::AttributeIds() {
registerDefaultAttribute(DefaultAttributeAccessibilityId, "accessibilityId");
registerDefaultAttribute(DefaultAttributeScaleX, "scaleX");
registerDefaultAttribute(DefaultAttributeScaleY, "scaleY");
registerDefaultAttribute(DefaultAttributeColorPaletteName, "colorPaletteName");
}

AttributeIds::~AttributeIds() = default;
Expand Down
1 change: 1 addition & 0 deletions valdi/src/valdi/runtime/Attributes/AttributeIds.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ enum DefaultAttribute : AttributeId {
DefaultAttributeAccessibilityId,
DefaultAttributeScaleX,
DefaultAttributeScaleY,
DefaultAttributeColorPaletteName,
};

class AttributeIds : public snap::NonCopyable {
Expand Down
52 changes: 29 additions & 23 deletions valdi/src/valdi/runtime/Attributes/AttributesBindingContextImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,22 @@ static Result<Value> preprocessString(const Value& value) {
return ValueConverter::toString(value).map<Value>();
}

static Result<Value> postprocessColor(ViewNode& viewNode, const Value& value) {
if (!value.isString()) {
return value;
}

const auto& colorPalette = viewNode.getResolvedColorPalette();
if (colorPalette == nullptr) {
return Error("ViewNode has no resolved ColorPalette");
}
return ValueConverter::toColor(*colorPalette, value);
}

AttributesBindingContextImpl::AttributesBindingContextImpl(AttributeIds& attributeIds,
const Ref<ColorPalette>& colorPalette,
const Ref<ColorPaletteManager>& colorPaletteManager,
ILogger& logger)
: _attributeIds(attributeIds), _colorPalette(colorPalette), _logger(logger) {}
: _attributeIds(attributeIds), _colorPaletteManager(colorPaletteManager), _logger(logger) {}

AttributesBindingContextImpl::~AttributesBindingContextImpl() = default;

Expand Down Expand Up @@ -113,17 +125,19 @@ AttributeId AttributesBindingContextImpl::bindTextAttribute(const StringBox& att
bool invalidateLayoutOnChange,
const Ref<AttributeHandlerDelegate>& delegate) {
auto& registeredHandler = registerHandler(attribute, invalidateLayoutOnChange, delegate);
registeredHandler.appendPreprocessor(
[colorPalette = _colorPalette, logger = &_logger](const Value& value) -> Result<Value> {
if (value.isString()) {
return value;
}
// strict parsing for non production build
auto strict = !snap::kIsAppstoreBuild;
return TextAttributeValueParser::parse(*colorPalette, value, *logger, strict);
},
false);
registeredHandler.setEnablePreprocessorCache(true);
registeredHandler.appendPostprocessor([logger = &_logger](ViewNode& viewNode, const Value& value) -> Result<Value> {
if (value.isString()) {
return value;
}
// strict parsing for non production build
auto strict = !snap::kIsAppstoreBuild;
const auto& colorPalette = viewNode.getResolvedColorPalette();
if (colorPalette == nullptr) {
return Error("ViewNode has no resolved ColorPalette");
}
return TextAttributeValueParser::parse(*colorPalette, value, *logger, strict);
});
registeredHandler.setShouldReevaluateOnColorPaletteChange(true);

return registeredHandler.getId();
}
Expand Down Expand Up @@ -261,16 +275,8 @@ const AttributeHandlerById& AttributesBindingContextImpl::getHandlers() const {
}

void AttributesBindingContextImpl::registerColorPreprocessor(AttributeHandler& handler) {
handler.appendPreprocessor(
[colorPalette = _colorPalette](const Value& value) -> Result<Value> {
auto color = ValueConverter::toColor(*colorPalette, value);
if (!color) {
return color.moveError();
}

return Value(color.value().value);
},
false);
handler.appendPreprocessor(&ValueConverter::toColorValue, false);
handler.appendPostprocessor(&postprocessColor);
handler.setShouldReevaluateOnColorPaletteChange(true);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class ILogger;

class AttributesBindingContextImpl : public AttributesBindingContext {
public:
AttributesBindingContextImpl(AttributeIds& attributeIds, const Ref<ColorPalette>& colorPalette, ILogger& logger);
AttributesBindingContextImpl(AttributeIds& attributeIds,
const Ref<ColorPaletteManager>& colorPaletteManager,
ILogger& logger);
~AttributesBindingContextImpl() override;

void registerPreprocessor(const Valdi::StringBox& attribute,
Expand Down Expand Up @@ -83,7 +85,7 @@ class AttributesBindingContextImpl : public AttributesBindingContext {

private:
AttributeIds& _attributeIds;
Ref<ColorPalette> _colorPalette;
Ref<ColorPaletteManager> _colorPaletteManager;
ILogger& _logger;
AttributeHandlerById _handlers;
Ref<AttributeHandlerDelegate> _defaultDelegate;
Expand Down
22 changes: 11 additions & 11 deletions valdi/src/valdi/runtime/Attributes/AttributesManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,22 @@ namespace Valdi {

AttributesManager::AttributesManager(IViewManager& viewManager,
AttributeIds& attributeIds,
const Ref<ColorPalette>& colorPalette,
const Ref<ColorPaletteManager>& colorPaletteManager,
ILogger& logger,
std::shared_ptr<YGConfig> yogaConfig)
: _viewManager(viewManager),
_attributeIds(attributeIds),
_logger(logger),
_yogaConfig(std::move(yogaConfig)),
_colorPalette(colorPalette) {}
_colorPaletteManager(colorPaletteManager) {}

void AttributesManager::registerPreprocessor(AttributeId attributeId,
Result<Value> (*preprocessor)(const Ref<ColorPalette>&, const Value&)) {
registerPreprocessor(attributeId,
[colorPalette = _colorPalette, preprocessor](const Value& value) -> Result<Value> {
return preprocessor(colorPalette, value);
});
Result<Value> (*preprocessor)(const Ref<ColorPaletteManager>&,
const Value&)) {
registerPreprocessor(
attributeId, [colorPaletteManager = _colorPaletteManager, preprocessor](const Value& value) -> Result<Value> {
return preprocessor(colorPaletteManager, value);
});
}

void AttributesManager::registerPreprocessor(AttributeId attributeId,
Expand Down Expand Up @@ -88,7 +89,6 @@ SharedBoundAttributes AttributesManager::lockFreeGetAttributesForClass(const Str
scrollAttributesBound);

_boundAttributesByClass[className] = boundAttributes;

return boundAttributes;
}

Expand Down Expand Up @@ -129,7 +129,7 @@ void AttributesManager::populateAttributeHandlerById(AttributeHandlerById& attri
}

if (!isLayoutClass) {
AttributesBindingContextImpl binder(_attributeIds, _colorPalette, _logger);
AttributesBindingContextImpl binder(_attributeIds, _colorPaletteManager, _logger);
_viewManager.bindAttributes(className, binder);

if (binder.getDefaultDelegate() != nullptr) {
Expand Down Expand Up @@ -196,8 +196,8 @@ AttributeIds& AttributesManager::getAttributeIds() const {
return _attributeIds;
}

const Ref<ColorPalette>& AttributesManager::getColorPalette() const {
return _colorPalette;
const Ref<ColorPaletteManager>& AttributesManager::getColorPaletteManager() const {
return _colorPaletteManager;
}

const StringBox& AttributesManager::getLayoutPlaceholderClassName() {
Expand Down
9 changes: 4 additions & 5 deletions valdi/src/valdi/runtime/Attributes/AttributesManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,24 @@ class AttributesManager {
public:
AttributesManager(IViewManager& viewManager,
AttributeIds& attributeIds,
const Ref<ColorPalette>& colorPalette,
const Ref<ColorPaletteManager>& colorPaletteManager,
ILogger& logger,
std::shared_ptr<YGConfig> yogaConfig);

void registerPreprocessor(AttributeId attributeId, const AttributePreprocessor& preprocessor);
void registerPreprocessor(AttributeId attributeId,
Result<Value> (*preprocessor)(const Ref<ColorPalette>&, const Value&));
Result<Value> (*preprocessor)(const Ref<ColorPaletteManager>&, const Value&));
void registerPostprocessor(AttributeId attributeId,
Result<Value> (*postprocessor)(ViewNode& viewNode, const Value& value));

SharedBoundAttributes getAttributesForClass(const StringBox& className) noexcept;
FlatMap<StringBox, SharedBoundAttributes> getAllBoundAttributes() const;

IViewManager& getViewManager() const;
ILogger& getLogger() const;
YGConfig* getYogaConfig() const;

AttributeIds& getAttributeIds() const;
const Ref<ColorPalette>& getColorPalette() const;
const Ref<ColorPaletteManager>& getColorPaletteManager() const;

static const StringBox& getLayoutPlaceholderClassName();
static const StringBox& getDeferredClassName();
Expand All @@ -61,7 +60,7 @@ class AttributesManager {
FlatMap<StringBox, SharedBoundAttributes> _boundAttributesByClass;
FlatMap<AttributeId, std::vector<AttributePreprocessor>> _preprocessors;
FlatMap<AttributeId, std::vector<AttributePostprocessor>> _postprocessors;
Ref<ColorPalette> _colorPalette;
Ref<ColorPaletteManager> _colorPaletteManager;
mutable std::mutex _mutex;

SharedBoundAttributes lockFreeGetAttributesForClass(const StringBox& className) noexcept;
Expand Down
Loading
Loading