Skip to content
Merged
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
1 change: 1 addition & 0 deletions animeal/res/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,4 @@
"action.privacyPolicy" = "Privacy Policy";
"action.acknowledgeTCandPP" = "By continuing, you agree to Animeal's Terms & Conditions and Privacy Policy";
"text.header.assignedModerators" = "Assigned Moderators";
"action.showAll" = "Show All (%@)";
1 change: 1 addition & 0 deletions animeal/res/ka.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,4 @@
"action.privacyPolicy" = "";
"action.acknowledgeTCandPP" = "";
"text.header.assignedModerators" = "დანიშნული მოდერატორები";
"action.showAll" = "ყველას ნახვა (%@)";
4 changes: 3 additions & 1 deletion animeal/res/sheet.csv
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,6 @@ Together, we can ensure they thrive in a safe and healthy environment.","","",""
"action.register","","Register/Log-in","","","","","","","","","","","","","","","","","","","","","","","",""
"action.termsAndConditions","","Terms & Conditions","","","","","","","","","","","","","","","","","","","","","","","",""
"action.privacyPolicy","","Privacy Policy","","","","","","","","","","","","","","","","","","","","","","","",""
"action.acknowledgeTCandPP","","By continuing, you agree to Animeal's Terms & Conditions and Privacy Policy","","","","","","","","","","","","","","","","","","","","","","","",""
"action.acknowledgeTCandPP","","By continuing, you agree to Animeal's Terms & Conditions and Privacy Policy","","","","","","","","","","","","","","","","","","","","","","","",""
"text.header.assignedModerators","","Assigned Moderators","დანიშნული მოდერატორები","","","","","","","","","","","","","","","","","","","","","","",""
"action.showAll","","Show All (%@)","ყველას ნახვა (%@)","","","","","","","","","","","","","","","","","","","","","","",""
4 changes: 4 additions & 0 deletions animeal/src/Common/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ internal enum L10n {
internal static let privacyPolicy = L10n.tr("Localizable", "action.privacyPolicy", fallback: "Privacy Policy")
/// Register/Log-in
internal static let register = L10n.tr("Localizable", "action.register", fallback: "Register/Log-in")
/// Show All (%@)
internal static func showAll(_ p1: Any) -> String {
return L10n.tr("Localizable", "action.showAll", String(describing: p1), fallback: "Show All (%@)")
}
/// Show on map
internal static let showOnMap = L10n.tr("Localizable", "action.showOnMap", fallback: "Show on map")
/// Terms & Conditions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,5 @@ enum FeedingPointEvent {
case tapShowOnMap
case tapCancelLocationRequest
case tapShowMoreModerators
case tapToggleModeratorsVisibility
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ final class FeedingPointDetailsViewModel: FeedingPointDetailsViewModelLifeCycle,
)
}
private var allModerators: [FeedingPointDetailsModel.Moderator] = []
private var isModeratorsExpanded = false
private var isModeratorsExpanded = true
Comment thread
steryokhin marked this conversation as resolved.
private var didRequestAllModerators = false
let shimmerScheduler = ShimmerViewScheduler()

// MARK: - Initialization
Expand Down Expand Up @@ -74,8 +75,8 @@ final class FeedingPointDetailsViewModel: FeedingPointDetailsViewModelLifeCycle,
}
model.onModeratorsChange = { [weak self] moderators in
DispatchQueue.main.async {
self?.moderatorsInitialized = true
self?.updateModeratorsContent(moderators)
self?.setModerators(moderators)
self?.updateModeratorsContent()
}
}
model.onFeedingPointChange = { [weak self] content, mutateFavorites in
Expand Down Expand Up @@ -106,34 +107,34 @@ final class FeedingPointDetailsViewModel: FeedingPointDetailsViewModelLifeCycle,
onContentHaveBeenPrepared?(contentMapper.mapFeedingPoint(modelContent))
}

private func updateModeratorsContent(_ moderators: [FeedingPointDetailsModel.Moderator]) {
guard !moderators.isEmpty else {
allModerators = []
isModeratorsExpanded = false
let mapped = contentMapper.mapModerators([], canShowMore: false, totalCount: 0)
private func updateModeratorsContent() {
guard !self.allModerators.isEmpty else {
let mapped = contentMapper.mapModerators([], canShowMore: false, isExpanded: false, totalCount: 0)
onModeratorsHaveBeenPrepared?(mapped)
return
}
allModerators = moderators
let moderatorsToDisplay: [FeedingPointDetailsModel.Moderator]
let canShowMore: Bool

if isModeratorsExpanded {
let limit = ModeratorDisplayConstants.expandedLimit
moderatorsToDisplay = Array(moderators.prefix(limit))
canShowMore = false
let moderatorsToDisplay: [FeedingPointDetailsModel.Moderator]
let limit = ModeratorDisplayConstants.expandedLimit
let totalCount = allModerators.count
let hasMoreThanLimit = totalCount > limit
if !isModeratorsExpanded {
moderatorsToDisplay = []
} else if didRequestAllModerators && hasMoreThanLimit {
moderatorsToDisplay = allModerators
} else {
if allModerators.count > ModeratorDisplayConstants.collapsedThreshold {
moderatorsToDisplay = []
canShowMore = true
} else {
moderatorsToDisplay = moderators
canShowMore = false
}
moderatorsToDisplay = Array(allModerators.prefix(limit))
}
let mapped = contentMapper.mapModerators(moderatorsToDisplay, canShowMore: canShowMore, totalCount: allModerators.count)

let canShowMore = hasMoreThanLimit && isModeratorsExpanded && !didRequestAllModerators
let mapped = contentMapper.mapModerators(moderatorsToDisplay, canShowMore: canShowMore, isExpanded: isModeratorsExpanded, totalCount: totalCount)
onModeratorsHaveBeenPrepared?(mapped)
}

private func setModerators(_ moderators: [FeedingPointDetailsModel.Moderator]) {
self.moderatorsInitialized = true
self.allModerators = moderators
}

private func updateFavorites() {
onFavoriteMutation?()
Expand Down Expand Up @@ -188,15 +189,19 @@ final class FeedingPointDetailsViewModel: FeedingPointDetailsViewModelLifeCycle,
break

case .tapShowMoreModerators:
isModeratorsExpanded = true
updateModeratorsContent(allModerators)
didRequestAllModerators = true
updateModeratorsContent()

case .tapToggleModeratorsVisibility:
isModeratorsExpanded.toggle()
didRequestAllModerators = false
updateModeratorsContent()
}
}
}

private extension FeedingPointDetailsViewModel {
enum ModeratorDisplayConstants {
static let collapsedThreshold = 5 /// show "Show more" if total > 5
static let expandedLimit = 10 /// max shown after expand
static let expandedLimit = 5
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ final class FeedingPointDetailsModel: FeedingPointDetailsModelProtocol, FeedingP
let mapped = uniqueIds.map { id in
FeedingPointDetailsModel.Moderator(name: namesMap[id] ?? "Unknown")
}
return Array(mapped.prefix(10))
return mapped
}

func mutateFavorite() async throws -> Bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ final class FeedingPointDetailsViewController: UIViewController, FeedingPointDet
let containerView = UIStackView()
containerView.axis = .horizontal
containerView.alignment = .center
containerView.distribution = .equalSpacing
containerView.distribution = .fill
moderatorsContainer.addArrangedSubview(containerView)

let title = TextTitleView()
Expand All @@ -159,20 +159,36 @@ final class FeedingPointDetailsViewController: UIViewController, FeedingPointDet
)
moderatorsContainer.addArrangedSubview(view)
}

if content.canShowMore {
let button = ButtonViewFactory().makeArrowButton()
button.configure(
ButtonView.Model(
identifier: UUID().uuidString,
viewType: ButtonView.self,
icon: UIImage(systemName: "chevron.down"))
)
button.onTap = { [weak self] _ in
let showMoreButton = ButtonViewFactory().makeTextButton()
let model = ButtonView.Model(identifier: UUID().uuidString, viewType: ButtonView.self, title: L10n.Action.showAll(content.totalCount))
showMoreButton.configure(model)
showMoreButton.onTap = { [weak self] _ in
self?.viewModel.handleActionEvent(.tapShowMoreModerators)
}
containerView.addArrangedSubview(button)
let showMoreContainer = UIView()
showMoreContainer.addSubview(showMoreButton.prepareForAutoLayout())
showMoreButton.leadingAnchor ~= showMoreContainer.leadingAnchor
showMoreButton.topAnchor ~= showMoreContainer.topAnchor
showMoreButton.bottomAnchor ~= showMoreContainer.bottomAnchor
showMoreButton.trailingAnchor <= showMoreContainer.trailingAnchor

moderatorsContainer.addArrangedSubview(showMoreContainer)
}

let toggleButton = ButtonViewFactory().makeArrowButton()
let iconName = content.isExpanded ? "chevron.up" : "chevron.down"
toggleButton.configure(
ButtonView.Model(
identifier: UUID().uuidString,
viewType: ButtonView.self,
icon: UIImage(systemName: iconName))
)
toggleButton.onTap = { [weak self] _ in
self?.viewModel.handleActionEvent(.tapToggleModeratorsVisibility)
}
containerView.addArrangedSubview(toggleButton)
}

func applyFavoriteMutationFailed() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ protocol FeedingPointDetailsViewMappable {
func mapModerators(
_ input: [FeedingPointDetailsModel.Moderator],
canShowMore: Bool,
isExpanded: Bool,
totalCount: Int
) -> FeedingPointDetailsViewMapper.FeedingPointModerators
}
Expand Down Expand Up @@ -69,13 +70,15 @@ final class FeedingPointDetailsViewMapper: FeedingPointDetailsViewMappable {
func mapModerators(
_ input: [FeedingPointDetailsModel.Moderator],
canShowMore: Bool,
isExpanded: Bool,
totalCount: Int
) -> FeedingPointModerators {
let moderators = input.map { FeedingPointModerators.Moderator(name: $0.name) }
return FeedingPointModerators(
title: L10n.Text.Header.assignedModerators,
moderators: moderators,
canShowMore: canShowMore,
isExpanded: isExpanded,
totalCount: totalCount
)
}
Expand Down Expand Up @@ -115,6 +118,7 @@ extension FeedingPointDetailsViewMapper {
let title: String
let moderators: [Moderator]
let canShowMore: Bool
let isExpanded: Bool
let totalCount: Int

struct Moderator {
Expand Down
Loading