From 6744f526b3e84df0c54ae1999314e89b33290ccf Mon Sep 17 00:00:00 2001 From: Ermat Date: Fri, 4 Aug 2023 15:20:57 +0600 Subject: [PATCH] Change rating scale to overall score in CoinAnalytics module --- .../Coin/Analytics/CoinAnalyticsModule.swift | 11 +- ...inAnalyticsRatingScaleViewController.swift | 24 ++- .../CoinAnalyticsViewController.swift | 174 +++++++++++++++--- .../Modules/Wallet/WalletViewController.swift | 2 +- .../en.lproj/Localizable.strings | 20 +- 5 files changed, 190 insertions(+), 41 deletions(-) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsModule.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsModule.swift index 5e6725c062..b556cea1d3 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsModule.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsModule.swift @@ -37,16 +37,7 @@ extension CoinAnalyticsModule { case poor var title: String { - "coin_analytics.rating_scale.\(rawValue)".localized - } - - var percents: String { - switch self { - case .excellent: return "25%" - case .good: return "25%-50%" - case .fair: return "50%-75%" - case .poor: return "75%-100%" - } + "coin_analytics.overall_score.\(rawValue)".localized } var image: UIImage? { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsRatingScaleViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsRatingScaleViewController.swift index 83b381d770..1afd51e5a2 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsRatingScaleViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsRatingScaleViewController.swift @@ -5,8 +5,24 @@ import SnapKit import ComponentKit class CoinAnalyticsRatingScaleViewController: ThemeViewController { + private let _title: String + private let _description: String + private let scores: [CoinAnalyticsModule.Rating: String] + private let tableView = SectionsTableView(style: .grouped) + init(title: String, description: String, scores: [CoinAnalyticsModule.Rating: String]) { + _title = title + _description = description + self.scores = scores + + super.init() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override func viewDidLoad() { super.viewDidLoad() @@ -24,6 +40,7 @@ class CoinAnalyticsRatingScaleViewController: ThemeViewController { tableView.sectionDataSource = self tableView.registerCell(forClass: MarkdownHeader1Cell.self) + tableView.registerCell(forClass: MarkdownHeader3Cell.self) tableView.registerCell(forClass: MarkdownTextCell.self) tableView.buildSections() @@ -43,8 +60,9 @@ extension CoinAnalyticsRatingScaleViewController: SectionsDataSource { id: "info", footerState: .margin(height: .margin12), rows: [ - MarkdownViewController.header1Row(id: "header", string: "coin_analytics.rating_scale".localized), - MarkdownViewController.textRow(id: "description", string: "coin_analytics.rating_scale.description".localized) + MarkdownViewController.header1Row(id: "header", string: "coin_analytics.overall_score".localized), + MarkdownViewController.header3Row(id: "sub-header", string: _title), + MarkdownViewController.textRow(id: "description", string: _description) ] ), Section( @@ -59,7 +77,7 @@ extension CoinAnalyticsRatingScaleViewController: SectionsDataSource { .imageElement(image: .local(rating.image), size: .image24), .margin8, .textElement(text: .subhead1(rating.title.uppercased(), color: rating.color)), - .textElement(text: .subhead1(rating.percents.uppercased(), color: rating.color)), + .textElement(text: .subhead1(scores[rating], color: rating.color)), ]), tableView: tableView, id: "rating-\(index)", diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsViewController.swift index 978597f376..dbd3641bd3 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/Analytics/CoinAnalyticsViewController.swift @@ -27,6 +27,16 @@ class CoinAnalyticsViewController: ThemeViewController { private var viewItem: CoinAnalyticsViewModel.ViewItem? private var indicatorViewItem: CoinAnalyticsViewModel.IndicatorViewItem? + private let currencyFormatter: NumberFormatter = { + let formatter = NumberFormatter() + formatter.numberStyle = .currency + formatter.maximumFractionDigits = 0 + formatter.minimumFractionDigits = 0 + formatter.currencySymbol = "$" + formatter.internationalCurrencySymbol = "$" + return formatter + }() + init(viewModel: CoinAnalyticsViewModel) { self.viewModel = viewModel @@ -130,6 +140,11 @@ class CoinAnalyticsViewController: ThemeViewController { tableView.reload() } + private func formatUsd(value: Int, number: String) -> String { + let string = currencyFormatter.string(from: value as NSNumber) ?? "" + return number.localized(string) + } + private func openTechnicalIndicatorInfo() { let viewController = InfoModule.viewController(viewItems: [ .header1(text: "coin_analytics.technical_indicators".localized), @@ -232,6 +247,111 @@ class CoinAnalyticsViewController: ThemeViewController { parentNavigationController?.present(viewController, animated: true) } + private func openCexVolumeScoreInfo() { + let viewController = CoinAnalyticsRatingScaleViewController( + title: "coin_analytics.cex_volume".localized, + description: "coin_analytics.overall_score.cex_volume".localized, + scores: [ + .excellent: "> \(formatUsd(value: 10, number: "number.million"))", + .good: "> \(formatUsd(value: 5, number: "number.million"))", + .fair: "> \(formatUsd(value: 1, number: "number.million"))", + .poor: "< \(formatUsd(value: 1, number: "number.million"))", + ] + ) + + parentNavigationController?.present(ThemeNavigationController(rootViewController: viewController), animated: true) + } + + private func openDexVolumeScoreInfo() { + let viewController = CoinAnalyticsRatingScaleViewController( + title: "coin_analytics.dex_volume".localized, + description: "coin_analytics.overall_score.dex_volume".localized, + scores: [ + .excellent: "> \(formatUsd(value: 1, number: "number.million"))", + .good: "> \(formatUsd(value: 500, number: "number.thousand"))", + .fair: "> \(formatUsd(value: 100, number: "number.thousand"))", + .poor: "< \(formatUsd(value: 100, number: "number.thousand"))", + ] + ) + + parentNavigationController?.present(ThemeNavigationController(rootViewController: viewController), animated: true) + } + + private func openDexLiquidityScoreInfo() { + let viewController = CoinAnalyticsRatingScaleViewController( + title: "coin_analytics.dex_liquidity".localized, + description: "coin_analytics.overall_score.dex_liquidity".localized, + scores: [ + .excellent: "> \(formatUsd(value: 2, number: "number.million"))", + .good: "> \(formatUsd(value: 1, number: "number.million"))", + .fair: "> \(formatUsd(value: 500, number: "number.thousand"))", + .poor: "< \(formatUsd(value: 500, number: "number.thousand"))", + ] + ) + + parentNavigationController?.present(ThemeNavigationController(rootViewController: viewController), animated: true) + } + + private func openAddressesScoreInfo() { + let viewController = CoinAnalyticsRatingScaleViewController( + title: "coin_analytics.active_addresses".localized, + description: "coin_analytics.overall_score.active_addresses".localized, + scores: [ + .excellent: "> 500", + .good: "> 200", + .fair: "> 100", + .poor: "< 100", + ] + ) + + parentNavigationController?.present(ThemeNavigationController(rootViewController: viewController), animated: true) + } + + private func openTvlScoreInfo() { + let viewController = CoinAnalyticsRatingScaleViewController( + title: "coin_analytics.project_tvl".localized, + description: "coin_analytics.overall_score.project_tvl".localized, + scores: [ + .excellent: "> \(formatUsd(value: 200, number: "number.million"))", + .good: "> \(formatUsd(value: 100, number: "number.million"))", + .fair: "> \(formatUsd(value: 50, number: "number.million"))", + .poor: "< \(formatUsd(value: 50, number: "number.million"))", + ] + ) + + parentNavigationController?.present(ThemeNavigationController(rootViewController: viewController), animated: true) + } + + private func openTransactionCountScoreInfo() { + let viewController = CoinAnalyticsRatingScaleViewController( + title: "coin_analytics.transaction_count".localized, + description: "coin_analytics.overall_score.transaction_count".localized, + scores: [ + .excellent: "> \("number.thousand".localized("10"))", + .good: "> \("number.thousand".localized("5"))", + .fair: "> \("number.thousand".localized("1"))", + .poor: "< \("number.thousand".localized("1"))", + ] + ) + + parentNavigationController?.present(ThemeNavigationController(rootViewController: viewController), animated: true) + } + + private func openHoldersScoreInfo() { + let viewController = CoinAnalyticsRatingScaleViewController( + title: "coin_analytics.holders".localized, + description: "coin_analytics.overall_score.holders".localized, + scores: [ + .excellent: "> \("number.thousand".localized("100"))", + .good: "> \("number.thousand".localized("50"))", + .fair: "> \("number.thousand".localized("30"))", + .poor: "< \("number.thousand".localized("30"))", + ] + ) + + parentNavigationController?.present(ThemeNavigationController(rootViewController: viewController), animated: true) + } + private func openMajorHolders(blockchain: Blockchain) { let viewController = CoinMajorHoldersModule.viewController(coin: viewModel.coin, blockchain: blockchain) parentNavigationController?.present(viewController, animated: true) @@ -267,11 +387,6 @@ class CoinAnalyticsViewController: ThemeViewController { parentNavigationController?.present(viewController, animated: true) } - private func openRatings() { - let viewController = CoinAnalyticsRatingScaleViewController() - parentNavigationController?.present(ThemeNavigationController(rootViewController: viewController), animated: true) - } - private func openRanks(type: CoinRankModule.RankType) { let viewController = CoinRankModule.viewController(type: type) parentNavigationController?.present(viewController, animated: true) @@ -454,9 +569,9 @@ extension CoinAnalyticsViewController: SectionsDataSource { ]) } - private func ratingRow(id: String, rating: Previewable, isFirst: Bool = false, isLast: Bool = false) -> RowProtocol { + private func ratingRow(id: String, rating: Previewable, isFirst: Bool = false, isLast: Bool = false, action: @escaping () -> ()) -> RowProtocol { let titleElements: [CellBuilderNew.CellElement] = [ - .textElement(text: .subhead2("coin_analytics.rating_scale".localized), parameters: .highHugging), + .textElement(text: .subhead2("coin_analytics.overall_score".localized), parameters: .highHugging), .margin8, .imageElement(image: .local(UIImage(named: "circle_information_20")?.withTintColor(.themeGray)), size: .image20) ] @@ -474,9 +589,7 @@ extension CoinAnalyticsViewController: SectionsDataSource { bind: { cell in cell.set(backgroundStyle: .lawrence, isFirst: isFirst, isLast: isLast) }, - action: { [weak self] in - self?.openRatings() - } + action: action ) case .regular(let rating): return CellBuilderNew.row( @@ -493,9 +606,7 @@ extension CoinAnalyticsViewController: SectionsDataSource { bind: { cell in cell.set(backgroundStyle: .lawrence, isFirst: isFirst, isLast: isLast) }, - action: { [weak self] in - self?.openRatings() - } + action: action ) } } @@ -526,7 +637,10 @@ extension CoinAnalyticsViewController: SectionsDataSource { ratingRow( id: "cex-volume-rating", rating: rating, - isLast: rows.count + 1 == itemCount + isLast: rows.count + 1 == itemCount, + action: { [weak self] in + self?.openCexVolumeScoreInfo() + } ) ) } @@ -579,7 +693,10 @@ extension CoinAnalyticsViewController: SectionsDataSource { ratingRow( id: "dex-volume-rating", rating: rating, - isLast: rows.count + 1 == itemCount + isLast: rows.count + 1 == itemCount, + action: { [weak self] in + self?.openDexVolumeScoreInfo() + } ) ) } @@ -632,7 +749,10 @@ extension CoinAnalyticsViewController: SectionsDataSource { ratingRow( id: "dex-liquidity-rating", rating: rating, - isLast: rows.count + 1 == itemCount + isLast: rows.count + 1 == itemCount, + action: { [weak self] in + self?.openDexLiquidityScoreInfo() + } ) ) } @@ -685,7 +805,10 @@ extension CoinAnalyticsViewController: SectionsDataSource { ratingRow( id: "addresses-rating", rating: rating, - isLast: rows.count + 1 == itemCount + isLast: rows.count + 1 == itemCount, + action: { [weak self] in + self?.openAddressesScoreInfo() + } ) ) } @@ -749,7 +872,10 @@ extension CoinAnalyticsViewController: SectionsDataSource { ratingRow( id: "tx-count-rating", rating: rating, - isLast: rows.count + 1 == itemCount + isLast: rows.count + 1 == itemCount, + action: { [weak self] in + self?.openTransactionCountScoreInfo() + } ) ) } @@ -861,7 +987,10 @@ extension CoinAnalyticsViewController: SectionsDataSource { ratingRow( id: "holders-rating", rating: rating, - isLast: false + isLast: false, + action: { [weak self] in + self?.openHoldersScoreInfo() + } ) ) } @@ -925,9 +1054,12 @@ extension CoinAnalyticsViewController: SectionsDataSource { if let rating = viewItem.rating { rows.append( ratingRow( - id: "cex-volume-rating", + id: "tvl-rating", rating: rating, - isLast: rows.count + 1 == itemCount + isLast: rows.count + 1 == itemCount, + action: { [weak self] in + self?.openTvlScoreInfo() + } ) ) } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewController.swift index e335c8d9d8..835afd12f0 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewController.swift @@ -264,7 +264,7 @@ class WalletViewController: ThemeViewController { } private func sync(nftVisible: Bool) { - navigationItem.rightBarButtonItem = nftVisible ? UIBarButtonItem(image: UIImage(named: "nft_24"), style: .plain, target: self, action: #selector(onTapNft)) : nil +// navigationItem.rightBarButtonItem = nftVisible ? UIBarButtonItem(image: UIImage(named: "nft_24"), style: .plain, target: self, action: #selector(onTapNft)) : nil } private func sync(state: WalletViewModel.State) { diff --git a/UnstoppableWallet/UnstoppableWallet/en.lproj/Localizable.strings b/UnstoppableWallet/UnstoppableWallet/en.lproj/Localizable.strings index f77d185fbe..7cc316a3db 100644 --- a/UnstoppableWallet/UnstoppableWallet/en.lproj/Localizable.strings +++ b/UnstoppableWallet/UnstoppableWallet/en.lproj/Localizable.strings @@ -814,12 +814,20 @@ Go to Settings - > %@ and allow access to the camera."; "coin_analytics.last_30d" = "last 30d"; "coin_analytics.current" = "current"; -"coin_analytics.rating_scale" = "Rating Scale"; -"coin_analytics.rating_scale.description" = "The rating scale is derived from the top 250 tokens by market capitalisation and is proportionally adjusted by percentage to obtain the final rating scale."; -"coin_analytics.rating_scale.excellent" = "Excellent"; -"coin_analytics.rating_scale.good" = "Good"; -"coin_analytics.rating_scale.fair" = "Fair"; -"coin_analytics.rating_scale.poor" = "Poor"; + +"coin_analytics.overall_score" = "Overall Score"; +"coin_analytics.overall_score.excellent" = "Excellent"; +"coin_analytics.overall_score.good" = "Good"; +"coin_analytics.overall_score.fair" = "Fair"; +"coin_analytics.overall_score.poor" = "Poor"; +"coin_analytics.overall_score.cex_volume" = "The overall score is based on the average daily trading volume on centralized exchanges over the last 7 days."; +"coin_analytics.overall_score.dex_volume" = "The overall score is based on the average daily trading volume on decentralized exchanges over the last 7 days."; +"coin_analytics.overall_score.dex_liquidity" = "The overall score is based on the total avilable liquidity on decentralized exchanges."; +"coin_analytics.overall_score.active_addresses" = "The overall score is based on the average daily active addresses over the last 7 days."; +"coin_analytics.overall_score.project_tvl" = "The overall score is based on the total value locked (assets under management) on the project represented by the given token."; +"coin_analytics.overall_score.transaction_count" = "The overall score is based on the average daily transaction count over the last 7 days."; +"coin_analytics.overall_score.holders" = "The overall score is based on the total number of addresses holding respective token."; + "coin_analytics.rank" = "Rank"; "coin_analytics.30_day_rank" = "30-Day Rank"; "coin_analytics.30_day_volume" = "30-Day Volume";