Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Today widget to MVVM architecture : viewModel and model files added #6864

Merged
36 changes: 36 additions & 0 deletions Client.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@
/* Begin PBXBuildFile section */
03CCC9181AF05E7300DBF30D /* RelativeDatesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03CCC9171AF05E7300DBF30D /* RelativeDatesTests.swift */; };
0430A545203B372D00FDF76D /* IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0430A544203B372D00FDF76D /* IntegrationTests.swift */; };
048B4C7924A53E7B001B56E8 /* TodayModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C7824A53E7B001B56E8 /* TodayModel.swift */; };
048B4C7A24A53E7B001B56E8 /* TodayModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C7824A53E7B001B56E8 /* TodayModel.swift */; };
048B4C7D24A53EA8001B56E8 /* TodayViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C7C24A53EA8001B56E8 /* TodayViewModel.swift */; };
048B4C7E24A53EA8001B56E8 /* TodayViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C7C24A53EA8001B56E8 /* TodayViewModel.swift */; };
048B4C8024A53EEB001B56E8 /* ImageButtonWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C7F24A53EEB001B56E8 /* ImageButtonWithLabel.swift */; };
048B4C8124A53EEB001B56E8 /* ImageButtonWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C7F24A53EEB001B56E8 /* ImageButtonWithLabel.swift */; };
048B4C8324A53F26001B56E8 /* ButtonWithSublabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C8224A53F26001B56E8 /* ButtonWithSublabel.swift */; };
048B4C8424A53F26001B56E8 /* ButtonWithSublabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C8224A53F26001B56E8 /* ButtonWithSublabel.swift */; };
048B4C8624A53F3E001B56E8 /* TodayUX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C8524A53F3E001B56E8 /* TodayUX.swift */; };
048B4C8724A53F3E001B56E8 /* TodayUX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C8524A53F3E001B56E8 /* TodayUX.swift */; };
048B4C8924A53F81001B56E8 /* UIButtonExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C8824A53F81001B56E8 /* UIButtonExtensions.swift */; };
048B4C8A24A53F81001B56E8 /* UIButtonExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 048B4C8824A53F81001B56E8 /* UIButtonExtensions.swift */; };
0B21E8061E26CCB7000C8779 /* EarlGrey.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0B21E8051E26CCB7000C8779 /* EarlGrey.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
0B305E1B1E3A98A900BE0767 /* BookmarkingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B305E1A1E3A98A900BE0767 /* BookmarkingTests.swift */; };
0B3D670E1E09B90B00C1EFC7 /* AuthenticationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3D670D1E09B90B00C1EFC7 /* AuthenticationTest.swift */; };
Expand Down Expand Up @@ -1165,6 +1177,12 @@
/* Begin PBXFileReference section */
03CCC9171AF05E7300DBF30D /* RelativeDatesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RelativeDatesTests.swift; sourceTree = "<group>"; };
0430A544203B372D00FDF76D /* IntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationTests.swift; sourceTree = "<group>"; };
048B4C7824A53E7B001B56E8 /* TodayModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayModel.swift; sourceTree = "<group>"; };
048B4C7C24A53EA8001B56E8 /* TodayViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewModel.swift; sourceTree = "<group>"; };
048B4C7F24A53EEB001B56E8 /* ImageButtonWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageButtonWithLabel.swift; sourceTree = "<group>"; };
048B4C8224A53F26001B56E8 /* ButtonWithSublabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonWithSublabel.swift; sourceTree = "<group>"; };
048B4C8524A53F3E001B56E8 /* TodayUX.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayUX.swift; sourceTree = "<group>"; };
048B4C8824A53F81001B56E8 /* UIButtonExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIButtonExtensions.swift; sourceTree = "<group>"; };
0B21E8051E26CCB7000C8779 /* EarlGrey.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = EarlGrey.framework; path = Carthage/Build/iOS/EarlGrey.framework; sourceTree = "<group>"; };
0B305E1A1E3A98A900BE0767 /* BookmarkingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarkingTests.swift; sourceTree = "<group>"; };
0B3D670D1E09B90B00C1EFC7 /* AuthenticationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticationTest.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2458,6 +2476,12 @@
391AEFD11C8F11ED00691F84 /* Images.xcassets */,
390527531C874D35007E0BB7 /* Info.plist */,
3905274E1C874D35007E0BB7 /* TodayViewController.swift */,
048B4C7824A53E7B001B56E8 /* TodayModel.swift */,
048B4C7C24A53EA8001B56E8 /* TodayViewModel.swift */,
048B4C7F24A53EEB001B56E8 /* ImageButtonWithLabel.swift */,
048B4C8224A53F26001B56E8 /* ButtonWithSublabel.swift */,
048B4C8524A53F3E001B56E8 /* TodayUX.swift */,
048B4C8824A53F81001B56E8 /* UIButtonExtensions.swift */,
);
path = Today;
sourceTree = "<group>";
Expand Down Expand Up @@ -4897,8 +4921,14 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
048B4C7E24A53EA8001B56E8 /* TodayViewModel.swift in Sources */,
048B4C8724A53F3E001B56E8 /* TodayUX.swift in Sources */,
048B4C8124A53EEB001B56E8 /* ImageButtonWithLabel.swift in Sources */,
315D05561E58DD60001F349B /* UIPasteboardExtensions.swift in Sources */,
3905274F1C874D35007E0BB7 /* TodayViewController.swift in Sources */,
048B4C8A24A53F81001B56E8 /* UIButtonExtensions.swift in Sources */,
048B4C7A24A53E7B001B56E8 /* TodayModel.swift in Sources */,
048B4C8424A53F26001B56E8 /* ButtonWithSublabel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -5081,6 +5111,7 @@
5F130D2E2483508E00B0F7D0 /* FxAWebViewModel.swift in Sources */,
D0FCF7F51FE45842004A7995 /* UserScriptManager.swift in Sources */,
E4A960061ABB9C450069AD6F /* ReaderModeUtils.swift in Sources */,
048B4C8324A53F26001B56E8 /* ButtonWithSublabel.swift in Sources */,
435D660323D793DF0046EFA2 /* UpdateModel.swift in Sources */,
EBF47E701F7979DF00899189 /* UnifiedTelemetry.swift in Sources */,
E68F36981EA694000048CF44 /* PanelDataObservers.swift in Sources */,
Expand All @@ -5099,6 +5130,7 @@
D3C3696E1CC6B78800348A61 /* LocalRequestHelper.swift in Sources */,
E4B423DD1ABA0318007E66C8 /* ReaderModeHandlers.swift in Sources */,
D308E4E41A5306F500842685 /* SearchEngines.swift in Sources */,
048B4C8924A53F81001B56E8 /* UIButtonExtensions.swift in Sources */,
3BCE6D3C1CEB9E4D0080928C /* ThirdPartySearchAlerts.swift in Sources */,
745DAB301CDAAFAA00D44181 /* RecentlyClosedTabsPanel.swift in Sources */,
D0B9483D22A18B78002F4AA1 /* TextFieldTableViewCell.swift in Sources */,
Expand All @@ -5111,6 +5143,7 @@
39F819C61FD70F5D009E31E4 /* TabEventHandlers.swift in Sources */,
E65607611C08B4E200534B02 /* SearchInputView.swift in Sources */,
FA6B2AC21D41F02D00429414 /* Punycode.swift in Sources */,
048B4C7D24A53EA8001B56E8 /* TodayViewModel.swift in Sources */,
43446CEA2412066500F5C643 /* UIViewControllerExtension.swift in Sources */,
D301AAEE1A3A55B70078DD1D /* TabTrayControllerV1.swift in Sources */,
EB9A179B20E69A7F00B12184 /* ThemeManager.swift in Sources */,
Expand All @@ -5119,6 +5152,7 @@
EBB89509219398E500EB91A0 /* TabContentBlocker+ContentScript.swift in Sources */,
D3BE7B461B054F8600641031 /* TestAppDelegate.swift in Sources */,
3BB50E111D6274CD004B33DF /* FirefoxHomeTopSitesCell.swift in Sources */,
048B4C8624A53F3E001B56E8 /* TodayUX.swift in Sources */,
0B62EFD21AD63CD100ACB9CD /* Clearables.swift in Sources */,
7482205C1DBAB56300EEEA72 /* MailProviders.swift in Sources */,
C40046FA1CF8E0B200B08303 /* BackForwardListAnimator.swift in Sources */,
Expand All @@ -5130,6 +5164,7 @@
274A36CC239EB99400A21587 /* LibraryPanelContextMenu.swift in Sources */,
D314E7F71A37B98700426A76 /* TabToolbar.swift in Sources */,
CEFA977E1FAA6B490016F365 /* SyncContentSettingsViewController.swift in Sources */,
048B4C7924A53E7B001B56E8 /* TodayModel.swift in Sources */,
E60D03181D511398002FE3F6 /* SyncStatusResolver.swift in Sources */,
435D660723D7962C0046EFA2 /* UpdateCoverSheetTableViewCell.swift in Sources */,
C4E3983D1D21F1E7004E89BA /* TopTabsViews.swift in Sources */,
Expand Down Expand Up @@ -5265,6 +5300,7 @@
A93067E81D0FE18E00C49C6E /* NightModeHelper.swift in Sources */,
3B39EDCB1E16E1AA00EF029F /* CustomSearchViewController.swift in Sources */,
E65075571E37F714006961AC /* FaviconFetcher.swift in Sources */,
048B4C8024A53EEB001B56E8 /* ImageButtonWithLabel.swift in Sources */,
D863C8F21F68BFC20058D95F /* GradientProgressBar.swift in Sources */,
EB9A178E20E525DF00B12184 /* ThemeSettingsController.swift in Sources */,
D3C744CD1A687D6C004CE85D /* URIFixup.swift in Sources */,
Expand Down
56 changes: 56 additions & 0 deletions Extensions/Today/ButtonWithSublabel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import UIKit

class ButtonWithSublabel: UIButton {
lazy var subtitleLabel = UILabel()
lazy var label = UILabel()

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

convenience init() {
self.init(frame: .zero)
}

override init(frame: CGRect) {
super.init(frame: frame)
performLayout()
}

fileprivate func performLayout() {
let buttonImage = self.imageView!
self.titleLabel?.removeFromSuperview()
addSubview(self.label)
addSubview(self.subtitleLabel)

buttonImage.snp.makeConstraints { make in
make.centerY.left.equalTo(10)
make.width.equalTo(TodayUX.copyLinkImageWidth)
}

self.label.snp.makeConstraints { make in
make.left.equalTo(buttonImage.snp.right).offset(10)
make.trailing.top.equalTo(self)
make.height.greaterThanOrEqualTo(15)
}
self.label.numberOfLines = 1
self.label.lineBreakMode = .byWordWrapping

self.subtitleLabel.lineBreakMode = .byTruncatingTail
self.subtitleLabel.snp.makeConstraints { make in
make.bottom.equalTo(self).inset(10)
make.top.equalTo(self.label.snp.bottom).offset(3)
make.leading.trailing.equalTo(self.label)
make.height.greaterThanOrEqualTo(10)
}
}

override func setTitle(_ text: String?, for state: UIControl.State) {
self.label.text = text
super.setTitle(text, for: state)
}
}
47 changes: 47 additions & 0 deletions Extensions/Today/ImageButtonWithLabel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import UIKit

class ImageButtonWithLabel: UIView {
lazy var button = UIButton()
lazy var label = UILabel()

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override init(frame: CGRect) {
super.init(frame: frame)
performLayout()
}

fileprivate func performLayout() {
addSubview(button)
addSubview(label)
button.imageView?.contentMode = .scaleAspectFit

button.snp.makeConstraints { make in
make.centerX.equalTo(self)
make.top.equalTo(self.safeAreaLayoutGuide).offset(5)
make.right.greaterThanOrEqualTo(self.safeAreaLayoutGuide).offset(40)
make.left.greaterThanOrEqualTo(self.safeAreaLayoutGuide).inset(40)
make.height.greaterThanOrEqualTo(60)
}

label.snp.makeConstraints { make in
make.top.equalTo(button.snp.bottom).offset(10)
make.leading.trailing.bottom.equalTo(self)
make.height.greaterThanOrEqualTo(10)
}

label.numberOfLines = 1
label.lineBreakMode = .byWordWrapping
label.textAlignment = .center
}

func addTarget(_ target: AnyObject?, action: Selector, forControlEvents events: UIControl.Event) {
button.addTarget(target, action: action, for: events)
}
}
17 changes: 17 additions & 0 deletions Extensions/Today/TodayModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import Foundation

struct TodayModel {
static var copiedURL: URL?

var scheme: String {
guard let string = Bundle.main.object(forInfoDictionaryKey: "MozInternalURLScheme") as? String else {
// Something went wrong/weird, but we should fallback to the public one.
return "firefox"
}
return string
}
}
30 changes: 30 additions & 0 deletions Extensions/Today/TodayUX.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import UIKit

struct TodayUX {
static let backgroundHightlightColor = UIColor(white: 216.0/255.0, alpha: 44.0/255.0)
static let linkTextSize: CGFloat = 9.0
static let labelTextSize: CGFloat = 12.0
static let imageButtonTextSize: CGFloat = 13.0
static let copyLinkImageWidth: CGFloat = 20
static let margin: CGFloat = 8
static let buttonsHorizontalMarginPercentage: CGFloat = 0.1
static let buttonStackViewSpacing: CGFloat = 20.0
static var labelColor: UIColor {
if #available(iOS 13, *) {
return UIColor(named: "widgetLabelColors") ?? UIColor(rgb: 0x242327)
} else {
return UIColor(rgb: 0x242327)
}
}
static var subtitleLabelColor: UIColor {
if #available(iOS 13, *) {
return UIColor(named: "subtitleLableColor") ?? UIColor(rgb: 0x38383C)
} else {
return UIColor(rgb: 0x38383C)
}
}
}
Loading