mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-22 00:11:00 +00:00
Add followers count widget
This commit is contained in:
parent
1578896b3e
commit
f40aeb9cac
5 changed files with 137 additions and 0 deletions
|
@ -89,6 +89,9 @@
|
|||
9F7788F02BE78E77004E6BEF /* Timeline in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7788EF2BE78E77004E6BEF /* Timeline */; };
|
||||
9F7D93942980063100EE6B7A /* AppAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7D93932980063100EE6B7A /* AppAccount */; };
|
||||
9F7D939A29805DBD00EE6B7A /* AccountSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7D939929805DBD00EE6B7A /* AccountSettingView.swift */; };
|
||||
9F8B92122BF77DBE003D37A2 /* AccountWidgetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F8B920E2BF77DB4003D37A2 /* AccountWidgetConfiguration.swift */; };
|
||||
9F8B92132BF77DBE003D37A2 /* AccountWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F8B92102BF77DBB003D37A2 /* AccountWidget.swift */; };
|
||||
9F8B92162BF77F0B003D37A2 /* AccountWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F8B92142BF77F05003D37A2 /* AccountWidgetView.swift */; };
|
||||
9FA6FD6229C04A8800E2312C /* TranslationSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FA6FD6129C04A8800E2312C /* TranslationSettingsView.swift */; };
|
||||
9FAD858B29743F7400496AB1 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FAD858A29743F7400496AB1 /* ShareViewController.swift */; };
|
||||
9FAD858E29743F7400496AB1 /* (null) in Resources */ = {isa = PBXBuildFile; };
|
||||
|
@ -275,6 +278,9 @@
|
|||
9F7788EC2BE78D75004E6BEF /* TimelineFilterEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineFilterEntity.swift; sourceTree = "<group>"; };
|
||||
9F7D939529800B0300EE6B7A /* IceCubesApp-release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "IceCubesApp-release.xcconfig"; sourceTree = "<group>"; };
|
||||
9F7D939929805DBD00EE6B7A /* AccountSettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSettingView.swift; sourceTree = "<group>"; };
|
||||
9F8B920E2BF77DB4003D37A2 /* AccountWidgetConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountWidgetConfiguration.swift; sourceTree = "<group>"; };
|
||||
9F8B92102BF77DBB003D37A2 /* AccountWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountWidget.swift; sourceTree = "<group>"; };
|
||||
9F8B92142BF77F05003D37A2 /* AccountWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountWidgetView.swift; sourceTree = "<group>"; };
|
||||
9FA6FD6129C04A8800E2312C /* TranslationSettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranslationSettingsView.swift; sourceTree = "<group>"; };
|
||||
9FAD858829743F7400496AB1 /* IceCubesShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = IceCubesShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9FAD858A29743F7400496AB1 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -497,6 +503,7 @@
|
|||
9F7788CA2BE652B1004E6BEF /* IceCubesAppWidgetsExtension */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9F8B920D2BF77DA8003D37A2 /* AccountWidget */,
|
||||
9F5BE6202BF48FB20074387E /* ListsWidget */,
|
||||
9FF2FB6B2BE8AE78001560CE /* MentionWidget */,
|
||||
9FF2FB642BE7F7FA001560CE /* Shared */,
|
||||
|
@ -510,6 +517,16 @@
|
|||
path = IceCubesAppWidgetsExtension;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9F8B920D2BF77DA8003D37A2 /* AccountWidget */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9F8B920E2BF77DB4003D37A2 /* AccountWidgetConfiguration.swift */,
|
||||
9F8B92102BF77DBB003D37A2 /* AccountWidget.swift */,
|
||||
9F8B92142BF77F05003D37A2 /* AccountWidgetView.swift */,
|
||||
);
|
||||
path = AccountWidget;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9FA0D2AC29921C1F008A143B /* Embeds */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1011,6 +1028,9 @@
|
|||
9F5BE6272BF492CF0074387E /* ListEntity.swift in Sources */,
|
||||
9FF2FB622BE7F5D5001560CE /* HashtagPostsWidget.swift in Sources */,
|
||||
9FF2FB712BE8AEA0001560CE /* MentionWidget.swift in Sources */,
|
||||
9F8B92162BF77F0B003D37A2 /* AccountWidgetView.swift in Sources */,
|
||||
9F8B92122BF77DBE003D37A2 /* AccountWidgetConfiguration.swift in Sources */,
|
||||
9F8B92132BF77DBE003D37A2 /* AccountWidget.swift in Sources */,
|
||||
9F7788EA2BE65585004E6BEF /* AppAccountEntity.swift in Sources */,
|
||||
9FF2FB6A2BE7F84E001560CE /* SharedUtils.swift in Sources */,
|
||||
9F7788CE2BE652B1004E6BEF /* LatestPostsWidget.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
import DesignSystem
|
||||
import Models
|
||||
import Network
|
||||
import SwiftUI
|
||||
import Timeline
|
||||
import WidgetKit
|
||||
|
||||
struct AccountWidgetProvider: AppIntentTimelineProvider {
|
||||
func placeholder(in _: Context) -> AccountWidgetEntry {
|
||||
.init(date: Date(), account: .placeholder(), avatar: nil)
|
||||
}
|
||||
|
||||
func snapshot(for configuration: AccountWidgetConfiguration, in context: Context) async -> AccountWidgetEntry {
|
||||
let account = await fetchAccount(configuration: configuration)
|
||||
return .init(date: Date(), account: account, avatar: nil)
|
||||
}
|
||||
|
||||
func timeline(for configuration: AccountWidgetConfiguration, in context: Context) async -> Timeline<AccountWidgetEntry> {
|
||||
let account = await fetchAccount(configuration: configuration)
|
||||
let images = try? await loadImages(urls: [account.avatar])
|
||||
return .init(entries: [.init(date: Date(), account: account, avatar: images?.first?.value)],
|
||||
policy: .atEnd)
|
||||
}
|
||||
|
||||
private func fetchAccount(configuration: AccountWidgetConfiguration) async -> Account {
|
||||
let client = Client(server: configuration.account.account.server,
|
||||
oauthToken: configuration.account.account.oauthToken)
|
||||
do {
|
||||
let account: Account = try await client.get(endpoint: Accounts.verifyCredentials)
|
||||
return account
|
||||
} catch {
|
||||
return .placeholder()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AccountWidgetEntry: TimelineEntry {
|
||||
let date: Date
|
||||
let account: Account
|
||||
let avatar: UIImage?
|
||||
}
|
||||
|
||||
struct AccountWidget: Widget {
|
||||
let kind: String = "AccountWidget"
|
||||
|
||||
var body: some WidgetConfiguration {
|
||||
AppIntentConfiguration(kind: kind,
|
||||
intent: AccountWidgetConfiguration.self,
|
||||
provider: AccountWidgetProvider())
|
||||
{ entry in
|
||||
AccountWidgetView(entry: entry)
|
||||
.containerBackground(Color("WidgetBackground").gradient, for: .widget)
|
||||
}
|
||||
.configurationDisplayName("Account")
|
||||
.description("Show information about your Mastodon account")
|
||||
.supportedFamilies([.systemSmall])
|
||||
}
|
||||
}
|
||||
|
||||
#Preview(as: .systemSmall) {
|
||||
AccountWidget()
|
||||
} timeline: {
|
||||
AccountWidgetEntry(date: Date(), account: .placeholder(), avatar: nil)
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import AppIntents
|
||||
import WidgetKit
|
||||
|
||||
struct AccountWidgetConfiguration: WidgetConfigurationIntent {
|
||||
static let title: LocalizedStringResource = "Configuration"
|
||||
static let description = IntentDescription("Choose the account for this widget")
|
||||
|
||||
@Parameter(title: "Account")
|
||||
var account: AppAccountEntity
|
||||
}
|
||||
|
||||
extension AccountWidgetConfiguration {
|
||||
static var previewAccount: AccountWidgetConfiguration {
|
||||
let intent = AccountWidgetConfiguration()
|
||||
intent.account = .init(account: .init(server: "Test", accountName: "Test account"))
|
||||
return intent
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import DesignSystem
|
||||
import Models
|
||||
import Network
|
||||
import SwiftUI
|
||||
import Timeline
|
||||
import WidgetKit
|
||||
|
||||
struct AccountWidgetView: View {
|
||||
var entry: AccountWidgetProvider.Entry
|
||||
|
||||
@Environment(\.widgetFamily) var family
|
||||
@Environment(\.redactionReasons) var redacted
|
||||
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .center, spacing: 4) {
|
||||
if let avatar = entry.avatar {
|
||||
Image(uiImage: avatar)
|
||||
.resizable()
|
||||
.frame(width: 64, height: 64)
|
||||
.clipShape(Circle())
|
||||
Text("\(entry.account.followersCount ?? 0)")
|
||||
.font(.title)
|
||||
.fontDesign(.rounded)
|
||||
.fontWeight(.bold)
|
||||
.monospacedDigit()
|
||||
Text("Followers")
|
||||
.font(.headline)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
|
@ -8,5 +8,6 @@ struct IceCubesAppWidgetsExtensionBundle: WidgetBundle {
|
|||
HashtagPostsWidget()
|
||||
ListsPostWidget()
|
||||
MentionsWidget()
|
||||
AccountWidget()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue