diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 69c241842248..3c20091b3631 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -2875,6 +2875,11 @@ C9B477B229CC4949008CBF49 /* HomeWidgetDataFileReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B477B129CC4949008CBF49 /* HomeWidgetDataFileReader.swift */; }; C9B477B329CC4949008CBF49 /* HomeWidgetDataFileReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B477B129CC4949008CBF49 /* HomeWidgetDataFileReader.swift */; }; C9B477B429CC4949008CBF49 /* HomeWidgetDataFileReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B477B129CC4949008CBF49 /* HomeWidgetDataFileReader.swift */; }; + C9B477B629CD2EF7008CBF49 /* LockScreenUnconfiguredView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B477B529CD2EF7008CBF49 /* LockScreenUnconfiguredView.swift */; }; + C9B477B729CD2EF7008CBF49 /* LockScreenUnconfiguredView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B477B529CD2EF7008CBF49 /* LockScreenUnconfiguredView.swift */; }; + C9B477B929CD2FEF008CBF49 /* LockScreenUnconfiguredViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B477B829CD2FEE008CBF49 /* LockScreenUnconfiguredViewModel.swift */; }; + C9B477BA29CD2FEF008CBF49 /* LockScreenUnconfiguredViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B477B829CD2FEE008CBF49 /* LockScreenUnconfiguredViewModel.swift */; }; + C9B477BB29CD576F008CBF49 /* LockScreenUnconfiguredViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B477B829CD2FEE008CBF49 /* LockScreenUnconfiguredViewModel.swift */; }; C9C21D7729BECFC1009F68E5 /* LockScreenStatsWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C21D7629BECFC1009F68E5 /* LockScreenStatsWidget.swift */; }; C9C21D7829BECFC7009F68E5 /* LockScreenStatsWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C21D7629BECFC1009F68E5 /* LockScreenStatsWidget.swift */; }; C9C21D7B29BED18C009F68E5 /* LockScreenStatsWidgetsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C21D7A29BED18C009F68E5 /* LockScreenStatsWidgetsView.swift */; }; @@ -8136,6 +8141,8 @@ C9B477AB29CC15D9008CBF49 /* WidgetDataReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WidgetDataReader.swift; sourceTree = ""; }; C9B477AF29CC35C5008CBF49 /* WidgetDataReaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetDataReaderTests.swift; sourceTree = ""; }; C9B477B129CC4949008CBF49 /* HomeWidgetDataFileReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeWidgetDataFileReader.swift; sourceTree = ""; }; + C9B477B529CD2EF7008CBF49 /* LockScreenUnconfiguredView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LockScreenUnconfiguredView.swift; sourceTree = ""; }; + C9B477B829CD2FEE008CBF49 /* LockScreenUnconfiguredViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LockScreenUnconfiguredViewModel.swift; sourceTree = ""; }; C9C21D7629BECFC1009F68E5 /* LockScreenStatsWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenStatsWidget.swift; sourceTree = ""; }; C9C21D7A29BED18C009F68E5 /* LockScreenStatsWidgetsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenStatsWidgetsView.swift; sourceTree = ""; }; C9D7DDBF2613B84500104E95 /* WordPress 119.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "WordPress 119.xcdatamodel"; sourceTree = ""; }; @@ -15716,6 +15723,7 @@ children = ( C9C21D7A29BED18C009F68E5 /* LockScreenStatsWidgetsView.swift */, C9FE383029C2053300D39841 /* LockScreenSingleStatView.swift */, + C9B477B529CD2EF7008CBF49 /* LockScreenUnconfiguredView.swift */, ); path = Views; sourceTree = ""; @@ -15743,6 +15751,7 @@ C9B4778229C85948008CBF49 /* LockScreenStatsWidgetData.swift */, C9B4778329C85949008CBF49 /* LockScreenStatsWidgetEntry.swift */, C9FE382B29C204E700D39841 /* LockScreenSingleStatViewModel.swift */, + C9B477B829CD2FEE008CBF49 /* LockScreenUnconfiguredViewModel.swift */, C9FE382A29C204E700D39841 /* LockScreenWidgetViewModelMapper.swift */, ); path = Models; @@ -20537,6 +20546,7 @@ C9FE384129C2A3D200D39841 /* LockScreenTodayViewsStatWidgetConfig.swift in Sources */, 0107E16128FFE99300DE87DB /* WidgetConfiguration.swift in Sources */, 0107E0BB28F97D5000DE87DB /* StatsWidgetsService.swift in Sources */, + C9B477B729CD2EF7008CBF49 /* LockScreenUnconfiguredView.swift in Sources */, 0107E0BC28F97D5000DE87DB /* StatsWidgetsView.swift in Sources */, 0107E0BD28F97D5000DE87DB /* AppLocalizedString.swift in Sources */, 0107E0BE28F97D5000DE87DB /* MultiStatsView.swift in Sources */, @@ -20567,6 +20577,7 @@ 0107E0D028F97D5000DE87DB /* WordPressHomeWidgetThisWeek.swift in Sources */, C9FE382D29C204E700D39841 /* LockScreenWidgetViewModelMapper.swift in Sources */, C9FE384729C2A3D200D39841 /* LockScreenStatsWidgetConfig.swift in Sources */, + C9B477BA29CD2FEF008CBF49 /* LockScreenUnconfiguredViewModel.swift in Sources */, 0107E0D128F97D5000DE87DB /* SingleStatView.swift in Sources */, 0107E0D228F97D5000DE87DB /* UnconfiguredView.swift in Sources */, 0107E1852900059300DE87DB /* LocalizationConfiguration.swift in Sources */, @@ -21610,6 +21621,7 @@ D8212CB520AA68D5008E8AE8 /* ReaderSubscribingNotificationAction.swift in Sources */, FF8C54AD21F677260003ABCF /* GutenbergMediaInserterHelper.swift in Sources */, 176BA53B268266E70025E4A3 /* BlogService+Reminders.swift in Sources */, + C9B477BB29CD576F008CBF49 /* LockScreenUnconfiguredViewModel.swift in Sources */, 40C403F32215D66A00E8C894 /* TopViewedAuthorStatsRecordValue+CoreDataClass.swift in Sources */, 08A7343F298AB68000F925C7 /* JetpackPluginOverlayViewModel.swift in Sources */, E11C4B72201096EF00A6619C /* JetpackState.swift in Sources */, @@ -22414,6 +22426,7 @@ C9FE384029C2A3D200D39841 /* LockScreenTodayViewsStatWidgetConfig.swift in Sources */, 0107E16A28FFED1800DE87DB /* WidgetConfiguration.swift in Sources */, 3F2F0C16256C6B2C003351C7 /* StatsWidgetsService.swift in Sources */, + C9B477B629CD2EF7008CBF49 /* LockScreenUnconfiguredView.swift in Sources */, 3F526D572539FAC60069706C /* StatsWidgetsView.swift in Sources */, 3F2656A125AF4DFA0073A832 /* AppLocalizedString.swift in Sources */, 3F568A0025420DE80048A9E4 /* MultiStatsView.swift in Sources */, @@ -22444,6 +22457,7 @@ 3F8B138F25D09AA5004FAC0A /* WordPressHomeWidgetThisWeek.swift in Sources */, C9FE382C29C204E700D39841 /* LockScreenWidgetViewModelMapper.swift in Sources */, C9FE384629C2A3D200D39841 /* LockScreenStatsWidgetConfig.swift in Sources */, + C9B477B929CD2FEF008CBF49 /* LockScreenUnconfiguredViewModel.swift in Sources */, 3F5689F0254209790048A9E4 /* SingleStatView.swift in Sources */, 3FAA18CC25797B85002B1911 /* UnconfiguredView.swift in Sources */, 0107E1872900065500DE87DB /* LocalizationConfiguration.swift in Sources */, diff --git a/WordPress/WordPressStatsWidgets/LockScreenWidgets/Configs/LockScreenTodayViewsStatWidgetConfig.swift b/WordPress/WordPressStatsWidgets/LockScreenWidgets/Configs/LockScreenTodayViewsStatWidgetConfig.swift index 1a257bcb1e18..c172c3bca759 100644 --- a/WordPress/WordPressStatsWidgets/LockScreenWidgets/Configs/LockScreenTodayViewsStatWidgetConfig.swift +++ b/WordPress/WordPressStatsWidgets/LockScreenWidgets/Configs/LockScreenTodayViewsStatWidgetConfig.swift @@ -42,7 +42,8 @@ struct LockScreenTodayViewsStatWidgetConfig: LockScreenStatsWidgetConfig { var viewProvider: ViewProvider { LockScreenSingleStatWidgetViewProvider( - title: LocalizableStrings.viewsInTodayTitle + title: LocalizableStrings.viewsInTodayTitle, + widgetKind: .today ) } } diff --git a/WordPress/WordPressStatsWidgets/LockScreenWidgets/Models/LockScreenUnconfiguredViewModel.swift b/WordPress/WordPressStatsWidgets/LockScreenWidgets/Models/LockScreenUnconfiguredViewModel.swift new file mode 100644 index 000000000000..a4368ce1ad76 --- /dev/null +++ b/WordPress/WordPressStatsWidgets/LockScreenWidgets/Models/LockScreenUnconfiguredViewModel.swift @@ -0,0 +1,5 @@ +import Foundation + +struct LockScreenUnconfiguredViewModel { + let message: String +} diff --git a/WordPress/WordPressStatsWidgets/LockScreenWidgets/Models/LockScreenWidgetViewModelMapper.swift b/WordPress/WordPressStatsWidgets/LockScreenWidgets/Models/LockScreenWidgetViewModelMapper.swift index 4004b9bcbcf9..ad4bd838e7b2 100644 --- a/WordPress/WordPressStatsWidgets/LockScreenWidgets/Models/LockScreenWidgetViewModelMapper.swift +++ b/WordPress/WordPressStatsWidgets/LockScreenWidgets/Models/LockScreenWidgetViewModelMapper.swift @@ -1,24 +1,27 @@ import Foundation struct LockScreenWidgetViewModelMapper { - let data: LockScreenStatsWidgetData - func getLockScreenSingleStatViewModel( + data: LockScreenStatsWidgetData, title: String ) -> LockScreenSingleStatViewModel { LockScreenSingleStatViewModel( - siteName: getSiteName(), + siteName: getSiteName(data), title: title, - value: getViews(), + value: getViews(data), updatedTime: data.date ) } - func getSiteName() -> String { + func getLockScreenUnconfiguredViewModel(_ message: String) -> LockScreenUnconfiguredViewModel { + LockScreenUnconfiguredViewModel(message: message) + } + + private func getSiteName(_ data: LockScreenStatsWidgetData) -> String { data.siteName } - func getViews() -> String { + private func getViews(_ data: LockScreenStatsWidgetData) -> String { data.views?.abbreviatedString() ?? "" } } diff --git a/WordPress/WordPressStatsWidgets/LockScreenWidgets/ViewProvider/LockScreenSingleStatWidgetViewProvider.swift b/WordPress/WordPressStatsWidgets/LockScreenWidgets/ViewProvider/LockScreenSingleStatWidgetViewProvider.swift index cf632d803d57..3c3a2c8017a9 100644 --- a/WordPress/WordPressStatsWidgets/LockScreenWidgets/ViewProvider/LockScreenSingleStatWidgetViewProvider.swift +++ b/WordPress/WordPressStatsWidgets/LockScreenWidgets/ViewProvider/LockScreenSingleStatWidgetViewProvider.swift @@ -3,32 +3,64 @@ import SwiftUI @available(iOS 16.0, *) struct LockScreenSingleStatWidgetViewProvider: LockScreenStatsWidgetsViewProvider { typealias SiteSelectedView = LockScreenSingleStatView - typealias LoggedOutView = Text - typealias NoSiteView = Text - typealias NoDataView = Text + typealias LoggedOutView = LockScreenUnconfiguredView + typealias NoSiteView = LockScreenUnconfiguredView + typealias NoDataView = LockScreenUnconfiguredView let title: String + let widgetKind: StatsWidgetKind + let mapper = LockScreenWidgetViewModelMapper() func buildSiteSelectedView(_ data: LockScreenStatsWidgetData) -> LockScreenSingleStatView { - let mapper = LockScreenWidgetViewModelMapper(data: data) let viewModel = mapper.getLockScreenSingleStatViewModel( + data: data, title: title ) return LockScreenSingleStatView(viewModel: viewModel) } - // TODO: Build view for loggedOut status - func buildLoggedOutView() -> Text { - Text("Build Later") + func buildLoggedOutView() -> LockScreenUnconfiguredView { + var message: String { + switch widgetKind { + case .today: + return AppConfiguration.Widget.Localization.unconfiguredViewTodayTitle + case .allTime: + return AppConfiguration.Widget.Localization.unconfiguredViewAllTimeTitle + case .thisWeek: + return AppConfiguration.Widget.Localization.unconfiguredViewThisWeekTitle + } + } + let viewModel = mapper.getLockScreenUnconfiguredViewModel(message) + return LockScreenUnconfiguredView(viewModel: viewModel) } - // TODO: Build view for noSite status - func buildNoSiteView() -> Text { - Text("Build Later") + func buildNoSiteView() -> LockScreenUnconfiguredView { + var message: String { + switch widgetKind { + case .today: + return LocalizableStrings.noSiteViewTodayTitle + case .allTime: + return LocalizableStrings.noSiteViewAllTimeTitle + case .thisWeek: + return LocalizableStrings.noSiteViewThisWeekTitle + } + } + let viewModel = mapper.getLockScreenUnconfiguredViewModel(message) + return LockScreenUnconfiguredView(viewModel: viewModel) } - // TODO: Build view for noData status - func buildNoDataView() -> Text { - Text("Build Later") + func buildNoDataView() -> LockScreenUnconfiguredView { + var message: String { + switch widgetKind { + case .today: + return LocalizableStrings.noDataViewTodayTitle + case .allTime: + return LocalizableStrings.noDataViewAllTimeTitle + case .thisWeek: + return LocalizableStrings.noDataViewThisWeekTitle + } + } + let viewModel = mapper.getLockScreenUnconfiguredViewModel(message) + return LockScreenUnconfiguredView(viewModel: viewModel) } } diff --git a/WordPress/WordPressStatsWidgets/LockScreenWidgets/Views/LockScreenUnconfiguredView.swift b/WordPress/WordPressStatsWidgets/LockScreenWidgets/Views/LockScreenUnconfiguredView.swift new file mode 100644 index 000000000000..480aeb488869 --- /dev/null +++ b/WordPress/WordPressStatsWidgets/LockScreenWidgets/Views/LockScreenUnconfiguredView.swift @@ -0,0 +1,41 @@ +import SwiftUI +import WidgetKit + +@available(iOS 16.0, *) +struct LockScreenUnconfiguredView: View { + @Environment(\.widgetFamily) var family: WidgetFamily + let viewModel: LockScreenUnconfiguredViewModel + + var body: some View { + if family == .accessoryRectangular { + ZStack { + AccessoryWidgetBackground().cornerRadius(8) + Text(viewModel.message) + .font(.system(size: 11)) + .minimumScaleFactor(0.8) + .multilineTextAlignment(.center) + .padding( + EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8) + ) + } + } else { + Text("Not implemented for widget family \(family.debugDescription)") + } + } +} + +@available(iOS 16.0, *) +struct LockScreenUnconfiguredView_Previews: PreviewProvider { + static let viewModel = LockScreenUnconfiguredViewModel( + message: "Log in to Jetpack to see today's stats." + ) + + static var previews: some View { + LockScreenUnconfiguredView( + viewModel: LockScreenUnconfiguredView_Previews.viewModel + ) + .previewContext( + WidgetPreviewContext(family: .accessoryRectangular) + ) + } +} diff --git a/WordPress/WordPressTest/Widgets/WidgetsViewModelMapperTests.swift b/WordPress/WordPressTest/Widgets/WidgetsViewModelMapperTests.swift index 1fd74f18334f..a0395133275a 100644 --- a/WordPress/WordPressTest/Widgets/WidgetsViewModelMapperTests.swift +++ b/WordPress/WordPressTest/Widgets/WidgetsViewModelMapperTests.swift @@ -9,8 +9,9 @@ final class WidgetsViewModelMapperTests: XCTestCase { let todayStats = makeTodayWidgetStats(views: views) let data = makeTodayData(stats: todayStats, date: date) - let sut = makeSUT(data) + let sut = makeSUT() let viewModel = sut.getLockScreenSingleStatViewModel( + data: data, title: title ) @@ -23,17 +24,23 @@ final class WidgetsViewModelMapperTests: XCTestCase { func testTodayViewsStatsURL() { let todayStats = makeTodayWidgetStats(views: 649) let data = makeTodayData(stats: todayStats, date: Date()) - - let sut = makeSUT(data) let statsURL = data.statsURL XCTAssertEqual(statsURL?.absoluteString, "https://wordpress.com/stats/day/0?source=widget") } + + func testUnconfiguredViewModel() { + let sut = makeSUT() + let message = "Test" + let viewModel = sut.getLockScreenUnconfiguredViewModel(message) + + XCTAssertEqual(viewModel.message, message) + } } extension WidgetsViewModelMapperTests { - func makeSUT(_ data: LockScreenStatsWidgetData) -> LockScreenWidgetViewModelMapper { - LockScreenWidgetViewModelMapper(data: data) + func makeSUT() -> LockScreenWidgetViewModelMapper { + LockScreenWidgetViewModelMapper() } func makeTodayData(stats: TodayWidgetStats, date: Date) -> LockScreenStatsWidgetData {