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
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,6 @@ public class BloggingPromptSettings: NSManagedObject {
return try context.fetch(fetchRequest).first
}

func configure(with remoteSettings: RemoteBloggingPromptsSettings, siteID: Int32, context: NSManagedObjectContext) {
self.siteID = siteID
self.promptCardEnabled = remoteSettings.promptCardEnabled
self.reminderTime = remoteSettings.reminderTime
self.promptRemindersEnabled = remoteSettings.promptRemindersEnabled
self.isPotentialBloggingSite = remoteSettings.isPotentialBloggingSite
updatePromptSettingsIfNecessary(siteID: Int(siteID), enabled: isPotentialBloggingSite)
self.reminderDays = reminderDays ?? BloggingPromptSettingsReminderDays(context: context)
reminderDays?.configure(with: remoteSettings.reminderDays)
}

func reminderTimeDate() -> Date? {
guard let reminderTime else {
return nil
Expand All @@ -46,15 +35,6 @@ public class BloggingPromptSettings: NSManagedObject {
dateFormatter.dateFormat = "HH.mm"
return dateFormatter.date(from: reminderTime)
}

private func updatePromptSettingsIfNecessary(siteID: Int, enabled: Bool) {
DispatchQueue.main.async {
let service = BlogDashboardPersonalizationService(siteID: siteID)
if !service.hasPreference(for: .prompts) {
service.setEnabled(enabled, for: .prompts)
}
}
}
}

extension RemoteBloggingPromptsSettings {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,4 @@ public class BloggingPromptSettingsReminderDays: NSManagedObject {
self.saturday = remoteReminderDays.saturday
self.sunday = remoteReminderDays.sunday
}

func getActiveWeekdays() -> [BloggingRemindersScheduler.Weekday] {
return [
sunday,
monday,
tuesday,
wednesday,
thursday,
friday,
saturday
].enumerated().compactMap { (index: Int, isReminderActive: Bool) in
guard isReminderActive else {
return nil
}
return BloggingRemindersScheduler.Weekday(rawValue: index)
}
}

}
37 changes: 37 additions & 0 deletions WordPress/Classes/Models/PostVisibility.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
public enum PostVisibility: Identifiable, CaseIterable {
case `public`
case `private`
case protected

public init(post: AbstractPost) {
self.init(status: post.status ?? .draft, password: post.password)
}

init(status: AbstractPost.Status, password: String?) {
if let password, !password.isEmpty {
self = .protected
} else if status == .publishPrivate {
self = .private
} else {
self = .public
}
}

public var id: PostVisibility { self }

public var localizedTitle: String {
switch self {
case .public: NSLocalizedString("postVisibility.public.title", value: "Public", comment: "Title for a 'Public' (default) privacy setting")
case .protected: NSLocalizedString("postVisibility.protected.title", value: "Password protected", comment: "Title for a 'Password Protected' privacy setting")
case .private: NSLocalizedString("postVisibility.private.title", value: "Private", comment: "Title for a 'Private' privacy setting")
}
}

public var localizedDetails: String {
switch self {
case .public: NSLocalizedString("postVisibility.public.details", value: "Visible to everyone", comment: "Details for a 'Public' (default) privacy setting")
case .protected: NSLocalizedString("postVisibility.protected.details", value: "Visibile to everyone but requires a password", comment: "Details for a 'Password Protected' privacy setting")
case .private: NSLocalizedString("postVisibility.private.details", value: "Only visible to site admins and editors", comment: "Details for a 'Private' privacy setting")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -434,3 +434,23 @@ class BloggingRemindersScheduler {
static let notificationBody = NSLocalizedString("This is your reminder to blog today ✍️", comment: "The body of a notification displayed to the user prompting them to create a new blog post. The emoji should ideally remain, as part of the text.")
}
}

extension BloggingPromptSettingsReminderDays {

func getActiveWeekdays() -> [BloggingRemindersScheduler.Weekday] {
return [
sunday,
monday,
tuesday,
wednesday,
thursday,
friday,
saturday
].enumerated().compactMap { (index: Int, isReminderActive: Bool) in
guard isReminderActive else {
return nil
}
return BloggingRemindersScheduler.Weekday(rawValue: index)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import UIKit
import WordPressUI
import Gridicons

extension BloggingPromptsAttribution {

var attributedText: NSAttributedString {
let baseText = String(format: Strings.fromTextFormat, source)
let attributedText = NSMutableAttributedString(string: baseText, attributes: Constants.baseAttributes)
guard let range = baseText.range(of: source) else {
return attributedText
}

let nsRange = NSRange(range, in: baseText)
attributedText.addAttributes(Constants.sourceAttributes, range: nsRange)

return attributedText
}

var source: String {
switch self {
case .dayone: return Strings.dayOne
case .bloganuary: return Strings.bloganuary
}
}

var iconImage: UIImage? {
switch self {
case .dayone: return Constants.dayOneIcon
case .bloganuary: return Constants.bloganuaryIcon
}
}

var externalURL: URL? {
switch self {
case .dayone: return Constants.dayOneURL
case .bloganuary: return nil
}
}

var trailingImage: UIImage? {
guard let _ = externalURL else {
return nil
}

return Constants.linkIcon
}

private struct Strings {
static let fromTextFormat = NSLocalizedString("From %1$@", comment: "Format for blogging prompts attribution. %1$@ is the attribution source.")
static let dayOne = "Day One"
static let bloganuary = "Bloganuary"
}

private struct Constants {
static let baseAttributes: [NSAttributedString.Key: Any] = [
.font: WPStyleGuide.fontForTextStyle(.caption1),
.foregroundColor: UIColor.secondaryLabel,
]
static let sourceAttributes: [NSAttributedString.Key: Any] = [
.font: WPStyleGuide.fontForTextStyle(.caption1, fontWeight: .medium),
.foregroundColor: UIColor.label,
]
static let dayOneIconSize = CGSize(width: 18, height: 18)
static let dayOneIcon = UIImage(named: "logo-dayone")?.resized(to: Constants.dayOneIconSize)
static let dayOneURL = URL(string: "https://dayoneapp.com/?utm_source=jetpack&utm_medium=prompts")

static let linkIconSize = CGFloat(10)
static let linkIcon = UIImage(systemName: "link", withConfiguration: UIImage.SymbolConfiguration(pointSize: linkIconSize))

/// This is computed so it can react accordingly on color scheme changes.
static var bloganuaryIcon: UIImage? {
UIImage(named: "logo-bloganuary")?
.withRenderingMode(.alwaysTemplate)
.resized(to: Constants.bloganuaryIconSize)
.withAlignmentRectInsets(UIEdgeInsets(.all, -6.0))
.withTintColor(.label)
}

/// Unlike the dayOne icon, the bloganuary icon has no implicit 6px padding surrounding the icon.
static let bloganuaryIconSize = CGSize(width: 12, height: 12)
}
}
Original file line number Diff line number Diff line change
@@ -1,85 +1,4 @@
import UIKit
import WordPressUI
import Gridicons

enum BloggingPromptsAttribution: String {
public enum BloggingPromptsAttribution: String {
case dayone
case bloganuary

var attributedText: NSAttributedString {
let baseText = String(format: Strings.fromTextFormat, source)
let attributedText = NSMutableAttributedString(string: baseText, attributes: Constants.baseAttributes)
guard let range = baseText.range(of: source) else {
return attributedText
}

let nsRange = NSRange(range, in: baseText)
attributedText.addAttributes(Constants.sourceAttributes, range: nsRange)

return attributedText
}

var source: String {
switch self {
case .dayone: return Strings.dayOne
case .bloganuary: return Strings.bloganuary
}
}

var iconImage: UIImage? {
switch self {
case .dayone: return Constants.dayOneIcon
case .bloganuary: return Constants.bloganuaryIcon
}
}

var externalURL: URL? {
switch self {
case .dayone: return Constants.dayOneURL
case .bloganuary: return nil
}
}

var trailingImage: UIImage? {
guard let _ = externalURL else {
return nil
}

return Constants.linkIcon
}

private struct Strings {
static let fromTextFormat = NSLocalizedString("From %1$@", comment: "Format for blogging prompts attribution. %1$@ is the attribution source.")
static let dayOne = "Day One"
static let bloganuary = "Bloganuary"
}

private struct Constants {
static let baseAttributes: [NSAttributedString.Key: Any] = [
.font: WPStyleGuide.fontForTextStyle(.caption1),
.foregroundColor: UIColor.secondaryLabel,
]
static let sourceAttributes: [NSAttributedString.Key: Any] = [
.font: WPStyleGuide.fontForTextStyle(.caption1, fontWeight: .medium),
.foregroundColor: UIColor.label,
]
static let dayOneIconSize = CGSize(width: 18, height: 18)
static let dayOneIcon = UIImage(named: "logo-dayone")?.resized(to: Constants.dayOneIconSize)
static let dayOneURL = URL(string: "https://dayoneapp.com/?utm_source=jetpack&utm_medium=prompts")

static let linkIconSize = CGFloat(10)
static let linkIcon = UIImage(systemName: "link", withConfiguration: UIImage.SymbolConfiguration(pointSize: linkIconSize))

/// This is computed so it can react accordingly on color scheme changes.
static var bloganuaryIcon: UIImage? {
UIImage(named: "logo-bloganuary")?
.withRenderingMode(.alwaysTemplate)
.resized(to: Constants.bloganuaryIconSize)
.withAlignmentRectInsets(UIEdgeInsets(.all, -6.0))
.withTintColor(.label)
}

/// Unlike the dayOne icon, the bloganuary icon has no implicit 6px padding surrounding the icon.
static let bloganuaryIconSize = CGSize(width: 12, height: 12)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Foundation
import WordPressKit
import WordPressShared

/// `BlogDashboardPersonalizable` is a protocol that defines the requirements for personalizing blog dashboard items.
Expand Down Expand Up @@ -142,3 +143,26 @@ extension NSNotification.Name {
/// are changed.
static let blogDashboardPersonalizationSettingsChanged = NSNotification.Name("BlogDashboardPersonalizationSettingsChanged")
}

extension BloggingPromptSettings {

func configure(with remoteSettings: RemoteBloggingPromptsSettings, siteID: Int32, context: NSManagedObjectContext) {
self.siteID = siteID
self.promptCardEnabled = remoteSettings.promptCardEnabled
self.reminderTime = remoteSettings.reminderTime
self.promptRemindersEnabled = remoteSettings.promptRemindersEnabled
self.isPotentialBloggingSite = remoteSettings.isPotentialBloggingSite
updatePromptSettingsIfNecessary(siteID: Int(siteID), enabled: isPotentialBloggingSite)
self.reminderDays = reminderDays ?? BloggingPromptSettingsReminderDays(context: context)
reminderDays?.configure(with: remoteSettings.reminderDays)
}

private func updatePromptSettingsIfNecessary(siteID: Int, enabled: Bool) {
DispatchQueue.main.async {
let service = BlogDashboardPersonalizationService(siteID: siteID)
if !service.hasPreference(for: .prompts) {
service.setEnabled(enabled, for: .prompts)
}
}
}
}
38 changes: 0 additions & 38 deletions WordPress/Classes/ViewRelated/Post/PostVisibilityPicker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,44 +149,6 @@ private struct PasswordField: View {
}
}

enum PostVisibility: Identifiable, CaseIterable {
case `public`
case `private`
case protected

init(post: AbstractPost) {
self.init(status: post.status ?? .draft, password: post.password)
}

init(status: AbstractPost.Status, password: String?) {
if let password, !password.isEmpty {
self = .protected
} else if status == .publishPrivate {
self = .private
} else {
self = .public
}
}

var id: PostVisibility { self }

var localizedTitle: String {
switch self {
case .public: NSLocalizedString("postVisibility.public.title", value: "Public", comment: "Title for a 'Public' (default) privacy setting")
case .protected: NSLocalizedString("postVisibility.protected.title", value: "Password protected", comment: "Title for a 'Password Protected' privacy setting")
case .private: NSLocalizedString("postVisibility.private.title", value: "Private", comment: "Title for a 'Private' privacy setting")
}
}

var localizedDetails: String {
switch self {
case .public: NSLocalizedString("postVisibility.public.details", value: "Visible to everyone", comment: "Details for a 'Public' (default) privacy setting")
case .protected: NSLocalizedString("postVisibility.protected.details", value: "Visibile to everyone but requires a password", comment: "Details for a 'Password Protected' privacy setting")
case .private: NSLocalizedString("postVisibility.private.details", value: "Only visible to site admins and editors", comment: "Details for a 'Private' privacy setting")
}
}
}

private enum Strings {
static let title = NSLocalizedString("postVisibilityPicker.navigationTitle", value: "Visibility", comment: "Navigation bar title for the Post Visibility picker")
static let cancel = NSLocalizedString("postVisibilityPicker.cancel", value: "Cancel", comment: "Button cancel")
Expand Down
4 changes: 0 additions & 4 deletions WordPress/WordPress.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,6 @@
D821C817210036D9002ED995 /* ActivityContentFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D821C816210036D9002ED995 /* ActivityContentFactoryTests.swift */; };
D821C819210037F8002ED995 /* activity-log-activity-content.json in Resources */ = {isa = PBXBuildFile; fileRef = D821C818210037F8002ED995 /* activity-log-activity-content.json */; };
D821C81B21003AE9002ED995 /* FormattableContentGroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D821C81A21003AE9002ED995 /* FormattableContentGroupTests.swift */; };
D826D67F211D21C700A5D8FE /* NullMockUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D826D67E211D21C700A5D8FE /* NullMockUserDefaults.swift */; };
D82E087529EEB0B00098F500 /* DashboardTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D82E087429EEB0B00098F500 /* DashboardTests.swift */; };
D82E087629EEB0B00098F500 /* DashboardTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D82E087429EEB0B00098F500 /* DashboardTests.swift */; };
D842EA4021FABB1800210E96 /* SiteSegmentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D842EA3F21FABB1700210E96 /* SiteSegmentTests.swift */; };
Expand Down Expand Up @@ -2513,7 +2512,6 @@
D821C816210036D9002ED995 /* ActivityContentFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityContentFactoryTests.swift; sourceTree = "<group>"; };
D821C818210037F8002ED995 /* activity-log-activity-content.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "activity-log-activity-content.json"; sourceTree = "<group>"; };
D821C81A21003AE9002ED995 /* FormattableContentGroupTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattableContentGroupTests.swift; sourceTree = "<group>"; };
D826D67E211D21C700A5D8FE /* NullMockUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NullMockUserDefaults.swift; sourceTree = "<group>"; };
D82E087429EEB0B00098F500 /* DashboardTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardTests.swift; sourceTree = "<group>"; };
D842EA3F21FABB1700210E96 /* SiteSegmentTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SiteSegmentTests.swift; sourceTree = "<group>"; };
D848CBF620FEEE7F00A9038F /* notifications-text-content.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "notifications-text-content.json"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4398,7 +4396,6 @@
0CF7D6C22ABB753A006D1E89 /* MediaImageServiceTests.swift */,
C38C5D8027F61D2C002F517E /* MenuItemTests.swift */,
D848CC1420FF33FC00A9038F /* NotificationContentRangeTests.swift */,
D826D67E211D21C700A5D8FE /* NullMockUserDefaults.swift */,
5960967E1CF7959300848496 /* PostTests.swift */,
FEFA6AC72A88D5FC004EE5E6 /* Post+JetpackSocialTests.swift */,
8BBBEBB124B8F8C0005E358E /* ReaderCardTests.swift */,
Expand Down Expand Up @@ -8077,7 +8074,6 @@
D81C2F5E20F88CE5002AE1F1 /* MarkAsSpamActionTests.swift in Sources */,
D848CC1520FF33FC00A9038F /* NotificationContentRangeTests.swift in Sources */,
084FC3B729913B1B00A17BCF /* JetpackPluginOverlayViewModelTests.swift in Sources */,
D826D67F211D21C700A5D8FE /* NullMockUserDefaults.swift in Sources */,
7E987F58210811CC00CAFB88 /* NotificationContentRouterTests.swift in Sources */,
E1C9AA561C10427100732665 /* MathTest.swift in Sources */,
93A379EC19FFBF7900415023 /* KeychainTest.m in Sources */,
Expand Down
Loading