Skip to content

Commit

Permalink
feat: add support for multiple image scales (#21)
Browse files Browse the repository at this point in the history
* chore: reference .png files for mock images in PoodleSurf iOS

* feat: add support for defining multiple scale assets for an image

* fix: add 1x and 2x assets

* fix: mock image sizes for non-3x devices

* fix: HelloMyStateBag iOS example

* fix: ios test goldens and fixture bindings

* fix: android Image bindings

* fix: add @2x and @3x image assets fixtures for tests

* fix: fix background drawing on android

* fix: failing test

* chore: use File instead of Image for mock model images

* fix: web goldens
  • Loading branch information
n8chur authored and roperzh committed Nov 14, 2019
1 parent 38d1403 commit b61b1b1
Show file tree
Hide file tree
Showing 66 changed files with 313 additions and 238 deletions.
Binary file modified examples/playground/assets/images/diez.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/playground/assets/images/diez@2x.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/playground/assets/images/diez@3x.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified examples/playground/assets/images/haiku.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/playground/assets/images/haiku@2x.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/playground/assets/images/haiku@3x.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 2 additions & 9 deletions examples/playground/src/MyStateBag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,8 @@ export class MyStateBag extends Component {

@property numbers: Integer[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

@property image = new Image({
file: new File({
// Try changing this to diez.jpg!
src: 'assets/images/haiku.jpg',
}),
width: 246,
height: 246,
scale: 3,
});
// Try changing this to `assets/images/diez`!
@property image = Image.responsive('assets/images/haiku', 'jpg');

@property svg = new SVG({src: 'assets/images/rat.svg'});

Expand Down
Binary file added examples/poodle-surf/assets/images/Gear.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/poodle-surf/assets/images/Gear@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/poodle-surf/assets/images/Gear@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/poodle-surf/assets/images/Icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/poodle-surf/assets/images/Icon@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/poodle-surf/assets/images/Map Pin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/poodle-surf/assets/images/Map Pin@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/poodle-surf/assets/images/Thermometer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 9 additions & 5 deletions examples/poodle-surf/ios/PoodleSurf.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
/* Begin PBXBuildFile section */
46087BE7225D341600F4B63F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46087BE6225D341600F4B63F /* AppDelegate.swift */; };
46087BE9225D341600F4B63F /* ReportViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46087BE8225D341600F4B63F /* ReportViewController.swift */; };
46087BEE225D341800F4B63F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 46087BED225D341800F4B63F /* Assets.xcassets */; };
46087BF1225D341800F4B63F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 46087BEF225D341800F4B63F /* LaunchScreen.storyboard */; };
46087BFA225D3F9900F4B63F /* ReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46087BF9225D3F9900F4B63F /* ReportView.swift */; };
46087BFC225D419500F4B63F /* ReportHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46087BFB225D419500F4B63F /* ReportHeaderView.swift */; };
Expand Down Expand Up @@ -40,6 +39,8 @@
46087C5D22623BD100F4B63F /* LoadingViewController+FallbackStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46087C5C22623BD100F4B63F /* LoadingViewController+FallbackStyle.swift */; };
46087C5F22623D8800F4B63F /* ReportViewController+Diez.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46087C5E22623D8800F4B63F /* ReportViewController+Diez.swift */; };
46087C6122623D9400F4B63F /* LoadingViewController+Diez.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46087C6022623D9400F4B63F /* LoadingViewController+Diez.swift */; };
46E14CA4226E38CF007938DA /* mock in Resources */ = {isa = PBXBuildFile; fileRef = 46E14CA3226E38CF007938DA /* mock */; };
46E14CA6226E3933007938DA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 46E14CA5226E3933007938DA /* Assets.xcassets */; };
D036E2EDC4B2DFDD9B65F7E3 /* Pods_PoodleSurf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 004A5CE4D3AFF9FBB963C591 /* Pods_PoodleSurf.framework */; };
/* End PBXBuildFile section */

Expand All @@ -49,7 +50,6 @@
46087BE3225D341600F4B63F /* PoodleSurf.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PoodleSurf.app; sourceTree = BUILT_PRODUCTS_DIR; };
46087BE6225D341600F4B63F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
46087BE8225D341600F4B63F /* ReportViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportViewController.swift; sourceTree = "<group>"; };
46087BED225D341800F4B63F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
46087BF0225D341800F4B63F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
46087BF2225D341800F4B63F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
46087BF9225D3F9900F4B63F /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -81,6 +81,8 @@
46087C5C22623BD100F4B63F /* LoadingViewController+FallbackStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LoadingViewController+FallbackStyle.swift"; sourceTree = "<group>"; };
46087C5E22623D8800F4B63F /* ReportViewController+Diez.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ReportViewController+Diez.swift"; sourceTree = "<group>"; };
46087C6022623D9400F4B63F /* LoadingViewController+Diez.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LoadingViewController+Diez.swift"; sourceTree = "<group>"; };
46E14CA3226E38CF007938DA /* mock */ = {isa = PBXFileReference; lastKnownFileType = folder; path = mock; sourceTree = "<group>"; };
46E14CA5226E3933007938DA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
C1D82D16AD79B2D902C96B87 /* Pods-PoodleSurf.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PoodleSurf.release.xcconfig"; path = "Target Support Files/Pods-PoodleSurf/Pods-PoodleSurf.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -179,10 +181,11 @@
46087C0F225D74C900F4B63F /* Resources */ = {
isa = PBXGroup;
children = (
46087BED225D341800F4B63F /* Assets.xcassets */,
46E14CA5226E3933007938DA /* Assets.xcassets */,
46087BF2225D341800F4B63F /* Info.plist */,
46087BEF225D341800F4B63F /* LaunchScreen.storyboard */,
46087C4A2260084000F4B63F /* hang10.json */,
46087BEF225D341800F4B63F /* LaunchScreen.storyboard */,
46E14CA3226E38CF007938DA /* mock */,
);
path = Resources;
sourceTree = "<group>";
Expand Down Expand Up @@ -298,7 +301,8 @@
files = (
46087C4B2260084000F4B63F /* hang10.json in Resources */,
46087BF1225D341800F4B63F /* LaunchScreen.storyboard in Resources */,
46087BEE225D341800F4B63F /* Assets.xcassets in Resources */,
46E14CA6226E3933007938DA /* Assets.xcassets in Resources */,
46E14CA4226E38CF007938DA /* mock in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,48 +9,12 @@
import UIKit

extension UIImage {
static func getURLForImage(named name: String) -> URL? {
let fileManager = FileManager.default

guard let cacheDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first else {
return nil
}

let url = cacheDirectory.appendingPathComponent("\(name).png")

guard fileManager.fileExists(atPath: url.path) else {
guard
let image = UIImage(named: name),
let data = image.pngData() else {
return nil
}

fileManager.createFile(atPath: url.path, contents: data)

return url
}

return url
}

/// TODO: Use asynchronous method instead. Possibly also rely on the suffix for image scale.
/// - Note: Assumes remote assets (URLs with a scheme prefixed with "http") are delivered at 3x but local assets are
/// at the scale of the UIScreen.main.screen.
// TODO: Use asynchronous method instead.
convenience init?(url: URL) {
guard let data = try? Data(contentsOf: url) else {
return nil
}

let scale: CGFloat = {
// Assume remote assets (URLs with a scheme prefixed with "http") are delivered at 3x but local assets are
// at the scale of the UIScreen.main.screen.
if url.scheme?.hasPrefix("http") == true {
return 3
}

return UIScreen.main.scale
}()

self.init(data: data, scale: scale)
self.init(data: data)
}
}
49 changes: 49 additions & 0 deletions examples/poodle-surf/ios/PoodleSurf/Report/Cards/DayPartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,47 @@ class DayPartView: UIView {
set { valueStackView.layoutMargins = newValue }
}

var iconWidth: CGFloat? {
get {
let constraintValue = iconWidthConstraint.isActive ? iconWidthConstraint.constant : 0
if constraintValue > 0 {
return constraintValue
}

return iconView.image?.size.width
}
set {
update(iconWidthConstraint, with: newValue)
}
}

var iconHeight: CGFloat? {
get {
let constraintValue = iconHeightConstraint.isActive ? iconHeightConstraint.constant : 0
if constraintValue > 0 {
return constraintValue
}

return iconView.image?.size.height
}
set {
update(iconHeightConstraint, with: newValue)
}
}

override class var requiresConstraintBasedLayout: Bool { return true }

private let outterStackView: UIStackView
private let valueStackView: UIStackView
private var iconWidthConstraint: NSLayoutConstraint!
private var iconHeightConstraint: NSLayoutConstraint!

private func setupLayout() {
embed(outterStackView)

// Do not activate this constraint yet. Only activate if a value is set by a consumer.
iconWidthConstraint = iconView.widthAnchor.constraint(equalToConstant: 0)
iconHeightConstraint = iconView.heightAnchor.constraint(equalToConstant: 0)
}

private func configureViews() {
Expand All @@ -77,6 +111,21 @@ class DayPartView: UIView {
unitLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
}

/// If the newValue > 0, then the constraint will be made active and have its constant set to the new value.
/// If the newValue <= 0, then the constraint will be made inactive and its constant will be set to 0.
private func update(_ constraint: NSLayoutConstraint, with newValue: CGFloat?) {
guard
let newValue = newValue,
newValue > 0 else {
constraint.constant = 0
constraint.isActive = false
return
}

constraint.constant = newValue
constraint.isActive = true
}

@available(*, unavailable)
required init?(coder aDecoder: NSCoder) { fatalError("\(#function) not implemented.") }
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ extension ReportModel {
let location = Location(
region: "Santa Cruz, CA",
place: "Natural Bridges State Park",
mapImage: UIImage.getURLForImage(named: "Santa Cruz Map")!,
bannerImage: UIImage.getURLForImage(named: "Santa Cruz Banner")!)
mapImage: ReportModel.url(forImageNamed: "Santa Cruz Map")!,
bannerImage: ReportModel.url(forImageNamed: "Santa Cruz Banner")!)

let temperature = Temperature(
formattedValue: "55°F",
Expand All @@ -30,22 +30,28 @@ extension ReportModel {

return ReportModel(location: location, temperature: temperature, wind: wind, swell: swell, tide: tide)
}

/// Returns the URL for the @3x png image with the provided name (found in the `mock/images` folder).
fileprivate static func url(forImageNamed name: String) -> URL? {
let bundle = Bundle.main
return bundle.url(forResource: "\(name)", withExtension: "png", subdirectory: "mock/images")
}
}

extension ReportModel.WindForecast {
static func makeExample(earlyTime: String, middleTime: String, lateTime: String) -> ReportModel.WindForecast {
let early = DayPart(
directionImage: UIImage.getURLForImage(named: "Direction - South West")!,
directionImage: ReportModel.url(forImageNamed: "Direction - South West")!,
value: "4",
time: earlyTime)

let middle = DayPart(
directionImage: UIImage.getURLForImage(named: "Direction - South")!,
directionImage: ReportModel.url(forImageNamed: "Direction - South")!,
value: "12",
time: middleTime)

let late = DayPart(
directionImage: UIImage.getURLForImage(named: "Direction - North East")!,
directionImage: ReportModel.url(forImageNamed: "Direction - North East")!,
value: "17",
time: lateTime)

Expand Down
11 changes: 7 additions & 4 deletions examples/poodle-surf/ios/PoodleSurf/Report/ReportView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,26 @@ class ReportView: UIView {
}

private func setupLayout() {
var constraints: [NSLayoutConstraint] = []
scrollView.translatesAutoresizingMaskIntoConstraints = false
addSubview(scrollView)
NSLayoutConstraint.activate([
constraints += [
scrollView.topAnchor.constraint(equalTo: topAnchor),
scrollView.leftAnchor.constraint(equalTo: leftAnchor),
scrollView.rightAnchor.constraint(equalTo: rightAnchor),
scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
])
]

outterStackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(outterStackView)
NSLayoutConstraint.activate([
constraints += [
outterStackView.topAnchor.constraint(equalTo: scrollView.topAnchor),
outterStackView.leftAnchor.constraint(equalTo: scrollView.leftAnchor),
outterStackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
outterStackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
])
]

NSLayoutConstraint.activate(constraints)
}

private func configureViews() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ extension ReportViewController {
view.bottomLabel.apply(design.valueTextStyle)
view.verticalSpacing = design.labelSpacing
view.horizontalSpacing = design.iconSpacing
view.imageView.image = design.icon.image
}

private func apply(_ design: ForecastCardDesign, to view: ForecastCardView) {
Expand All @@ -75,12 +76,14 @@ extension ReportViewController {
}
}

private func apply(_ design: SharedDayPartDesign, to view: DayPartView) {
private func apply(_ design: DayPartDesign, to view: DayPartView) {
view.valueLabel.apply(design.valueTextStyle)
view.unitLabel.apply(design.unitTextStyle)
view.timeLabel.apply(design.timeTextStyle)
view.valueUnitSpacing = design.valueUnitSpacing
view.layoutMargins = UIEdgeInsets(design.layoutMargins)
view.iconWidth = design.iconWidth
view.iconHeight = design.iconHeight
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ extension ReportViewController {
view.timeLabel.textColor = .white
view.valueUnitSpacing = 5
view.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
view.iconWidth = 78
view.iconHeight = 78
}

private func applyCardStyle(to view: CardViewDescribable) {
Expand Down

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions examples/poodle-surf/src/designs/NavigationTitleDesign.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {Image} from '@diez/designsystem';
import {Component, property} from '@diez/engine';
import {ImageNames} from './assets';
import {Images} from './assets';
import {palette, textStyles} from './constants';

/**
* The navigation title design.
*/
export class NavigationTitleDesign extends Component {
@property barTintColor = palette.white;
@property icon = Image.scaled(ImageNames.Icon, 3);
@property icon = Images.Icon;
@property title = 'PITTED';
@property textStyle = textStyles.headerTitle;
}
Loading

0 comments on commit b61b1b1

Please sign in to comment.