Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add expiration label to wireless users profile screen (#1848)
* Add WirelessExpirationTimeFormatter * Add expiration label to wireless users profile screen
- Loading branch information
Showing
6 changed files
with
220 additions
and
3 deletions.
There are no files selected for viewing
114 changes: 114 additions & 0 deletions
114
Wire-iOS Tests/WirelessExpirationTimeFormatterTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// | ||
// Wire | ||
// Copyright (C) 2018 Wire Swiss GmbH | ||
// | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see http://www.gnu.org/licenses/. | ||
// | ||
|
||
import XCTest | ||
@testable import Wire | ||
|
||
class WirelessExpirationTimeFormatterTests: XCTestCase { | ||
|
||
func testExpirationTimeFormatting_LargerThan2Hours() { | ||
assert(remainingTime: 12_000, expected: "4h left") | ||
} | ||
|
||
func testExpirationTimeFormatting_2Hours() { | ||
assert(remainingTime: 7_200, expected: "3h left") | ||
} | ||
|
||
func testExpirationTimeFormatting_91Minutes() { | ||
assert(remainingTime: 5_460, expected: "2h left") | ||
} | ||
|
||
func testExpirationTimeFormatting_90Minutes() { | ||
assert(remainingTime: 5_400, expected: "1.5h left") | ||
} | ||
|
||
func testExpirationTimeFormatting_89Minutes() { | ||
assert(remainingTime: 5_340, expected: "1.5h left") | ||
} | ||
|
||
func testExpirationTimeFormatting_61Minutes() { | ||
assert(remainingTime: 3_660, expected: "1.5h left") | ||
} | ||
|
||
func testExpirationTimeFormatting_60Minutes() { | ||
assert(remainingTime: 3_600, expected: "1h left") | ||
} | ||
|
||
func testExpirationTimeFormatting_59Minutes() { | ||
assert(remainingTime: 3_540, expected: "1h left") | ||
} | ||
|
||
func testExpirationTimeFormatting_46Minutes() { | ||
assert(remainingTime: 2_760, expected: "1h left") | ||
} | ||
|
||
func testExpirationTimeFormatting_45Minutes() { | ||
assert(remainingTime: 2_700, expected: "1h left") | ||
} | ||
|
||
func testExpirationTimeFormatting_44Minutes() { | ||
assert(remainingTime: 2_640, expected: "Less than 45m left") | ||
} | ||
|
||
func testExpirationTimeFormatting_31Minutes() { | ||
assert(remainingTime: 1_860, expected: "Less than 45m left") | ||
} | ||
|
||
func testExpirationTimeFormatting_30Minutes() { | ||
assert(remainingTime: 1_800, expected: "Less than 45m left") | ||
} | ||
|
||
func testExpirationTimeFormatting_29Minutes() { | ||
assert(remainingTime: 1_740, expected: "Less than 30m left") | ||
} | ||
|
||
func testExpirationTimeFormatting_16Minutes() { | ||
assert(remainingTime: 960, expected: "Less than 30m left") | ||
} | ||
|
||
func testExpirationTimeFormatting_15Minutes() { | ||
assert(remainingTime: 900, expected: "Less than 30m left") | ||
} | ||
|
||
func testExpirationTimeFormatting_14Minutes() { | ||
assert(remainingTime: 840, expected: "Less than 15m left") | ||
} | ||
|
||
func testExpirationTimeFormatting_5Minutes() { | ||
assert(remainingTime: 300, expected: "Less than 15m left") | ||
} | ||
|
||
func testExpirationTimeFormatting_1Minute() { | ||
assert(remainingTime: 60, expected: "Less than 15m left") | ||
} | ||
|
||
func testExpirationTimeFormatting_0Minutes() { | ||
assert(remainingTime: 0, expected: nil) | ||
} | ||
|
||
func testExpirationTimeFormatting_NegativeValue() { | ||
assert(remainingTime: -10, expected: nil) | ||
} | ||
|
||
// MARK: - Helper | ||
|
||
private func assert(remainingTime: TimeInterval, expected: String?, file: StaticString = #file, line: UInt = #line) { | ||
let result = WirelessExpirationTimeFormatter.shared.string(for: remainingTime) | ||
XCTAssertEqual(result, expected, file: file, line: line) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
Wire-iOS/Sources/Helpers/syncengine/ZMUser+ExpirationTimeFormatting.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
//// | ||
// Wire | ||
// Copyright (C) 2018 Wire Swiss GmbH | ||
// | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see http://www.gnu.org/licenses/. | ||
// | ||
|
||
import Foundation | ||
|
||
fileprivate extension TimeInterval { | ||
var hours: Double { | ||
return self / 3600 | ||
} | ||
|
||
var minutes: Double { | ||
return self / 60 | ||
} | ||
} | ||
|
||
final class WirelessExpirationTimeFormatter { | ||
static let shared = WirelessExpirationTimeFormatter() | ||
private let numberFormatter: NumberFormatter = { | ||
let formatter = NumberFormatter() | ||
formatter.maximumFractionDigits = 1 | ||
return formatter | ||
}() | ||
|
||
func string(for user: ZMUser) -> String? { | ||
return string(for: user.expiresAfter) | ||
} | ||
|
||
func string(for interval: TimeInterval) -> String? { | ||
guard interval > 0 else { return nil } | ||
let (hoursLeft, minutesLeft) = (interval.hours, interval.minutes) | ||
guard hoursLeft < 2 else { return localizedHours(floor(hoursLeft) + 1) } | ||
|
||
if hoursLeft > 1 { | ||
let extraMinutes = minutesLeft - 60 | ||
return localizedHours(extraMinutes > 30 ? 2 : 1.5) | ||
} | ||
|
||
switch minutesLeft { | ||
case 45...Double.greatestFiniteMagnitude: return localizedHours(1) | ||
case 30..<45: return localizedMinutes(45) | ||
case 15..<30: return localizedMinutes(30) | ||
default: return localizedMinutes(15) | ||
} | ||
} | ||
|
||
private func localizedMinutes(_ minutes: Double) -> String { | ||
return "guest_room.expiration.less_than_minutes_left".localized(args: String(format: "%.0f", minutes)) | ||
} | ||
|
||
private func localizedHours(_ hours: Double) -> String { | ||
let localizedHoursString = numberFormatter.string(from: NSNumber(value: hours)) ?? "\(hours)" | ||
return "guest_room.expiration.hours_left".localized(args: localizedHoursString) | ||
} | ||
} | ||
|
||
extension ZMUser { | ||
@objc var expirationDisplayString: String? { | ||
return WirelessExpirationTimeFormatter.shared.string(for: self) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters