Skip to content

Commit

Permalink
"Nicegram plus" release 1.1.9
Browse files Browse the repository at this point in the history
  • Loading branch information
denis15yo committed Jan 31, 2023
1 parent b5e85a1 commit 0839b83
Show file tree
Hide file tree
Showing 30 changed files with 502 additions and 198 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ public class AssistantBuilderImpl: AssistantBuilder {
),
getReferralLinkUseCase: GetReferralLinkUseCaseImpl(),
initiateLoginWithTelegramUseCase: appContext.resolveInitiateLoginWithTelegramUseCase(),
getLotteryDataUseCase: appContext.resolveGetLotteryDataUseCase(),
eventsLogger: LoggersFactory().createDefaultEventsLogger()
)
interactor.output = presenter
Expand Down
31 changes: 10 additions & 21 deletions Nicegram/NGAssistant/Sources/Assistant/AssistantInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ protocol AssistantInteractorOutput {

@available(iOS 13.0, *)
class AssistantInteractor: AssistantInteractorInput {

private struct Constants {
static let lotteryJackpot = Money(amount: 250000000, currency: .usd)
}

var output: AssistantInteractorOutput!
var router: AssistantRouterInput!

Expand All @@ -37,7 +42,6 @@ class AssistantInteractor: AssistantInteractorInput {
private let getSpecialOfferUseCase: GetSpecialOfferUseCase
private let getReferralLinkUseCase: GetReferralLinkUseCase
private let initiateLoginWithTelegramUseCase: InitiateLoginWithTelegramUseCase
private let getLotteryDataUseCase: GetLotteryDataUseCase
private let eventsLogger: EventsLogger

private var deeplink: Deeplink?
Expand All @@ -46,23 +50,22 @@ class AssistantInteractor: AssistantInteractorInput {
private var cancellables = Set<AnyCancellable>()


init(deeplink: Deeplink?, esimAuth: EsimAuth, userEsimsRepository: UserEsimsRepository, getCurrentUserUseCase: GetCurrentUserUseCase, getSpecialOfferUseCase: GetSpecialOfferUseCase, getReferralLinkUseCase: GetReferralLinkUseCase, initiateLoginWithTelegramUseCase: InitiateLoginWithTelegramUseCase, getLotteryDataUseCase: GetLotteryDataUseCase, eventsLogger: EventsLogger) {
init(deeplink: Deeplink?, esimAuth: EsimAuth, userEsimsRepository: UserEsimsRepository, getCurrentUserUseCase: GetCurrentUserUseCase, getSpecialOfferUseCase: GetSpecialOfferUseCase, getReferralLinkUseCase: GetReferralLinkUseCase, initiateLoginWithTelegramUseCase: InitiateLoginWithTelegramUseCase, eventsLogger: EventsLogger) {
self.deeplink = deeplink
self.esimAuth = esimAuth
self.userEsimsRepository = userEsimsRepository
self.getCurrentUserUseCase = getCurrentUserUseCase
self.getSpecialOfferUseCase = getSpecialOfferUseCase
self.getReferralLinkUseCase = getReferralLinkUseCase
self.initiateLoginWithTelegramUseCase = initiateLoginWithTelegramUseCase
self.getLotteryDataUseCase = getLotteryDataUseCase
self.eventsLogger = eventsLogger
}

func onViewDidLoad() {
output.handleViewDidLoad()
trySignInWithTelegram()
fetchSpecialOffer()
subscribeToLotteryChange()
displayLotteryIfNeeded()
}

func onViewDidAppear() {
Expand Down Expand Up @@ -195,23 +198,9 @@ private extension AssistantInteractor {
}
}

func subscribeToLotteryChange() {
guard !hideLottery else { return }
getLotteryDataUseCase.lotteryDataPublisher()
.receive(on: DispatchQueue.main)
.sink { [weak self] lotteryData in
guard let self else { return }

if let lotteryData {
self.output.presentLottery(jackpot: lotteryData.currentDraw.jackpot)
self.output.presentLottery(true)

AppCache.wasLotteryShown = true
} else {
self.output.presentLottery(false)
}
}
.store(in: &cancellables)
func displayLotteryIfNeeded() {
self.output.presentLottery(jackpot: Constants.lotteryJackpot)
self.output.presentLottery(!hideLottery)
}

func tryHandleDeeplink() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ final class AssistantViewController: UIViewController {
make.height.equalTo(0.66)
}

lotteryContainerView.isHidden = true
lotteryContainerView.addSubview(lotteryStack)
lotteryStack.snp.makeConstraints { make in
make.edges.equalToSuperview()
Expand Down
18 changes: 18 additions & 0 deletions Nicegram/NGCopyProtectedContent/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")

swift_library(
name = "NGCopyProtectedContent",
module_name = "NGCopyProtectedContent",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
"//Nicegram/NGCore:NGCore",
"//Nicegram/NGData:NGData",
"//Nicegram/NGRemoteConfig:NGRemoteConfig",
"//Nicegram/NGSubscription:NGSubscription",
],
visibility = [
"//visibility:public",
],
)
56 changes: 56 additions & 0 deletions Nicegram/NGCopyProtectedContent/Sources/CopyProtectedContent.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Foundation
import NGCore
import NGData
import NGRemoteConfig
import NGSubscription
import Postbox
import TelegramPresentationData
import UIKit

// MARK: - Logic

public func shouldShowInterfaceForCopyContent(message: Message) -> Bool {
let isCopyProtectionEnabled = message.isCopyProtected()
return !isCopyProtectionEnabled || allowCopyProtectedContent
}

public func shouldShowInterfaceForForwardAsCopy(message: Message) -> Bool {
let isCopyProtectionEnabled = message.isCopyProtected()

if isCopyProtectionEnabled {
let hasMedia = !message.media.isEmpty
return !hasMedia && shouldShowInterfaceForCopyContent(message: message)
} else {
return true
}
}

public func shouldSubscribeToCopyContent(message: Message) -> Bool {
let isCopyProtectionEnabled = message.isCopyProtected()

if isCopyProtectionEnabled {
return !isPremium() && !getBypassCopyProtection()
} else {
return false
}
}

public func routeToNicegramPremiumForCopyContent(presentationData: PresentationData) {
let c = SubscriptionBuilderImpl(presentationData: presentationData).build()
c.modalPresentationStyle = .fullScreen
if let topViewController = UIApplication.topViewController {
topViewController.present(c, animated: true)
}
}

// MARK: - Bypass setting (Secret Menu)

private let bypassCopyProtectionKey = "ng:bypassCopyProtection"

public func getBypassCopyProtection() -> Bool {
return UserDefaults.standard.bool(forKey: bypassCopyProtectionKey)
}

public func setBypassCopyProtection(_ value: Bool) {
UserDefaults.standard.set(value, forKey: bypassCopyProtectionKey)
}
89 changes: 76 additions & 13 deletions Nicegram/NGCoreUI/Sources/LoadingView/LoadingView.swift
Original file line number Diff line number Diff line change
@@ -1,37 +1,100 @@
import NGLoadingIndicator
import EsimUI
import SnapKit
import UIKit
import Lottie

public class LoadingView: UIView {

// MARK: - UI Elements

private let activityIndicator: AnimationView
private let dimmView = UIView()

// MARK: - Public Properties

public var isLoading: Bool = false {
didSet {
if isLoading, !isLoadingAnimationInFlight {
loadingInicator.startAnimating(on: containerView)
isLoadingAnimationInFlight = true
} else if !isLoading, isLoadingAnimationInFlight {
loadingInicator.stopAnimating()
isLoadingAnimationInFlight = false
if isLoading {
start()
} else {
stop()
}
}
}

public var hidesWhenStopped: Bool = true
public var dimmBackground: Bool = false

// MARK: - Logic

private let loadingInicator = NGLoadingIndicator()
private var isLoadingAnimationInFlight: Bool = false
private weak var containerView: UIView?
private var isAnimationInFlight: Bool = false

// MARK: - Lifecycle

public init(containerView: UIView?) {
self.containerView = containerView
public override init(frame: CGRect) {
self.activityIndicator = AnimationView(name: "NicegramLoader")

super.init(frame: frame)

isHidden = true

activityIndicator.loopMode = .loop

super.init(frame: .zero)
dimmView.backgroundColor = .black.withAlphaComponent(0.5)

addSubview(dimmView)
dimmView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}

addSubview(activityIndicator)
activityIndicator.snp.makeConstraints { make in
make.center.equalTo(safeAreaLayoutGuide)
make.leading.top.greaterThanOrEqualToSuperview()
make.height.equalTo(activityIndicator.snp.width)
make.width.equalTo(80).priority(999)
}
}

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

// MARK: - Privtae Functions

private func start() {
guard !isAnimationInFlight else { return }
isAnimationInFlight = true

isHidden = false
dimmView.isHidden = !dimmBackground
UIView.animate(withDuration: 0.2) { [weak self] in
guard let self else { return }
self.activityIndicator.alpha = 1
} completion: { [weak self] _ in
guard let self else { return }
self.activityIndicator.play()
}
}

private func stop() {
activityIndicator.stop()
if hidesWhenStopped {
isHidden = true
}

isAnimationInFlight = false
}
}

public extension PlaceholderableView {
func showLoading() {
let view = LoadingView()
view.isLoading = true
self.showPlaceholder(view)
}

func hideLoading() {
self.hidePlaceholder()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import NGLocalization
import UIKit

public extension PlaceholderState {
static func retry(error: Error, onTap: @escaping () -> Void) -> PlaceholderState {
return retry(message: error.localizedDescription, onTap: onTap)
}

static func retry(message: String?, onTap: @escaping () -> Void) -> PlaceholderState {
return PlaceholderState(
title: nil,
image: nil,
description: mapErrorDescription(message),
buttonState: .init(
title: ngLocalized("Nicegram.Alert.TryAgain").uppercased(),
image: UIImage(named: "ng.refresh"),
style: .small,
onTap: onTap
)
)
}
}
34 changes: 34 additions & 0 deletions Nicegram/NGCoreUI/Sources/Placeholder/PlaceholderState.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import UIKit

public struct PlaceholderState {
public let title: String?
public let image: UIImage?
public let description: String
public let buttonState: ButtonState?

public init(title: String?, image: UIImage?, description: String, buttonState: ButtonState?) {
self.title = title
self.image = image
self.description = description
self.buttonState = buttonState
}

public struct ButtonState {
public let title: String
public let image: UIImage?
public let style: Style
public let onTap: () -> Void

public init(title: String, image: UIImage? = nil, style: Style = .normal, onTap: @escaping () -> Void) {
self.title = title
self.image = image
self.style = style
self.onTap = onTap
}

public enum Style {
case normal
case small
}
}
}
25 changes: 25 additions & 0 deletions Nicegram/NGCoreUI/Sources/Placeholder/PlaceholderableView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import NGCustomViews
import SnapKit
import UIKit

public typealias PlaceholderableView = NGCustomViews.PlaceholderableView

public extension PlaceholderableView {
func showPlaceholder(_ state: PlaceholderState) {
let view = DefaultPlaceholderView()

switch state.buttonState?.style {
case .small:
view.configureWithSmallButton()
case .normal, .none:
break
}

view.display(image: state.image, description: state.description, buttonTitle: state.buttonState?.title, buttonImage: state.buttonState?.image)

view.onButtonClick = state.buttonState?.onTap

self.showPlaceholder(view)
}
}

19 changes: 18 additions & 1 deletion Nicegram/NGCustomViews/Sources/DefaultPlaceholderView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ open class DefaultPlaceholderView: UIView {
set { stack.spacing = newValue }
}

var onButtonClick: (() -> ())? {
public var onButtonClick: (() -> ())? {
get { button.touchUpInside }
set { button.touchUpInside = newValue }
}
Expand Down Expand Up @@ -83,3 +83,20 @@ open class DefaultPlaceholderView: UIView {
c(button)
}
}

public extension DefaultPlaceholderView {
func configureWithSmallButton() {
self.alignment = .center
self.spacing = 24
self.configureButton { button in
button.backgroundColor = .ngLightOrange
button.layer.cornerRadius = 8
button.insets = UIEdgeInsets(top: 5, left: 8, bottom: 5, right: 8)
button.spacing = 6

button.configureTitleLabel { label in
label.font = .systemFont(ofSize: 12, weight: .semibold)
}
}
}
}
Loading

0 comments on commit 0839b83

Please sign in to comment.