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

chore: Notification preference settings and relevant code #104

Merged
merged 5 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion Core/Core.xcodeproj/xcshareddata/xcschemes/Core.xcscheme
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1610"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
5 changes: 5 additions & 0 deletions Core/Core/Analytics/CoreAnalytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ public enum AnalyticsEvent: String {
case videoStreamQualityChanged = "Video:Streaming Quality Changed"
case videoDownloadQualityChanged = "Video:Download Quality Changed"
case profileVideoSettingsClicked = "Profile:Video Setting Clicked"
case profilePushSettingsClicked = "Profile:Push Notifications Setting Clicked"
case privacyPolicyClicked = "Profile:Privacy Policy Clicked"
case cookiePolicyClicked = "Profile:Cookie Policy Clicked"
case emailSupportClicked = "Profile:Contact Support Clicked"
Expand Down Expand Up @@ -332,6 +333,7 @@ public enum AnalyticsEvent: String {
case discussionLikeToggle = "Discussion:Like Toggle"
case discussionReportToggle = "Discussion:Report Toggle"
case notificationSettingPermissionStatus = "Notification:Setting Permission Status"
case notificationDiscussionPermissionToggle = "Notification:Discussion Permission Toggle"

}

Expand Down Expand Up @@ -363,6 +365,7 @@ public enum EventBIValue: String {
case profileEditClicked = "edx.bi.app.profile.edit.clicked"
case profileEditDoneClicked = "edx.bi.app.profile.edit_done.clicked"
case profileVideoSettingsClicked = "edx.bi.app.profile.video_setting.clicked"
case profilePushSettingsClicked = "edx.bi.app.profile.push_notifications_setting.clicked"
case emailSupportClicked = "edx.bi.app.profile.email_support.clicked"
case faqClicked = "edx.bi.app.profile.faq.clicked"
case tosClicked = "edx.bi.app.profile.terms_of_use.clicked"
Expand Down Expand Up @@ -445,6 +448,7 @@ public enum EventBIValue: String {
case discussionLikeToggle = "edx.bi.app.discussion.like_toggle"
case discussionReportToggle = "edx.bi.app.discussion.report_toggle"
case notificationSettingPermissionStatus = "edx.bi.app.notification.setting_permission.status"
case notificationDiscussionPermissionToggle = "edx.bi.app.notification.discussion.permission.toggle"
}

public struct EventParamKey {
Expand Down Expand Up @@ -515,4 +519,5 @@ public struct EventCategory {
public static let video = "video"
public static let course = "course"
public static let inAppPurchases = "in_app_purchases"
public static let notifications = "notifications"
}
6 changes: 6 additions & 0 deletions Core/Core/Configuration/Config/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public protocol ConfigProtocol {
var URIScheme: String { get }
var ecommerceURL: String? { get }
var fullStory: FullStoryConfig { get }
var pushNotificationsEnabled: Bool { get }
}

public enum TokenType: String {
Expand All @@ -52,6 +53,7 @@ private enum ConfigKeys: String {
case faq = "FAQ_URL"
case URIScheme = "URI_SCHEME"
case ecommerceURL = "ECOMMERCE_URL"
case pushNotificationsEnabled = "PUSH_NOTIFICATIONS_ENABLED"
}

public class Config {
Expand Down Expand Up @@ -167,6 +169,10 @@ extension Config: ConfigProtocol {
public var ecommerceURL: String? {
string(for: ConfigKeys.ecommerceURL.rawValue)
}

public var pushNotificationsEnabled: Bool {
bool(for: ConfigKeys.pushNotificationsEnabled.rawValue)
}
}

// Mark - For testing and SwiftUI preview
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1610"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1610"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
8 changes: 8 additions & 0 deletions Notifications/Notifications.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
02F1752F2A4DA3B60019CD70 /* NotificationsAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F1752E2A4DA3B60019CD70 /* NotificationsAnalytics.swift */; };
02F3BFDF29252F2F0051930C /* NotificationsRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F3BFDE29252F2F0051930C /* NotificationsRouter.swift */; };
072787AD28D34D15002E9142 /* Core.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 072787AC28D34D15002E9142 /* Core.framework */; };
146CF94A2D0BFD9B000955B2 /* NotificationsPersistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 146CF9492D0BFD92000955B2 /* NotificationsPersistence.swift */; };
149D4A9A2D0BEF7E003A2E1D /* NotificationsSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 149D4A992D0BEF7B003A2E1D /* NotificationsSettingsViewModel.swift */; };
14BAE6912D0978C300EAF0E4 /* NotificationsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14BAE6902D0978BC00EAF0E4 /* NotificationsSettingsView.swift */; };
87E3F4AB2D8BE4FD628C91C4 /* Pods_App_Notifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CAFCD31A42C7E150939829CE /* Pods_App_Notifications.framework */; };
FB43867C6484A90253882035 /* Pods_App_Notifications_NotificationsTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FEAD4AF36405458BBBE5AB /* Pods_App_Notifications_NotificationsTests.framework */; };
Expand Down Expand Up @@ -49,6 +51,8 @@
02F3BFDE29252F2F0051930C /* NotificationsRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsRouter.swift; sourceTree = "<group>"; };
0727879928D34C03002E9142 /* Notifications.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Notifications.framework; sourceTree = BUILT_PRODUCTS_DIR; };
072787AC28D34D15002E9142 /* Core.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Core.framework; sourceTree = BUILT_PRODUCTS_DIR; };
146CF9492D0BFD92000955B2 /* NotificationsPersistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsPersistence.swift; sourceTree = "<group>"; };
149D4A992D0BEF7B003A2E1D /* NotificationsSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsSettingsViewModel.swift; sourceTree = "<group>"; };
14BAE6902D0978BC00EAF0E4 /* NotificationsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsSettingsView.swift; sourceTree = "<group>"; };
14BAE6A82D09D01400EAF0E4 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = "<group>"; };
3CD79FA3FF160D72A5BE303D /* Pods-App-Notifications-NotificationsTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Notifications-NotificationsTests.release.xcconfig"; path = "Target Support Files/Pods-App-Notifications-NotificationsTests/Pods-App-Notifications-NotificationsTests.release.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -97,6 +101,7 @@
0208666829CC6CD600BC05B2 /* Persistence */ = {
isa = PBXGroup;
children = (
146CF9492D0BFD92000955B2 /* NotificationsPersistence.swift */,
029737412949FB3B0051696B /* NotificationsPersistenceProtocol.swift */,
);
path = Persistence;
Expand Down Expand Up @@ -203,6 +208,7 @@
1402A0C62B61011D00A0A00B /* Settings */ = {
isa = PBXGroup;
children = (
149D4A992D0BEF7B003A2E1D /* NotificationsSettingsViewModel.swift */,
14BAE6902D0978BC00EAF0E4 /* NotificationsSettingsView.swift */,
);
path = Settings;
Expand Down Expand Up @@ -449,10 +455,12 @@
0284DBFC28D4856A00830893 /* NotificationsEndpoint.swift in Sources */,
0283347728D499BC00C828FC /* NotificationsInteractor.swift in Sources */,
02F3BFDF29252F2F0051930C /* NotificationsRouter.swift in Sources */,
146CF94A2D0BFD9B000955B2 /* NotificationsPersistence.swift in Sources */,
029737422949FB3B0051696B /* NotificationsPersistenceProtocol.swift in Sources */,
0284DC0328D4922900830893 /* NotificationsRepository.swift in Sources */,
02EF39DC28D86BEF0058F6BD /* Strings.swift in Sources */,
02F1752F2A4DA3B60019CD70 /* NotificationsAnalytics.swift in Sources */,
149D4A9A2D0BEF7E003A2E1D /* NotificationsSettingsViewModel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this file as it's duplicate here.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// NotificationsPersistence.swift
// Notifications
//
// Created by Saeed Bashir on 12/13/24.
//

import CoreData

public class NotificationsPersistence: NotificationsPersistenceProtocol {
private var context: NSManagedObjectContext

public init(context: NSManagedObjectContext) {
self.context = context
}
}
10 changes: 5 additions & 5 deletions Notifications/Notifications/Domain/NotificationsInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public class NotificationsInteractor: NotificationsInteractorProtocol {
}

// Mark - For testing and SwiftUI preview
//#if DEBUG
//public extension NotificationsInteractor {
// static let mock = NotificationsInteractor(repository: NotificationsRepositoryMock())
//}
//#endif
#if DEBUG
public extension NotificationsInteractor {
static let mock = NotificationsInteractor(repository: NotificationsRepositoryMock())
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import Core

//sourcery: AutoMockable
public protocol NotificationsAnalytics {
func NotificationsScreenEvent(event: AnalyticsEvent, biValue: EventBIValue)
func notificationsScreenEvent(event: AnalyticsEvent, biValue: EventBIValue)
func notificationsDiscussionPermissionToggleEvent(action: Bool)
}

#if DEBUG
class NotificationsAnalyticsMock: NotificationsAnalytics {
public func NotificationsScreenEvent(event: AnalyticsEvent, biValue: EventBIValue) {}
public func notificationsScreenEvent(event: AnalyticsEvent, biValue: EventBIValue) {}
public func notificationsDiscussionPermissionToggleEvent(action: Bool) {}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public protocol NotificationsRouter: BaseRouter {
// Mark - For testing and SwiftUI preview
#if DEBUG
public class NotificationsRouterMock: BaseRouterMock, NotificationsRouter {

public override init() {}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,80 @@

import SwiftUI
import Theme
import Core

public struct NotificationsSettingsView: View {
@ObservedObject
private var viewModel: NotificationsSettingsViewModel

public init(viewModel: NotificationsSettingsViewModel) {
self.viewModel = viewModel
}

public var body: some View {
GeometryReader { proxy in
ZStack(alignment: .top) {
VStack(alignment: .center) {
Text("Notificaion settings view")
VStack(alignment: .leading) {
HStack {
Text(NotificationsLocalization.Settings.preferenceTitle)
.font(Theme.Fonts.titleMedium)
.foregroundStyle(Theme.Colors.textPrimary)

Spacer()
Toggle(isOn: $viewModel.hasPermission, label: {})
.toggleStyle(SwitchToggleStyle(tint: Theme.Colors.toggleSwitchColor))
.frame(width: 50)
.accessibilityIdentifier("discussion_switch")
.onTapGesture {
viewModel.toggleNotificationsPermissionAction()
}

}
Text(NotificationsLocalization.Settings.preferenceDescription)
.font(Theme.Fonts.bodyMedium)
.foregroundStyle(Theme.Colors.textSecondary)

Divider()
.padding(20)
}
.frameLimit(width: proxy.size.width)
.padding(20)

if viewModel.showError {
VStack {
Spacer()
SnackBarView(message: viewModel.errorMessage)
}
.transition(.move(edge: .bottom))
.onAppear {
doAfter(Theme.Timeout.snackbarMessageLongTimeout) {
viewModel.errorMessage = nil
}
}
}
.hideNavigationBar(true)
.navigationBarBackButtonHidden(true)
.navigationTitle(NotificationsLocalization.Notifications.Settings.title)
}

.hideNavigationBar(false)
.navigationBarBackButtonHidden(false)
.navigationTitle(NotificationsLocalization.Settings.title)
}
.background(
Theme.Colors.background
.ignoresSafeArea()
)
.ignoresSafeArea(.all, edges: .horizontal)
.animation(.default, value: viewModel.showError)
}
}

#if DEBUG
struct NotificationsSettingsView_Previews: PreviewProvider {
static var previews: some View {
NotificationsSettingsView(
viewModel: NotificationsSettingsViewModel(
interactor: NotificationsInteractor.mock,
analytics: NotificationsAnalyticsMock()
)
)
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// NotificationsSettingsViewModel.swift
// Notifications
//
// Created by Saeed Bashir on 12/13/24.
//

import Foundation
import Core
import SwiftUI

public class NotificationsSettingsViewModel: ObservableObject {
@Published var showError: Bool = false
public var hasPermission: Bool = false
Copy link
Collaborator

@rnr rnr Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we will have a list of push settings, perhaps we need to develop a way to interact with the list of ‘settings’.
Same in View - we need to have a ForEach that will show a list of all settings (I realise we don't have an API now, but we need to interact with many settings, and for the API we could just have an empty function at the moment). Just add one/two more settings to the existing ‘Discussion Activities'.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in the future, we will be getting more push notification settings, but when we are not sure, that's why I keep it simple as per the current requirements. When they come, we will plan it accordingly.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it

private var interactor: NotificationsInteractorProtocol
private var analytics: NotificationsAnalytics

var errorMessage: String? {
didSet {
showError = errorMessage != nil

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation issue

}
}

public init(
interactor: NotificationsInteractorProtocol,
analytics: NotificationsAnalytics
) {
self.interactor = interactor
self.analytics = analytics
}

public func toggleNotificationsPermissionAction() {
hasPermission.toggle()
analytics.notificationsDiscussionPermissionToggleEvent(action: hasPermission)
}
}
12 changes: 7 additions & 5 deletions Notifications/Notifications/SwiftGen/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import Foundation
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
public enum NotificationsLocalization {
public enum Notifications {
public enum Settings {
/// Push Notifications
public static let title = NotificationsLocalization.tr("Localizable", "NOTIFICATIONS.SETTINGS.TITLE", fallback: "Push Notifications")
}
public enum Settings {
/// Notifications for course discussions you post, comment, or follow.
public static let preferenceDescription = NotificationsLocalization.tr("Localizable", "SETTINGS.PREFERENCE_DESCRIPTION", fallback: "Notifications for course discussions you post, comment, or follow.")
/// Discussions Activity
public static let preferenceTitle = NotificationsLocalization.tr("Localizable", "SETTINGS.PREFERENCE_TITLE", fallback: "Discussions Activity")
/// Push Notifications
public static let title = NotificationsLocalization.tr("Localizable", "SETTINGS.TITLE", fallback: "Push Notifications")
}
}
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
Expand Down
6 changes: 5 additions & 1 deletion Notifications/Notifications/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@

*/

NOTIFICATIONS.SETTINGS.TITLE="Push Notifications";
SETTINGS.TITLE="Push Notifications";
SETTINGS.PREFERENCE_TITLE="Discussions Activity";
SETTINGS.PREFERENCE_DESCRIPTION="Notifications for course discussions you post, comment, or follow.";


4 changes: 3 additions & 1 deletion Notifications/Notifications/uk.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@

*/

NOTIFICATIONS.SETTINGS.TITLE="Push Notifications";
SETTINGS.TITLE="Push Notifications";
SETTINGS.PREFERENCE_TITLE="Discussions Activity";
SETTINGS.PREFERENCE_DESCRIPTION="Notifications for course discussions you post, comment, or follow.";
Loading
Loading