UI improvements

This commit is contained in:
Arkadiusz Fal 2021-11-11 22:07:13 +01:00
parent 72d735e962
commit c94687f54e
8 changed files with 44 additions and 43 deletions

View File

@ -2,28 +2,26 @@ import Foundation
extension Int { extension Int {
func formattedAsAbbreviation() -> String { func formattedAsAbbreviation() -> String {
typealias Abbrevation = (threshold: Double, divisor: Double, suffix: String) let num = fabs(Double(self))
let abbreviations: [Abbrevation] = [
(0, 1, ""), (1000.0, 1000.0, "K"),
(999_999.0, 1_000_000.0, "M"), (999_999_999.0, 1_000_000_000.0, "B")
]
let startValue = Double(abs(self)) guard num >= 1000.0 else {
guard let nextAbbreviationIndex = abbreviations.firstIndex(where: { startValue < $0.threshold }) else {
return String(self) return String(self)
} }
let abbreviation = abbreviations[abbreviations.index(before: nextAbbreviationIndex)] let exp = Int(log10(num) / 3.0)
let units = ["K", "M", "B", "T", "X"]
let unit = units[exp - 1]
let formatter = NumberFormatter() let formatter = NumberFormatter()
formatter.positiveSuffix = abbreviation.suffix formatter.positiveSuffix = unit
formatter.negativeSuffix = abbreviation.suffix formatter.negativeSuffix = unit
formatter.allowsFloats = true formatter.allowsFloats = true
formatter.minimumIntegerDigits = 1 formatter.minimumIntegerDigits = 1
formatter.minimumFractionDigits = 0 formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 1 formatter.maximumFractionDigits = 1
return formatter.string(from: NSNumber(value: Double(self) / abbreviation.divisor))! let roundedNum = round(10 * num / pow(1000.0, Double(exp))) / 10
return formatter.string(from: NSNumber(value: roundedNum))!
} }
} }

View File

@ -19,7 +19,7 @@ struct FavoriteItem: Codable, Equatable, Identifiable, Defaults.Serializable {
return "Popular" return "Popular"
case let .trending(country, category): case let .trending(country, category):
let trendingCountry = Country(rawValue: country)! let trendingCountry = Country(rawValue: country)!
let trendingCategory = category.isNil ? nil : TrendingCategory(rawValue: category!)! let trendingCategory = category.isNil ? nil : TrendingCategory(rawValue: category!)
return "\(trendingCountry.flag) \(trendingCountry.id) \(trendingCategory?.name ?? "Trending")" return "\(trendingCountry.flag) \(trendingCountry.id) \(trendingCategory?.name ?? "Trending")"
case let .channel(_, name): case let .channel(_, name):
return name return name

View File

@ -85,11 +85,19 @@ struct Video: Identifiable, Equatable, Hashable {
} }
var likesCount: String? { var likesCount: String? {
likes?.formattedAsAbbreviation() guard likes != -1 else {
return nil
}
return likes?.formattedAsAbbreviation()
} }
var dislikesCount: String? { var dislikesCount: String? {
dislikes?.formattedAsAbbreviation() guard dislikes != -1 else {
return nil
}
return dislikes?.formattedAsAbbreviation()
} }
func thumbnailURL(quality: Thumbnail.Quality) -> URL? { func thumbnailURL(quality: Thumbnail.Quality) -> URL? {

View File

@ -2,32 +2,16 @@ import Defaults
import Foundation import Foundation
extension Defaults.Keys { extension Defaults.Keys {
static let invidiousInstanceID = "default-invidious-instance"
static let pipedInstanceID = "default-piped-instance"
static let privateAccountID = "default-private-invidious-account"
static let instances = Key<[Instance]>("instances", default: [ static let instances = Key<[Instance]>("instances", default: [
.init( .init(
app: .piped, app: .piped,
id: pipedInstanceID, id: "default-piped-instance",
name: "Public", name: "Kavin",
apiURL: "https://pipedapi.kavin.rocks", apiURL: "https://pipedapi.kavin.rocks",
frontendURL: "https://piped.kavin.rocks" frontendURL: "https://piped.kavin.rocks"
),
.init(app: .invidious,
id: invidiousInstanceID,
name: "Private",
apiURL: "https://invidious.home.arekf.net")
])
static let accounts = Key<[Account]>("accounts", default: [
.init(
id: privateAccountID,
instanceID: invidiousInstanceID,
name: "arekf",
url: "https://invidious.home.arekf.net",
sid: "ki55SJbaQmm0bOxUWctGAQLYPQRgk-CXDPw5Dp4oBmI="
) )
]) ])
static let accounts = Key<[Account]>("accounts", default: [])
static let lastAccountID = Key<Account.ID?>("lastAccountID") static let lastAccountID = Key<Account.ID?>("lastAccountID")
static let lastInstanceID = Key<Instance.ID?>("lastInstanceID") static let lastInstanceID = Key<Instance.ID?>("lastInstanceID")
static let lastUsedPlaylistID = Key<Playlist.ID?>("lastPlaylistID") static let lastUsedPlaylistID = Key<Playlist.ID?>("lastPlaylistID")
@ -36,9 +20,8 @@ extension Defaults.Keys {
static let sponsorBlockCategories = Key<Set<String>>("sponsorBlockCategories", default: Set(SponsorBlockAPI.categories)) static let sponsorBlockCategories = Key<Set<String>>("sponsorBlockCategories", default: Set(SponsorBlockAPI.categories))
static let favorites = Key<[FavoriteItem]>("favorites", default: [ static let favorites = Key<[FavoriteItem]>("favorites", default: [
.init(section: .trending("US", nil)), .init(section: .trending("US", "default")),
.init(section: .searchQuery("World Discoveries", "", "", "")), .init(section: .channel("UC-lHJZR3Gqxm24_Vd_AJ5Yw", "PewDiePie")),
.init(section: .searchQuery("Full Body Workout", "", "", "")),
.init(section: .searchQuery("Apple Pie Recipes", "", "", "")) .init(section: .searchQuery("Apple Pie Recipes", "", "", ""))
]) ])

View File

@ -71,7 +71,7 @@ struct FavoriteItemView: View {
private var isVisible: Bool { private var isVisible: Bool {
switch item.section { switch item.section {
case .subscriptions: case .subscriptions:
return accounts.app.supportsSubscriptions return accounts.app.supportsSubscriptions && accounts.signedIn
case .popular: case .popular:
return accounts.app.supportsPopular return accounts.app.supportsPopular
default: default:
@ -93,7 +93,7 @@ struct FavoriteItemView: View {
case let .trending(country, category): case let .trending(country, category):
let trendingCountry = Country(rawValue: country)! let trendingCountry = Country(rawValue: country)!
let trendingCategory = category.isNil ? nil : TrendingCategory(rawValue: category!)! let trendingCategory = category.isNil ? nil : TrendingCategory(rawValue: category!)
return accounts.api.trending(country: trendingCountry, category: trendingCategory) return accounts.api.trending(country: trendingCountry, category: trendingCategory)

View File

@ -33,19 +33,28 @@ struct VerticalCells: View {
} }
var adaptiveItem: [GridItem] { var adaptiveItem: [GridItem] {
[GridItem(.adaptive(minimum: adaptiveGridItemMinimumSize))] [GridItem(.adaptive(minimum: adaptiveGridItemMinimumSize, maximum: adaptiveGridItemMaximumSize))]
} }
var adaptiveGridItemMinimumSize: Double { var adaptiveGridItemMinimumSize: Double {
#if os(iOS) #if os(iOS)
return verticalSizeClass == .regular ? 320 : 800 return verticalSizeClass == .regular ? 320 : 800
#elseif os(tvOS) #elseif os(tvOS)
return 500 return 600
#else #else
return 320 return 320
#endif #endif
} }
var adaptiveGridItemMaximumSize: Double {
#if os(tvOS)
return 600
#else
return .infinity
#endif
}
var scrollViewShowsIndicators: Bool { var scrollViewShowsIndicators: Bool {
#if !os(tvOS) #if !os(tvOS)
true true
@ -57,7 +66,7 @@ struct VerticalCells: View {
struct VeticalCells_Previews: PreviewProvider { struct VeticalCells_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
VerticalCells(items: ContentItem.array(of: Video.allFixtures)) VerticalCells(items: ContentItem.array(of: Array(repeating: Video.fixture, count: 30)))
.injectFixtureEnvironmentObjects() .injectFixtureEnvironmentObjects()
} }
} }

View File

@ -9,7 +9,8 @@ final class IntFormatTests: XCTestCase {
1101: "1,1K", 1101: "1,1K",
12345: "12,3K", 12345: "12,3K",
123_456: "123,5K", 123_456: "123,5K",
123_626_789: "123,6M" 123_626_789: "123,6M",
1_331_211_123: "1,3B"
] ]
samples.forEach { value, formatted in samples.forEach { value, formatted in

View File

@ -182,6 +182,7 @@
3765917C27237D21009F956E /* PINCache in Frameworks */ = {isa = PBXBuildFile; productRef = 3765917B27237D21009F956E /* PINCache */; }; 3765917C27237D21009F956E /* PINCache in Frameworks */ = {isa = PBXBuildFile; productRef = 3765917B27237D21009F956E /* PINCache */; };
3765917E27237D2A009F956E /* PINCache in Frameworks */ = {isa = PBXBuildFile; productRef = 3765917D27237D2A009F956E /* PINCache */; }; 3765917E27237D2A009F956E /* PINCache in Frameworks */ = {isa = PBXBuildFile; productRef = 3765917D27237D2A009F956E /* PINCache */; };
37666BAA27023AF000F869E5 /* AccountSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37666BA927023AF000F869E5 /* AccountSelectionView.swift */; }; 37666BAA27023AF000F869E5 /* AccountSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37666BA927023AF000F869E5 /* AccountSelectionView.swift */; };
3766AFD2273DA97D00686348 /* Int+FormatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BA796D26DC412E002A0235 /* Int+FormatTests.swift */; };
376A33E02720CAD6000C1D6B /* VideosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376A33DF2720CAD6000C1D6B /* VideosApp.swift */; }; 376A33E02720CAD6000C1D6B /* VideosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376A33DF2720CAD6000C1D6B /* VideosApp.swift */; };
376A33E12720CAD6000C1D6B /* VideosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376A33DF2720CAD6000C1D6B /* VideosApp.swift */; }; 376A33E12720CAD6000C1D6B /* VideosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376A33DF2720CAD6000C1D6B /* VideosApp.swift */; };
376A33E22720CAD6000C1D6B /* VideosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376A33DF2720CAD6000C1D6B /* VideosApp.swift */; }; 376A33E22720CAD6000C1D6B /* VideosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376A33DF2720CAD6000C1D6B /* VideosApp.swift */; };
@ -2044,6 +2045,7 @@
3774123327387CB000423605 /* Defaults.swift in Sources */, 3774123327387CB000423605 /* Defaults.swift in Sources */,
3774123527387CC700423605 /* PipedAPI.swift in Sources */, 3774123527387CC700423605 /* PipedAPI.swift in Sources */,
3774124E27387D2300423605 /* Playlist.swift in Sources */, 3774124E27387D2300423605 /* Playlist.swift in Sources */,
3766AFD2273DA97D00686348 /* Int+FormatTests.swift in Sources */,
3774124F27387D2300423605 /* SubscriptionsModel.swift in Sources */, 3774124F27387D2300423605 /* SubscriptionsModel.swift in Sources */,
3774126127387D2D00423605 /* AccountsModel.swift in Sources */, 3774126127387D2D00423605 /* AccountsModel.swift in Sources */,
); );