2023-01-26 16:22:18 +01:00
|
|
|
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
|
|
|
|
|
|
|
import SwiftUI
|
|
|
|
import WidgetKit
|
2023-01-30 11:21:04 +01:00
|
|
|
import MastodonAsset
|
2023-02-06 12:13:29 +01:00
|
|
|
import MastodonLocalization
|
2023-02-07 08:17:00 +01:00
|
|
|
import LightChart
|
2023-01-26 16:22:18 +01:00
|
|
|
|
2023-01-31 11:43:45 +01:00
|
|
|
struct FollowersCountWidgetView: View {
|
2023-01-30 15:28:16 +01:00
|
|
|
private let followersHistory = FollowersCountHistory.shared
|
|
|
|
|
2023-01-26 16:22:18 +01:00
|
|
|
@Environment(\.widgetFamily) var family
|
|
|
|
|
2023-01-31 11:43:45 +01:00
|
|
|
var entry: FollowersCountWidgetProvider.Entry
|
2023-01-26 16:22:18 +01:00
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
if let account = entry.account {
|
|
|
|
switch family {
|
|
|
|
case .systemSmall:
|
2023-01-30 11:21:04 +01:00
|
|
|
if let showChart = entry.configuration.showChart?.boolValue, showChart {
|
|
|
|
viewForSmallWidgetYesChart(account)
|
|
|
|
} else {
|
|
|
|
viewForSmallWidgetNoChart(account)
|
|
|
|
}
|
2023-01-26 16:22:18 +01:00
|
|
|
case .accessoryRectangular:
|
|
|
|
viewForAccessoryRectangular(account)
|
|
|
|
case .accessoryCircular:
|
|
|
|
viewForAccessoryCircular(account)
|
|
|
|
default:
|
2023-02-06 12:13:29 +01:00
|
|
|
Text(L10n.Widget.Common.unsupportedWidgetFamily)
|
2023-01-26 16:22:18 +01:00
|
|
|
}
|
|
|
|
} else {
|
2023-02-06 12:13:29 +01:00
|
|
|
Text(L10n.Widget.Common.userNotLoggedIn)
|
2023-01-26 16:22:18 +01:00
|
|
|
.multilineTextAlignment(.center)
|
|
|
|
.font(.caption)
|
|
|
|
.padding(.all, 20)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-30 11:21:04 +01:00
|
|
|
private func viewForSmallWidgetNoChart(_ account: FollowersEntryAccountable) -> some View {
|
2023-01-26 16:22:18 +01:00
|
|
|
HStack {
|
|
|
|
VStack(alignment: .leading, spacing: 0) {
|
2023-03-01 14:58:12 +01:00
|
|
|
Image(uiImage: account.avatarImage)
|
|
|
|
.resizable()
|
|
|
|
.frame(width: 50, height: 50)
|
|
|
|
.cornerRadius(12)
|
|
|
|
.padding(.bottom, 8)
|
|
|
|
|
2023-01-26 16:22:18 +01:00
|
|
|
Text(account.followersCount.asAbbreviatedCountString())
|
|
|
|
.font(.largeTitle)
|
|
|
|
.lineLimit(1)
|
|
|
|
.truncationMode(.tail)
|
|
|
|
|
|
|
|
Text(account.displayNameWithFallback)
|
2023-02-06 11:58:23 +01:00
|
|
|
.font(.system(size: UIFontMetrics.default.scaledValue(for: 13)))
|
2023-01-26 16:22:18 +01:00
|
|
|
.lineLimit(1)
|
|
|
|
.truncationMode(.tail)
|
|
|
|
|
|
|
|
Text("@\(account.acct)")
|
|
|
|
.font(.caption2)
|
|
|
|
.foregroundColor(.secondary)
|
|
|
|
.lineLimit(1)
|
|
|
|
.truncationMode(.tail)
|
|
|
|
}
|
|
|
|
.padding(.leading, 20)
|
2023-01-30 11:21:04 +01:00
|
|
|
.padding(.vertical, 16)
|
2023-01-26 16:22:18 +01:00
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-30 11:21:04 +01:00
|
|
|
private func viewForSmallWidgetYesChart(_ account: FollowersEntryAccountable) -> some View {
|
|
|
|
VStack(alignment: .leading, spacing: 0) {
|
|
|
|
HStack {
|
2023-03-01 14:58:12 +01:00
|
|
|
Image(uiImage: account.avatarImage)
|
|
|
|
.resizable()
|
|
|
|
.frame(width: 23, height: 23)
|
|
|
|
.cornerRadius(5)
|
2023-01-30 11:21:04 +01:00
|
|
|
VStack(alignment: .leading) {
|
|
|
|
Text(account.displayNameWithFallback)
|
|
|
|
.font(.caption)
|
|
|
|
.lineLimit(1)
|
|
|
|
.truncationMode(.tail)
|
|
|
|
|
|
|
|
Text("@\(account.acct)")
|
|
|
|
.font(.caption2)
|
|
|
|
.foregroundColor(.secondary)
|
|
|
|
.lineLimit(1)
|
|
|
|
.truncationMode(.tail)
|
|
|
|
}
|
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
.padding(.leading, 20)
|
|
|
|
|
|
|
|
ZStack {
|
2023-01-30 15:28:16 +01:00
|
|
|
if let account = entry.account {
|
|
|
|
LightChartView(
|
|
|
|
data: followersHistory.chartValues(for: account),
|
|
|
|
type: .line,
|
|
|
|
visualType: .filled(color: Asset.Colors.Brand.blurple.swiftUIColor, lineWidth: 2),
|
|
|
|
offset: 0.8 /// this is the positive offset from the bottom edge of the graph (~80% above bottom level)
|
|
|
|
)
|
|
|
|
}
|
2023-01-30 11:21:04 +01:00
|
|
|
|
|
|
|
HStack {
|
|
|
|
VStack(alignment: .leading, spacing: 0) {
|
|
|
|
Spacer()
|
2023-01-30 15:28:16 +01:00
|
|
|
if let increaseCount = followersHistory.increaseCountString(for: account) {
|
2023-02-06 12:13:29 +01:00
|
|
|
Text(L10n.Widget.FollowersCount.followersToday(increaseCount))
|
2023-02-06 11:58:23 +01:00
|
|
|
.font(.system(size: UIFontMetrics.default.scaledValue(for: 12)))
|
2023-01-30 15:28:16 +01:00
|
|
|
.foregroundColor(.secondary)
|
|
|
|
.lineLimit(1)
|
|
|
|
.truncationMode(.tail)
|
|
|
|
}
|
2023-01-30 11:21:04 +01:00
|
|
|
|
|
|
|
Text(account.followersCount.asAbbreviatedCountString())
|
|
|
|
.font(.largeTitle)
|
|
|
|
.lineLimit(1)
|
|
|
|
.truncationMode(.tail)
|
|
|
|
|
|
|
|
}
|
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
.padding(.bottom, 16)
|
|
|
|
.padding(.leading, 20)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.padding(.top, 16)
|
|
|
|
}
|
|
|
|
|
2023-05-02 18:44:20 +02:00
|
|
|
private func viewForAccessoryRectangular(_ account: FollowersEntryAccountable) -> some View {
|
2023-01-26 16:22:18 +01:00
|
|
|
HStack(spacing: 0) {
|
|
|
|
VStack(alignment: .leading, spacing: 0) {
|
|
|
|
HStack(alignment: .center) {
|
|
|
|
Image("BrandIcon")
|
2023-02-06 12:13:29 +01:00
|
|
|
Text(L10n.Widget.FollowersCount.title)
|
2023-02-06 11:58:23 +01:00
|
|
|
.font(.system(size: UIFontMetrics.default.scaledValue(for: 15), weight: .semibold))
|
2023-01-26 16:22:18 +01:00
|
|
|
}
|
|
|
|
.padding(.top, 6)
|
|
|
|
|
|
|
|
Text(account.followersCount.asAbbreviatedCountString())
|
2023-02-06 11:58:23 +01:00
|
|
|
.font(.system(size: UIFontMetrics.default.scaledValue(for: 43)))
|
2023-01-26 16:22:18 +01:00
|
|
|
.lineLimit(1)
|
|
|
|
.truncationMode(.tail)
|
|
|
|
}
|
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private func viewForAccessoryCircular(_ account :FollowersEntryAccountable) -> some View {
|
|
|
|
ZStack {
|
|
|
|
if #available(iOS 16, *) {
|
|
|
|
AccessoryWidgetBackground()
|
|
|
|
}
|
|
|
|
VStack {
|
|
|
|
Image("BrandIcon")
|
|
|
|
|
|
|
|
Text(account.followersCount.asAbbreviatedCountString())
|
2023-02-06 11:58:23 +01:00
|
|
|
.font(.system(size: UIFontMetrics.default.scaledValue(for: 15)))
|
2023-01-26 16:22:18 +01:00
|
|
|
.lineLimit(1)
|
|
|
|
.truncationMode(.tail)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|