Skip to content

Commit

Permalink
add empty states to customization
Browse files Browse the repository at this point in the history
  • Loading branch information
phillipthelen committed May 6, 2024
1 parent 979ab64 commit da51dcb
Show file tree
Hide file tree
Showing 21 changed files with 231 additions and 42 deletions.
2 changes: 2 additions & 0 deletions HabitRPG/Generated/Assets-Images.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ internal enum Asset {
internal static let crown = ImageAsset(name: "crown")
internal static let downIcon = ImageAsset(name: "down_icon")
internal enum Empty {
internal static let backgrounds = ImageAsset(name: "empty/Backgrounds")
internal static let customizations = ImageAsset(name: "empty/Customizations")
internal static let eggs = ImageAsset(name: "empty/Eggs")
internal static let food = ImageAsset(name: "empty/Food")
internal static let hatchingPotions = ImageAsset(name: "empty/HatchingPotions")
Expand Down
10 changes: 10 additions & 0 deletions HabitRPG/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ public enum L10n {
public static var createdTaskTitle: String { return L10n.tr("Mainstrings", "createdTaskTitle") }
/// Currency
public static var currency: String { return L10n.tr("Mainstrings", "currency") }
/// Customization Shop
public static var customizationShop: String { return L10n.tr("Mainstrings", "customization_shop") }
/// Daily
public static var daily: String { return L10n.tr("Mainstrings", "daily") }
/// Want to try something new? Join a Challenge to expand your task list and win some Gems!
Expand Down Expand Up @@ -1590,6 +1592,14 @@ public enum L10n {
}

public enum Empty {
/// You don’t own any of these items
public static var noItems: String { return L10n.tr("Mainstrings", "empty.no_items") }
/// Head over to the Customization Shop to browse the many ways you can customize your avatar!
public static var noItemsDescription: String { return L10n.tr("Mainstrings", "empty.no_items_description") }
/// Looking for more?
public static var wantMoreItems: String { return L10n.tr("Mainstrings", "empty.want_more_items") }
/// Check out the Customization Shop for even more ways to customize your avatar!
public static var wantMoreItemsDescription: String { return L10n.tr("Mainstrings", "empty.want_more_items_description") }

public enum Dailies {
/// Dailies are tasks that repeat on a regular basis. Choose the schedule that works for you!
Expand Down
23 changes: 23 additions & 0 deletions HabitRPG/Images.xcassets/empty/Backgrounds.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "Group 476.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group [email protected]",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group [email protected]",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "Group 480.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group [email protected]",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group [email protected]",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
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.
49 changes: 29 additions & 20 deletions HabitRPG/Storyboards/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="qCK-eG-irz">
<size key="itemSize" width="80" height="108"/>
<size key="headerReferenceSize" width="50" height="30"/>
<size key="footerReferenceSize" width="50" height="80"/>
<size key="footerReferenceSize" width="50" height="50"/>
<inset key="sectionInset" minX="8" minY="0.0" maxX="8" maxY="0.0"/>
</collectionViewFlowLayout>
<cells>
Expand Down Expand Up @@ -902,32 +902,36 @@
<outlet property="label" destination="pWt-Qo-uxJ" id="SLw-2L-Pb8"/>
</connections>
</collectionReusableView>
<collectionReusableView key="sectionFooterView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="SectionFooter" id="ZY5-HN-eTS" customClass="CustomizationFooterView" customModule="Habitica" customModuleProvider="target">
<rect key="frame" x="0.0" y="138" width="428" height="80"/>
<collectionReusableView key="sectionFooterView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="SectionFooter" id="6SS-98-tI6" customClass="CustomizationFooterView" customModule="Habitica" customModuleProvider="target">
<rect key="frame" x="0.0" y="138" width="428" height="50"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rUS-0y-rHP">
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qTK-jZ-X4O">
<rect key="frame" x="0.0" y="0.0" width="428" height="50"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LW7-NW-AwK">
<rect key="frame" x="84" y="18" width="260" height="40"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" distribution="equalCentering" alignment="center" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="IoC-em-zAB" customClass="StackView" customModule="Habitica" customModuleProvider="target">
<stackView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" distribution="equalCentering" alignment="center" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="sgw-pG-DJZ" customClass="StackView" customModule="Habitica" customModuleProvider="target">
<rect key="frame" x="38.333333333333329" y="0.0" width="183.33333333333337" height="40"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="1000" verticalHuggingPriority="251" horizontalCompressionResistancePriority="1000" text="Buy Set" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="24d-gz-RGO">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="1000" verticalHuggingPriority="251" horizontalCompressionResistancePriority="1000" text="Buy Set" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ncl-AA-1TI">
<rect key="frame" x="0.0" y="9.9999999999999982" width="59" height="20.333333333333329"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" horizontalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="xsZ-pT-z3A" customClass="CurrencyCountView" customModule="Habitica" customModuleProvider="target">
<view contentMode="scaleToFill" horizontalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="y05-DL-Ym8" customClass="CurrencyCountView" customModule="Habitica" customModuleProvider="target">
<rect key="frame" x="71.000000000000028" y="0.0" width="112.33333333333334" height="40"/>
<constraints>
<constraint firstAttribute="width" priority="500" constant="40" id="gcf-Eg-7he"/>
<constraint firstAttribute="width" priority="500" constant="40" id="HOO-Xj-2Cr"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstAttribute="width" priority="500" constant="50" id="QN0-Xe-NFC"/>
<constraint firstAttribute="height" constant="40" id="zy9-Hp-NYj"/>
<constraint firstAttribute="width" priority="500" constant="50" id="6nk-rt-PYH"/>
<constraint firstAttribute="height" constant="40" id="MeH-Ji-uD1"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
Expand All @@ -938,10 +942,10 @@
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="width" constant="260" id="0ZG-cj-tCs"/>
<constraint firstAttribute="height" constant="40" id="COV-Je-ETU"/>
<constraint firstItem="IoC-em-zAB" firstAttribute="centerX" secondItem="rUS-0y-rHP" secondAttribute="centerX" id="ZFG-yL-g11"/>
<constraint firstItem="IoC-em-zAB" firstAttribute="top" secondItem="rUS-0y-rHP" secondAttribute="top" id="bux-8g-D88"/>
<constraint firstAttribute="width" constant="260" id="EsC-HK-OGn"/>
<constraint firstItem="sgw-pG-DJZ" firstAttribute="centerX" secondItem="LW7-NW-AwK" secondAttribute="centerX" id="UJV-gT-GyH"/>
<constraint firstAttribute="height" constant="40" id="h9r-ts-Zh1"/>
<constraint firstItem="sgw-pG-DJZ" firstAttribute="top" secondItem="LW7-NW-AwK" secondAttribute="top" id="iAc-wd-q9b"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
Expand All @@ -951,13 +955,18 @@
</view>
</subviews>
<constraints>
<constraint firstItem="rUS-0y-rHP" firstAttribute="centerX" secondItem="ZY5-HN-eTS" secondAttribute="centerX" id="9be-uN-OFC"/>
<constraint firstItem="rUS-0y-rHP" firstAttribute="top" secondItem="ZY5-HN-eTS" secondAttribute="topMargin" constant="10" id="b94-RO-ggf"/>
<constraint firstItem="qTK-jZ-X4O" firstAttribute="top" secondItem="6SS-98-tI6" secondAttribute="top" id="R4T-r0-qfs"/>
<constraint firstItem="LW7-NW-AwK" firstAttribute="top" secondItem="6SS-98-tI6" secondAttribute="topMargin" constant="10" id="T4Y-eN-vUA"/>
<constraint firstItem="LW7-NW-AwK" firstAttribute="centerX" secondItem="6SS-98-tI6" secondAttribute="centerX" id="cBa-wA-5Kh"/>
<constraint firstAttribute="trailing" secondItem="qTK-jZ-X4O" secondAttribute="trailing" id="in8-UD-Wwy"/>
<constraint firstAttribute="bottom" secondItem="qTK-jZ-X4O" secondAttribute="bottom" id="jQL-uO-RC6"/>
<constraint firstItem="qTK-jZ-X4O" firstAttribute="leading" secondItem="6SS-98-tI6" secondAttribute="leading" id="z6v-Dw-kuH"/>
</constraints>
<connections>
<outlet property="buyAllLabel" destination="24d-gz-RGO" id="0V4-9s-fVU"/>
<outlet property="currencyView" destination="xsZ-pT-z3A" id="Mqf-X2-UMb"/>
<outlet property="purchaseButton" destination="rUS-0y-rHP" id="UfD-lE-Ypc"/>
<outlet property="buyAllLabel" destination="Ncl-AA-1TI" id="rdd-UT-Hwb"/>
<outlet property="currencyView" destination="y05-DL-Ym8" id="HRp-36-KkM"/>
<outlet property="hostingView" destination="qTK-jZ-X4O" id="bKk-SG-UJ1"/>
<outlet property="purchaseButton" destination="LW7-NW-AwK" id="vYT-YA-coD"/>
</connections>
</collectionReusableView>
<connections>
Expand All @@ -969,7 +978,7 @@
</collectionViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Q5s-Wo-MJQ" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="6363" y="124"/>
<point key="canvasLocation" x="6361.6822429906542" y="123.75809935205184"/>
</scene>
<!--Settings-->
<scene sceneID="5Gi-ds-f28">
Expand Down
6 changes: 6 additions & 0 deletions HabitRPG/Strings/Base.lproj/Mainstrings.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,10 @@
"empty.notifications.title" = "You're all caught up!";
"empty.notifications.description" = "The notification fairies give you a raucous round of applause! Well done!";
"empty.inbox.description" = "Start chatting below! Remember to be friendly and follow the Community Guidelines.";
"empty.no_items" = "You don’t own any of these items";
"empty.want_more_items" = "Looking for more?";
"empty.no_items_description" = "Head over to the Customization Shop to browse the many ways you can customize your avatar!";
"empty.want_more_items_description" = "Check out the Customization Shop for even more ways to customize your avatar!";
"achievements.onboarding" = "Onboarding Achievements";
"achievements.basic" = "Basic Achievements";
"achievements.seasonal" = "Seasonal Achievements";
Expand Down Expand Up @@ -1350,3 +1354,5 @@
"summer" = "Summer";
"fall" = "Fall";
"winter" = "Winter";

"customization_shop" = "Customization Shop";
46 changes: 29 additions & 17 deletions HabitRPG/TableViewDataSources/AvatarDetailViewDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import Foundation
import Habitica_Models
import SwiftUIX

class AvatarDetailViewDataSource: BaseReactiveCollectionViewDataSource<CustomizationProtocol> {

Expand Down Expand Up @@ -211,32 +212,43 @@ class AvatarDetailViewDataSource: BaseReactiveCollectionViewDataSource<Customiza
return CGSize.zero
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 80)
}

override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

let view = super.collectionView(collectionView, viewForSupplementaryElementOfKind: kind, at: indexPath)
let section = sections[indexPath.section]

if let footerView = view as? CustomizationFooterView {
if !newCustomizationLayout {
if newCustomizationLayout && indexPath.section == collectionView.numberOfSections - 1 {
footerView.purchaseButton.isHidden = true
}
if let set = customizationSets[section.key ?? ""] {
footerView.configure(customizationSet: set)
let individualPrice = set.setItems?.filter { (customization) -> Bool in
return !self.owns(customization: customization)
}.map { $0.price }.reduce(0, +) ?? 0
if individualPrice >= set.setPrice && set.setPrice != 0 && set.key?.contains("timeTravel") != true && set.key?.contains("incentive") != true {
footerView.purchaseButton.isHidden = false
footerView.hostingView.isHidden = false
let hostView = UIHostingView(rootView: CTAFooterView(type: customizationType, hasItems: !ownedCustomizations.isEmpty))
footerView.hostingView.addSubview(hostView)
hostView.frame = CGRect(x: 0, y: 0, width: collectionView.frame.width, height: 200)
} else {
footerView.hostingView.isHidden = true
if let set = customizationSets[section.key ?? ""] {
footerView.configure(customizationSet: set)
let individualPrice = set.setItems?.filter { (customization) -> Bool in
return !self.owns(customization: customization)
}.map { $0.price }.reduce(0, +) ?? 0
if individualPrice >= set.setPrice && set.setPrice != 0 && set.key?.contains("timeTravel") != true && set.key?.contains("incentive") != true {
footerView.purchaseButton.isHidden = false
} else {
footerView.purchaseButton.isHidden = true
}

footerView.purchaseButtonTapped = {
if let action = self.purchaseSet {
action(set)
}
}
} else {
footerView.purchaseButton.isHidden = true
}

footerView.purchaseButtonTapped = {
if let action = self.purchaseSet {
action(set)
}
}
} else {
footerView.purchaseButton.isHidden = true
}
} else if let headerView = view as? CustomizationHeaderView {
if let set = customizationSets[section.key ?? ""] {
Expand Down
2 changes: 2 additions & 0 deletions HabitRPG/TableviewCells/CustomizationFooterView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@

import Foundation
import Habitica_Models
import SwiftUIX

class CustomizationFooterView: UICollectionReusableView {

@IBOutlet weak var hostingView: UIView!
@IBOutlet weak var currencyView: CurrencyCountView!
@IBOutlet weak var purchaseButton: UIView!
@IBOutlet weak var buyAllLabel: UILabel!
Expand Down
13 changes: 8 additions & 5 deletions HabitRPG/UI/Inventory/AvatarDetailViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ class AvatarDetailViewController: BaseCollectionViewController, UICollectionView
}
}
HabiticaAnalytics.shared.logNavigationEvent("navigated \(customizationType ?? "") screen")

let flowlayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
if newCustomizationLayout {
flowlayout?.footerReferenceSize = CGSize(width: collectionView.frame.width, height: 20)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
if section == collectionView.numberOfSections - 1 && newCustomizationLayout {
return CGSize(width: collectionView.frame.width, height: 200)
} else if newCustomizationLayout {
return CGSize(width: collectionView.frame.width, height: 20)
}

return CGSize(width: collectionView.frame.width, height: 60)
}

override func applyTheme(theme: Theme) {
Expand Down
Loading

0 comments on commit da51dcb

Please sign in to comment.