Skip to content

Commit

Permalink
iOS profile badges representation (#600)
Browse files Browse the repository at this point in the history
^ALTAPPS-882 Needs testing
  • Loading branch information
vladkash authored Aug 4, 2023
1 parent e14429e commit 58ca45b
Show file tree
Hide file tree
Showing 36 changed files with 581 additions and 86 deletions.
28 changes: 24 additions & 4 deletions iosHyperskillApp/iosHyperskillApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,6 @@
E9859B91292E414300857679 /* RepeatButtonInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9859B90292E414300857679 /* RepeatButtonInfo.swift */; };
E9886D3228ABCE5C003724F9 /* OnboardingOutputProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9886D3128ABCE5C003724F9 /* OnboardingOutputProtocol.swift */; };
E98BE36D2A374394000B430F /* StreakRecoveryModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E98BE36C2A374394000B430F /* StreakRecoveryModalView.swift */; };
E98EDCEF2A5EB6B600B8C8AA /* ProgressScreenCallToActionButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = E98EDCEE2A5EB6B600B8C8AA /* ProgressScreenCallToActionButtonStyle.swift */; };
E993E9A928426FF2005988EC /* StepQuizSortingViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = E993E9A828426FF2005988EC /* StepQuizSortingViewData.swift */; };
E9950E9328893F1700C4D962 /* ProfileDailyStudyRemindersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9950E9228893F1700C4D962 /* ProfileDailyStudyRemindersView.swift */; };
E9950E9528894F4700C4D962 /* ProfileDailyStudyRemindersHourIntervalPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9950E9428894F4700C4D962 /* ProfileDailyStudyRemindersHourIntervalPickerView.swift */; };
Expand Down Expand Up @@ -473,6 +472,7 @@
E9B55A5D29C978E40066900E /* ProblemsLimitReachedModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9B55A5C29C978E40066900E /* ProblemsLimitReachedModalViewController.swift */; };
E9B642012A6BCC16001A9653 /* NextLearningActivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9B642002A6BCC16001A9653 /* NextLearningActivityView.swift */; };
E9B642032A6BDC8E001A9653 /* NextLearningActivitySkeletonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9B642022A6BDC8E001A9653 /* NextLearningActivitySkeletonView.swift */; };
E9BDB4052A7BE1E30069EF98 /* ProfileBadgeImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9BDB4042A7BE1E30069EF98 /* ProfileBadgeImageView.swift */; };
E9C3506D2886B0FE0080D277 /* MainBundleInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9C3506C2886B0FE0080D277 /* MainBundleInfo.swift */; };
E9C3506F2886D0600080D277 /* OpenURLInsideAppButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9C3506E2886D0600080D277 /* OpenURLInsideAppButton.swift */; };
E9C5C93028AE105200CADDEC /* NotificationsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9C5C92F28AE105200CADDEC /* NotificationsService.swift */; };
Expand All @@ -483,6 +483,9 @@
E9D2D673284E0A97000757AC /* StepQuizMatchingItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D2D672284E0A97000757AC /* StepQuizMatchingItemView.swift */; };
E9D2D675284E0B30000757AC /* StepQuizMatchingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D2D674284E0B30000757AC /* StepQuizMatchingView.swift */; };
E9D458E429927C8900AAEBD9 /* lines_wrapper.js in Resources */ = {isa = PBXBuildFile; fileRef = E9D458E329927C8900AAEBD9 /* lines_wrapper.js */; };
E9D537D02A71056100F21828 /* ProfileBadgesGridItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D537CF2A71056100F21828 /* ProfileBadgesGridItemView.swift */; };
E9D537D22A71330A00F21828 /* ProfileBadgesLinearGradientProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D537D12A71330A00F21828 /* ProfileBadgesLinearGradientProgressView.swift */; };
E9D537D42A71393A00F21828 /* ProfileBadgesGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D537D32A71393A00F21828 /* ProfileBadgesGridView.swift */; };
E9D69A4028084FF7000E114E /* AuthCredentialsErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D69A3F28084FF7000E114E /* AuthCredentialsErrorView.swift */; };
E9D90905289814AA00D0EE91 /* NotificationsRegistrationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D90904289814AA00D0EE91 /* NotificationsRegistrationService.swift */; };
E9E964872A0B8D8200841DF6 /* StepQuizProblemsLimitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E964862A0B8D8200841DF6 /* StepQuizProblemsLimitView.swift */; };
Expand Down Expand Up @@ -957,7 +960,6 @@
E9859B90292E414300857679 /* RepeatButtonInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatButtonInfo.swift; sourceTree = "<group>"; };
E9886D3128ABCE5C003724F9 /* OnboardingOutputProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingOutputProtocol.swift; sourceTree = "<group>"; };
E98BE36C2A374394000B430F /* StreakRecoveryModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StreakRecoveryModalView.swift; sourceTree = "<group>"; };
E98EDCEE2A5EB6B600B8C8AA /* ProgressScreenCallToActionButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressScreenCallToActionButtonStyle.swift; sourceTree = "<group>"; };
E993E9A828426FF2005988EC /* StepQuizSortingViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepQuizSortingViewData.swift; sourceTree = "<group>"; };
E9950E9228893F1700C4D962 /* ProfileDailyStudyRemindersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileDailyStudyRemindersView.swift; sourceTree = "<group>"; };
E9950E9428894F4700C4D962 /* ProfileDailyStudyRemindersHourIntervalPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileDailyStudyRemindersHourIntervalPickerView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -997,6 +999,7 @@
E9B55A5C29C978E40066900E /* ProblemsLimitReachedModalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProblemsLimitReachedModalViewController.swift; sourceTree = "<group>"; };
E9B642002A6BCC16001A9653 /* NextLearningActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextLearningActivityView.swift; sourceTree = "<group>"; };
E9B642022A6BDC8E001A9653 /* NextLearningActivitySkeletonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextLearningActivitySkeletonView.swift; sourceTree = "<group>"; };
E9BDB4042A7BE1E30069EF98 /* ProfileBadgeImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileBadgeImageView.swift; sourceTree = "<group>"; };
E9C3506C2886B0FE0080D277 /* MainBundleInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainBundleInfo.swift; sourceTree = "<group>"; };
E9C3506E2886D0600080D277 /* OpenURLInsideAppButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenURLInsideAppButton.swift; sourceTree = "<group>"; };
E9C5C92F28AE105200CADDEC /* NotificationsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsService.swift; sourceTree = "<group>"; };
Expand All @@ -1007,6 +1010,9 @@
E9D2D672284E0A97000757AC /* StepQuizMatchingItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepQuizMatchingItemView.swift; sourceTree = "<group>"; };
E9D2D674284E0B30000757AC /* StepQuizMatchingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepQuizMatchingView.swift; sourceTree = "<group>"; };
E9D458E329927C8900AAEBD9 /* lines_wrapper.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = lines_wrapper.js; sourceTree = "<group>"; };
E9D537CF2A71056100F21828 /* ProfileBadgesGridItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileBadgesGridItemView.swift; sourceTree = "<group>"; };
E9D537D12A71330A00F21828 /* ProfileBadgesLinearGradientProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileBadgesLinearGradientProgressView.swift; sourceTree = "<group>"; };
E9D537D32A71393A00F21828 /* ProfileBadgesGridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileBadgesGridView.swift; sourceTree = "<group>"; };
E9D69A3F28084FF7000E114E /* AuthCredentialsErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthCredentialsErrorView.swift; sourceTree = "<group>"; };
E9D90904289814AA00D0EE91 /* NotificationsRegistrationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsRegistrationService.swift; sourceTree = "<group>"; };
E9E964862A0B8D8200841DF6 /* StepQuizProblemsLimitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepQuizProblemsLimitView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1560,7 +1566,6 @@
2C336A052A4D388100A01F26 /* Views */ = {
isa = PBXGroup;
children = (
E98EDCEE2A5EB6B600B8C8AA /* ProgressScreenCallToActionButtonStyle.swift */,
2C8EBE502A4D3DF700A77205 /* ProgressScreenCardView.swift */,
2C6672052A527C0D0040EA2F /* ProgressScreenSectionTitleView.swift */,
CCC18157582494D2909B214C /* ProgressScreenView.swift */,
Expand Down Expand Up @@ -1634,6 +1639,7 @@
2CDA98402944512D00ADE539 /* ProfileSkeletonView.swift */,
2C9EB95C2861BABC007DDE44 /* ProfileView.swift */,
2C4FBD8F2876C95200ACA5C8 /* About */,
E9D537CE2A71053700F21828 /* Badges */,
2C96E83C28F6B6CB00F8495B /* DailyStudyReminders */,
2CDA984729445BF600ADE539 /* Statistics */,
);
Expand Down Expand Up @@ -3127,6 +3133,17 @@
path = Views;
sourceTree = "<group>";
};
E9D537CE2A71053700F21828 /* Badges */ = {
isa = PBXGroup;
children = (
E9BDB4042A7BE1E30069EF98 /* ProfileBadgeImageView.swift */,
E9D537CF2A71056100F21828 /* ProfileBadgesGridItemView.swift */,
E9D537D32A71393A00F21828 /* ProfileBadgesGridView.swift */,
E9D537D12A71330A00F21828 /* ProfileBadgesLinearGradientProgressView.swift */,
);
path = Badges;
sourceTree = "<group>";
};
E9D909032898149400D0EE91 /* Registration */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -3453,7 +3470,6 @@
2C3E656D2A12722800BC8DC0 /* TrackSelectionListHeaderView.swift in Sources */,
2C5B2A2828659AD80097B270 /* CodeElementSize.swift in Sources */,
2CAFD39127FC5D5D00F88B0B /* Color+DesignSystem.swift in Sources */,
E98EDCEF2A5EB6B600B8C8AA /* ProgressScreenCallToActionButtonStyle.swift in Sources */,
2C5CA2372A20185300DBF2F9 /* ProjectSelectionDetailsFeatureViewStateKsExtensions.swift in Sources */,
E9886D3228ABCE5C003724F9 /* OnboardingOutputProtocol.swift in Sources */,
2C5CBBE12948EBEA00113007 /* StepQuizSQLViewDataMapper.swift in Sources */,
Expand Down Expand Up @@ -3605,6 +3621,7 @@
E9A022AE291D0E3F004317DB /* TopicsRepetitionsCardView.swift in Sources */,
2C5CBBE32948F4B600113007 /* StepQuizSQLViewModel.swift in Sources */,
E9F923F628A2633D00C065A7 /* OnboardingView.swift in Sources */,
E9BDB4052A7BE1E30069EF98 /* ProfileBadgeImageView.swift in Sources */,
2C106D9928C1CE6E004FA584 /* SendEmailFeedbackController.swift in Sources */,
2C688C052A4E97750061AFFD /* ProgressScreenProjectProgressView.swift in Sources */,
E9523BF429DAA5690013A661 /* StudyPlanSkeletonView.swift in Sources */,
Expand Down Expand Up @@ -3715,6 +3732,7 @@
2CBC97D02A555BE60078E445 /* HypercoinsAwardView.swift in Sources */,
2CA8E094281039EB00154088 /* RoundedRectangleButtonStyle.swift in Sources */,
2C2FF9C928506FDE0069C092 /* LatexView.swift in Sources */,
E9D537D02A71056100F21828 /* ProfileBadgesGridItemView.swift in Sources */,
E9CC6C0729893F2200D8D070 /* StepQuizInputProtocol.swift in Sources */,
2C96743728882A0C0091B6C9 /* StepQuizCodeDetailsView.swift in Sources */,
2C20FBC7284F6928006D879E /* ProgrammaticallyInitializableViewProtocol.swift in Sources */,
Expand Down Expand Up @@ -3777,6 +3795,7 @@
2C0EB9502A151B56006DC84B /* TrackSelectionListViewModel.swift in Sources */,
E9ACD3412937342F0005E05B /* ProblemOfDaySolvedModalViewController.swift in Sources */,
2C0EB9562A15296D006DC84B /* TrackSelectionListFeatureViewStateContent+Placeholder.swift in Sources */,
E9D537D22A71330A00F21828 /* ProfileBadgesLinearGradientProgressView.swift in Sources */,
2C4F63A12A102D3300D4EE39 /* SharedProjectLevelWrapper.swift in Sources */,
2CD48D8B2858684100CFCC4A /* StepQuizViewData.swift in Sources */,
2C05AC572A0EC9E50039C7EF /* ProjectSelectionListHeaderSkeletonView.swift in Sources */,
Expand Down Expand Up @@ -3904,6 +3923,7 @@
2C967432288824370091B6C9 /* StepQuizCodeViewModel.swift in Sources */,
2CF72AA5284775BF00E1C192 /* StepQuizTableView.swift in Sources */,
D64BC006B49702DFDA107FA5 /* TrackSelectionDetailsAssembly.swift in Sources */,
E9D537D42A71393A00F21828 /* ProfileBadgesGridView.swift in Sources */,
C727878256DA0342EF174A4E /* TrackSelectionDetailsView.swift in Sources */,
D9B929495D696A140BA3D150 /* TrackSelectionDetailsViewModel.swift in Sources */,
ECD10958C8BA7D758D3D1F66 /* ProjectSelectionDetailsAssembly.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "profile-badges-benefactor.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "profile-badges-bounty-hunter.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "profile-badges-brilliant-mind.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "profile-badges-commited-learning.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "profile-badges-helping-hand.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "profile-badges-project-mastery.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "profile-badges-sweetheart.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "profile-badges-topic-mastery.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,17 @@ enum Images {
static let fire = "streak-recover-modal-fire"
}
}

enum Badges {
static let benefactor = "profile-badges-benefactor"
static let bountyHunter = "profile-badges-bounty-hunter"
static let brilliantMind = "profile-badges-brilliant-mind"
static let commitedLearning = "profile-badges-commited-learning"
static let helpingHand = "profile-badges-helping-hand"
static let projectMastery = "profile-badges-project-mastery"
static let sweetheart = "profile-badges-sweetheart"
static let topicMastery = "profile-badges-topic-mastery"
}
}

// MARK: - Onboarding -
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,12 @@ enum Strings {
static let title = sharedStrings.profile_daily_study_reminders_text.localized()
static let schedule = sharedStrings.profile_daily_study_reminders_schedule_text.localized()
}

enum Badges {
static let title = sharedStrings.profile_badges_title.localized()
static let showAll = sharedStrings.profile_badges_show_all.localized()
static let showLess = sharedStrings.profile_badges_show_less.localized()
}
}

// MARK: - Settings -
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ final class ProfileAssembly: Assembly {

let viewModel = ProfileViewModel(
presentationDescription: presentationDescription,
viewDataMapper: ProfileViewDataMapper(),
profileViewDataMapper: ProfileViewDataMapper(),
badgesViewStateMapper: profileComponent.badgesViewStateMapper,
notificationService: NotificationsService(
notificationInteractor: notificationComponent.notificationInteractor
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ final class ProfileViewModel: FeatureViewModel<
> {
private let presentationDescription: ProfilePresentationDescription

private let viewDataMapper: ProfileViewDataMapper
private let profileViewDataMapper: ProfileViewDataMapper

private let badgesViewStateMapper: BadgesViewStateMapper

private let notificationService: NotificationsService
private let notificationsRegistrationService: NotificationsRegistrationService
Expand All @@ -27,14 +29,16 @@ final class ProfileViewModel: FeatureViewModel<

init(
presentationDescription: ProfilePresentationDescription,
viewDataMapper: ProfileViewDataMapper,
profileViewDataMapper: ProfileViewDataMapper,
badgesViewStateMapper: BadgesViewStateMapper,
notificationService: NotificationsService,
notificationsRegistrationService: NotificationsRegistrationService,
notificationInteractor: NotificationInteractor,
feature: Presentation_reduxFeature
) {
self.presentationDescription = presentationDescription
self.viewDataMapper = viewDataMapper
self.profileViewDataMapper = profileViewDataMapper
self.badgesViewStateMapper = badgesViewStateMapper
self.notificationService = notificationService
self.notificationsRegistrationService = notificationsRegistrationService
self.notificationInteractor = notificationInteractor
Expand Down Expand Up @@ -86,18 +90,24 @@ final class ProfileViewModel: FeatureViewModel<
}
}

func makeViewData(
func makeProfileViewData(
profile: Profile,
dailyStudyRemindersState: ProfileFeatureDailyStudyRemindersState
) -> ProfileViewData {
viewDataMapper.mapProfileToViewData(
profileViewDataMapper.mapProfileToViewData(
profile,
isDailyStudyRemindersEnabled: dailyStudyRemindersState.isEnabled,
dailyStudyRemindersStartHour: Int(dailyStudyRemindersState.startHour),
notificationPermissionStatus: currentNotificationPermissionStatus
)
}

func makeBadgesViewState(
badgesState: ProfileFeatureBadgesState
) -> BadgesViewState {
badgesViewStateMapper.map(state: badgesState)
}

// MARK: Presentation

func doSocialAccountPresentation(_ profileSocialAccount: ProfileSocialAccount) {
Expand Down Expand Up @@ -131,6 +141,16 @@ final class ProfileViewModel: FeatureViewModel<
onNewMessage(ProfileFeatureMessageStreakFreezeModalButtonClicked())
}

// MARK: Badges

func doBadgeCardTapped(badgeKind: BadgeKind) {
onNewMessage(ProfileFeatureMessageBadgeClicked(badgeKind: badgeKind))
}

func doBadgesVisibilityButtonTapped(visibilityButton: ProfileFeatureMessageBadgesVisibilityButton) {
onNewMessage(ProfileFeatureMessageBadgesVisibilityButtonClicked(visibilityButton: visibilityButton))
}

// MARK: Daily study reminders

func setDailyStudyRemindersEnabled(_ isEnabled: Bool) {
Expand Down
Loading

0 comments on commit 58ca45b

Please sign in to comment.