Commit 899bbabd by Demid Merzlyakov

All menu items are functioning.

parent 72ede3bb
......@@ -211,6 +211,7 @@
CE849DB82638C33600DEFFBD /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE849DB72638C33600DEFFBD /* NotificationService.swift */; };
CE849DBC2638C33600DEFFBD /* OneWeatherNotificationServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = CE849DB52638C33600DEFFBD /* OneWeatherNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
CE849E382638CE8000DEFFBD /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE849E372638CE8000DEFFBD /* UserNotifications.framework */; };
CE8805D3263AEEE6003C53B7 /* UIDevice+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8805D2263AEEE6003C53B7 /* UIDevice+Convenience.swift */; };
CE895F0F26393FD800214175 /* WeatherImageProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE895F0E26393FD800214175 /* WeatherImageProvider.swift */; };
CE89628C26175D8D00CA274A /* regenerate_objects.sh in Resources */ = {isa = PBXBuildFile; fileRef = CE89628B26175D8D00CA274A /* regenerate_objects.sh */; };
CE8962A226175DF500CA274A /* _CoreAirQuality.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE89629126175DF400CA274A /* _CoreAirQuality.swift */; };
......@@ -535,6 +536,7 @@
CE849DB92638C33600DEFFBD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CE849DE82638C59800DEFFBD /* OneWeatherNotificationServiceExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OneWeatherNotificationServiceExtension.entitlements; sourceTree = "<group>"; };
CE849E372638CE8000DEFFBD /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
CE8805D2263AEEE6003C53B7 /* UIDevice+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDevice+Convenience.swift"; sourceTree = "<group>"; };
CE895F0E26393FD800214175 /* WeatherImageProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeatherImageProvider.swift; sourceTree = "<group>"; };
CE89628B26175D8D00CA274A /* regenerate_objects.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = regenerate_objects.sh; sourceTree = "<group>"; };
CE89629126175DF400CA274A /* _CoreAirQuality.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = _CoreAirQuality.swift; sourceTree = "<group>"; };
......@@ -739,6 +741,7 @@
CDF48091261729680076E9F5 /* UIApplication+Settings.swift */,
CD67616C262587D30079D273 /* UITabBarController+Hide.swift */,
CD43DF022636C6640010C9F7 /* CACornerMask+All.swift */,
CE8805D2263AEEE6003C53B7 /* UIDevice+Convenience.swift */,
);
path = Extensions;
sourceTree = "<group>";
......@@ -2031,6 +2034,7 @@
CD35DFCC260341B000F2138F /* Calendar+TimeZone.swift in Sources */,
CD9B6B1125DBC723001D9B80 /* CubicCurveAlgorithm.swift in Sources */,
CD8B60B4263819790055CB3F /* NotificationsViewController.swift in Sources */,
CE8805D3263AEEE6003C53B7 /* UIDevice+Convenience.swift in Sources */,
CEC5270025E7BACB00DA58A5 /* WdtLocation.swift in Sources */,
CE8962A726175DF500CA274A /* _CoreLocation.swift in Sources */,
CD67617026259D220079D273 /* RadarMapLayersController.swift in Sources */,
......
......@@ -15,3 +15,10 @@ let kAdMoPubInitializationAdUnitId = "05bff78d4a4245bd98ff6b595c134889"
let kOLAppMetricsKey: String = "OLAppMetricsKey"
//MARK: - InApp
let kInAppOneWeatherProId = "com.onelouder.oneweather.inapp1"
let ONE_WEATHER_ABOUT_US_URL = "https://1weatherapp.com/"
let ONE_WEATHER_PRIVACY_URL = "https://1weatherapp.com/privacy"
let ONE_WEATHER_PRIVACY_OPTOUT_URL = "https://1weatherapp.com/privacy#opt-out"
let ONE_WEATHER_FAQ_URL = "https://support.onelouder.com/hc/en-us/sections/201336846"
let ONE_WEATHER_URL = "https://pinsightmedia.com/solutions/onelouder"
let ONE_WEATHER_LICENSES_URL = "https://onelouder-1weather.s3.amazonaws.com/attribution.html"
//
// UIDevice+Convenience.swift
// 1Weather
//
// Created by Demid Merzlyakov on 29.04.2021.
//
import UIKit
public extension UIDevice {
var modelName: String {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
return identifier
}
}
......@@ -80,8 +80,11 @@ public class PushNotificationsManager: NSObject {
updateNwsSubscriptions(with: newFipsList, currentFipsCode: selectedLocation?.fipsCode)
}
var lastKnownPushToken: String?
public func set(pushToken: Data) {
let tokenString = pushToken.map { String(format: "%02.2hhx", $0) }.joined()
self.lastKnownPushToken = tokenString
log.info("Got new APNS token: \(tokenString)")
MoEngage.sharedInstance().setPushToken(pushToken)
}
......@@ -89,7 +92,7 @@ public class PushNotificationsManager: NSObject {
extension PushNotificationsManager: ConfigManagerDelegate {
public func dataUpdated(by configManager: ConfigManager) {
updateNwsSubscriptions(with: lastSetFIPSList)
updateNwsSubscriptions(with: lastSetFIPSList, currentFipsCode: lastSetFIPSCode)
}
}
......
{
"images" : [
{
"filename" : "group.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
......@@ -14,6 +14,7 @@
"general.ok" = "Ok";
"general.cancel" = "Cancel";
"general.continue" = "Continue";
"general.copy" = "Copy";
//Alert
"today.alert.infoTemplate.oneAlert" = "#ALERT_DESCRIPTION";
......@@ -183,7 +184,13 @@
"menu.help" = "Help";
"menu.faq" = "FAQ's";
"menu.privacy" = "Privacy Policy";
"menu.deviceId" = "Device Identifier";
"menu.version" = "version";
"menu.deviceId.notAvailable.title" = "Identifier not available";
"menu.deviceId.notAvailable.text" = "Identifier for verndor is empty";
"menu.deviceId.title" = "Device Identifier";
"menu.deviceId.text" = "Your device identifier is: ";
"menu.help.unableToSendEmail.text" = "Device is unable to send email.";
//Settings
"settings.theme.automatic" = "Automatic";
......
......@@ -15,6 +15,7 @@ public enum MenuRow {
case help
case faq
case privacy
case deviceId
var image: UIImage? {
switch self {
......@@ -32,6 +33,8 @@ public enum MenuRow {
return UIImage(named: "menu_faq")
case .privacy:
return UIImage(named: "menu_privacyPolicy")
case .deviceId:
return UIImage(named: "menu_device_id")
}
}
......@@ -51,6 +54,8 @@ public enum MenuRow {
return "menu.faq".localized()
case .privacy:
return "menu.privacy".localized()
case .deviceId:
return "menu.deviceId".localized()
}
}
......@@ -69,6 +74,8 @@ public enum MenuRow {
case .faq:
return []
case .privacy:
return []
case .deviceId:
return [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
}
}
......@@ -88,7 +95,7 @@ class MenuCellFactory<T>: CellFactoryProtocol {
//Private
private let menuViewModel:MenuViewModel
private let sections:[SectionItem] = [SectionItem(type: .info, rows: [.settings]),
SectionItem(type: .settings, rows: [.about, .ad, .rateUs, .help, .faq, .privacy])]
SectionItem(type: .settings, rows: [.about, .ad, .help, .faq, .privacy, .deviceId])]
//Public
public var kSectionHeight:CGFloat {
......
......@@ -6,6 +6,7 @@
//
import UIKit
import SafariServices
class MenuViewController: UIViewController {
//Private
......@@ -111,9 +112,23 @@ extension MenuViewController: UITableViewDelegate {
guard let type = menuCellFactory.cellTypeAt(indexPath: indexPath) else {
return
}
if type == .settings {
switch type {
case .about:
viewModel.viewAboutUs()
case .settings:
coordinator.openSettings()
case .faq:
viewModel.viewFAQ()
case .ad:
viewModel.viewAdChoices()
case .help:
viewModel.showHelp()
case .privacy:
viewModel.viewPrivacyPolicy()
case .deviceId:
viewModel.showDeviceId()
default:
break
}
}
}
......@@ -131,4 +146,15 @@ extension MenuViewController: MenuViewModelDelegate {
func viewControllerForPresentation() -> UIViewController {
return self
}
func presentWebView(url urlString: String) {
if let url = URL(string: urlString) {
let svc = SFSafariViewController(url: url)
// svc.preferredBarTintColor = ThemeManager.Colors.primaryBackground
// svc.modalPresentationCapturesStatusBarAppearance = false
// svc.setNeedsStatusBarAppearanceUpdate()
self.present(svc, animated: true, completion: nil)
}
}
}
......@@ -7,13 +7,15 @@
import UIKit
import StoreKit
import MessageUI
import PKHUD
protocol MenuViewModelDelegate: ViewModelDelegate {
func viewControllerForPresentation() -> UIViewController
func presentWebView(url: String)
}
class MenuViewModel: ViewModelProtocol {
class MenuViewModel: NSObject, ViewModelProtocol {
private var proVersionPurchaseInProgress = false
private let log = Logger(componentName: "MenuViewModel")
private var upgradeAlert: UIAlertController?
......@@ -57,6 +59,41 @@ class MenuViewModel: ViewModelProtocol {
}
}
public func viewAboutUs() {
self.delegate?.presentWebView(url: ONE_WEATHER_ABOUT_US_URL)
}
public func viewAdChoices() {
self.delegate?.presentWebView(url: ONE_WEATHER_PRIVACY_OPTOUT_URL)
}
public func viewFAQ() {
self.delegate?.presentWebView(url: ONE_WEATHER_FAQ_URL)
}
public func viewPrivacyPolicy() {
self.delegate?.presentWebView(url: ONE_WEATHER_PRIVACY_URL)
}
public func showDeviceId() {
guard let identifier = UIDevice.current.identifierForVendor else {
showAlert("menu.deviceId.notAvailable.title".localized(), message: "menu.deviceId.notAvailable.text".localized())
return
}
let alert = UIAlertController(title: "menu.deviceId.title".localized(),
message: "menu.deviceId.text".localized() + "\(identifier.uuidString)",
preferredStyle: .alert)
let copyAction = UIAlertAction(title: "general.copy".localized(), style: .default) { (_) in
UIPasteboard.general.string = identifier.uuidString
}
alert.addAction(copyAction)
alert.addAction(.init(title: "general.cancel".localized(), style: .cancel))
self.delegate?.viewControllerForPresentation().present(alert, animated: true)
}
private let kOLAppMetricsCountKey: String = "count"
private let kOLAppMetricsDateKey: String = "date"
......@@ -83,6 +120,101 @@ class MenuViewModel: ViewModelProtocol {
}
}
// MARK: - Help section
extension MenuViewModel {
private func helpRequestBodyString() -> String {
var str = String()
str.append("Weather Alerts Enabled: \(ConfigManager.shared.config.nwsAlertsViaMoEngageEnabled)\n")
let isRegistered = UIApplication.shared.isRegisteredForRemoteNotifications
str.append("Push Enabled: \(isRegistered)\n")
let locs = LocationManager.shared.locations
for loc in locs {
let myLoc = loc.deviceLocation ? "MyLocation: " : ""
let alertStr = " FIPS \(loc.fipsCode ?? "no")"
str.append("\(myLoc)")
str.append(loc.nameForDisplay)
str.append(" (\((loc.nickname ?? loc.cityName) ?? ""))")
if let coordinates = loc.coordinates {
str.append(String(format: " @%.5f,%.5f", coordinates.latitude, coordinates.longitude))
}
else {
str.append(" no coordinates")
}
str.append(alertStr)
str.append("\n")
}
str.append("\n--add your comments below--".localized)
return str
}
public func showHelp() {
if !MFMailComposeViewController.canSendMail() {
let alertView = UIAlertController(title: nil, message: "menu.help.unableToSendEmail.text".localized(), preferredStyle: .alert)
alertView.addAction(UIAlertAction(title: "general.ok".localized(), style: .default, handler: nil))
self.viewControllerForPresentation().present(alertView, animated: true, completion: nil)
return
}
var emailSubject = ""
let emailBody = helpRequestBodyString()
var emailRecipients = [String]()
var deviceToken = ""
emailSubject = "1Weather iOS Support Request"
emailRecipients = [ "oneweather_ios@onelouder.zendesk.com" ]
#if DEBUG
//TODO: REMOVE THIS'
emailRecipients = [ "rezonpk@yandex.ru" ]
#warning("THIS IS A DEBUG-ONLY PIECE OF CODE! Not even temporary! Remove before making a production build.")
#else
#error("THIS IS A DEBUG-ONLY PIECE OF CODE! Not even temporary! Remove before making a production build.")
#endif
if let lastUsedToken = PushNotificationsManager.shared.lastKnownPushToken {
deviceToken = "\nPush Token: \(lastUsedToken)"
}
let deviceName = UIDevice.current.modelName
let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")!
let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion")!
let systemVersion = UIDevice.current.systemVersion
let isPro = isAppPro() ? "Yes" : "No"
let installedDate = "Unknown"
let deviceInfo = "Version: \(version)-\(build)\nDevice: \(deviceName)\nOS: \(systemVersion)\nPro: \(isPro) \nInstalled: \(installedDate) \(deviceToken)"
let mc: MFMailComposeViewController = MFMailComposeViewController()
mc.mailComposeDelegate = self
mc.modalPresentationStyle = .formSheet
mc.setSubject(emailSubject)
mc.setMessageBody("\(deviceInfo) \n\n\(emailBody)", isHTML: false)
mc.setToRecipients(emailRecipients)
self.viewControllerForPresentation().present(mc, animated: true, completion: nil)
}
}
extension MenuViewModel: MFMailComposeViewControllerDelegate {
public func mailComposeController(_ controller:MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error:Error?) {
switch result.rawValue {
case MFMailComposeResult.cancelled.rawValue:
log.debug("Mail cancelled")
case MFMailComposeResult.saved.rawValue:
log.debug("Mail saved")
case MFMailComposeResult.sent.rawValue:
log.info("Mail sent")
case MFMailComposeResult.failed.rawValue:
log.error("Mail sent failure: \(error!.localizedDescription)")
default:
break
}
viewControllerForPresentation().dismiss(animated: true, completion: nil)
}
}
extension MenuViewModel: OLInAppStoreManagerDelegate {
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, purchaseCompletedForProductId productId: String) {
onMain {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment