From 6c260f942f3f8ef0b9f5965fed55d05cf8814127 Mon Sep 17 00:00:00 2001 From: Marcus Kida Date: Wed, 28 Dec 2022 11:52:44 +0100 Subject: [PATCH] feat: Implement abbreviated status counts --- .../Sources/MastodonExtension/Int.swift | 31 +++++++++++ .../View/Control/ActionToolbarContainer.swift | 3 +- .../MastodonExtensionTests/IntTests.swift | 53 +++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 MastodonSDK/Sources/MastodonExtension/Int.swift create mode 100644 MastodonSDK/Tests/MastodonExtensionTests/IntTests.swift diff --git a/MastodonSDK/Sources/MastodonExtension/Int.swift b/MastodonSDK/Sources/MastodonExtension/Int.swift new file mode 100644 index 000000000..e9c5ceb1e --- /dev/null +++ b/MastodonSDK/Sources/MastodonExtension/Int.swift @@ -0,0 +1,31 @@ +// +// Int.swift +// +// +// Created by Marcus Kida on 28.12.22. +// + +import Foundation + +public extension Int { + func asAbbreviatedCountString() -> String { + switch self { + case ..<1_000: + return String(format: "%d", locale: Locale.current, self) + case 1_000 ..< 999_999: + return String(format: "%.1fK", locale: Locale.current, Double(self) / 1_000) + .sanitizedAbbreviatedCountString(for: "K") + default: + return String(format: "%.1fM", locale: Locale.current, Double(self) / 1_000_000) + .sanitizedAbbreviatedCountString(for: "M") + } + } +} + +fileprivate extension String { + func sanitizedAbbreviatedCountString(for value: String) -> String { + [".0", ",0", "٫٠"].reduce(self) { res, acc in + return res.replacingOccurrences(of: "\(acc)\(value)", with: value) + } + } +} diff --git a/MastodonSDK/Sources/MastodonUI/View/Control/ActionToolbarContainer.swift b/MastodonSDK/Sources/MastodonUI/View/Control/ActionToolbarContainer.swift index 73695b782..ccb59157a 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Control/ActionToolbarContainer.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Control/ActionToolbarContainer.swift @@ -9,6 +9,7 @@ import os.log import UIKit import MastodonAsset import MastodonLocalization +import MastodonExtension public protocol ActionToolbarContainerDelegate: AnyObject { func actionToolbarContainer(_ actionToolbarContainer: ActionToolbarContainer, buttonDidPressed button: UIButton, action: ActionToolbarContainer.Action) @@ -283,7 +284,7 @@ extension ActionToolbarContainer { extension ActionToolbarContainer { private static func title(from number: Int?) -> String { guard let number = number, number > 0 else { return "" } - return String(number) + return number.asAbbreviatedCountString() } } diff --git a/MastodonSDK/Tests/MastodonExtensionTests/IntTests.swift b/MastodonSDK/Tests/MastodonExtensionTests/IntTests.swift new file mode 100644 index 000000000..ec0d045b2 --- /dev/null +++ b/MastodonSDK/Tests/MastodonExtensionTests/IntTests.swift @@ -0,0 +1,53 @@ +// +// IntTests.swift +// +// +// Created by Marcus Kida on 28.12.22. +// + +import XCTest +@testable import MastodonSDK + +class IntFriendlyCountTests: XCTestCase { + func testFriendlyCount_for_1000() { + let input = 1_000 + let expectedOutput = "1K" + + XCTAssertEqual(expectedOutput, input.asAbbreviatedCountString()) + } + + func testFriendlyCount_for_1200() { + let input = 1_200 + let expectedOutput = "1.2K" + + XCTAssertEqual(expectedOutput, input.asAbbreviatedCountString()) + } + + func testFriendlyCount_for_50000() { + let input = 50_000 + let expectedOutput = "50K" + + XCTAssertEqual(expectedOutput, input.asAbbreviatedCountString()) + } + + func testFriendlyCount_for_70666() { + let input = 70_666 + let expectedOutput = "70.7K" + + XCTAssertEqual(expectedOutput, input.asAbbreviatedCountString()) + } + + func testFriendlyCount_for_1M() { + let input = 1_000_000 + let expectedOutput = "1M" + + XCTAssertEqual(expectedOutput, input.asAbbreviatedCountString()) + } + + func testFriendlyCount_for_1dot5M() { + let input = 1_499_000 + let expectedOutput = "1.5M" + + XCTAssertEqual(expectedOutput, input.asAbbreviatedCountString()) + } +}